View Javadoc

1   /*******************************************************************************
2    * Copyright (c) 2007, 2014 Massimiliano Ziccardi
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *     http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   *******************************************************************************/
16  package it.jnrpe.plugin.jmx;
17  
18  import it.jnrpe.Status;
19  import it.jnrpe.plugins.PluginBase;
20  
21  import java.io.BufferedReader;
22  import java.io.IOException;
23  import java.io.InputStream;
24  import java.io.InputStreamReader;
25  import java.io.PrintStream;
26  import java.util.HashMap;
27  import java.util.Iterator;
28  import java.util.Map;
29  
30  import javax.management.MBeanServerConnection;
31  import javax.management.ObjectName;
32  import javax.management.openmbean.CompositeDataSupport;
33  import javax.management.openmbean.CompositeType;
34  import javax.management.remote.JMXConnector;
35  import javax.management.remote.JMXConnectorFactory;
36  import javax.management.remote.JMXServiceURL;
37  
38  /**
39   *
40   * JMXQuery is used for local or remote request of JMX attributes It requires
41   * JRE 1.5 to be used for compilation and execution. Look method main for
42   * description how it can be invoked.
43   *
44   */
45  public abstract class JMXQuery extends PluginBase {
46  
47      private String url;
48      private int verbatim;
49      private JMXConnector connector;
50      private MBeanServerConnection connection;
51      private String warning, critical;
52      private String attribute, info_attribute;
53      private String attribute_key, info_key;
54      private String object;
55      private String username, password;
56  
57      private Object checkData;
58      private Object infoData;
59  
60      private static final String OK_STRING = "JMX OK -";
61      private static final String WARNING_STRING = "JMX WARNING -";
62      private static final String CRITICAL_STRING = "JMX CRITICAL -";
63      private static final int RETURN_UNKNOWN = 3; // Invalid command line
64                                                   // arguments were supplied to
65                                                   // the plugin or low-level
66                                                   // failures internal to the
67                                                   // plugin (such as unable to
68                                                   // fork, or open a tcp socket)
69                                                   // that prevent it from
70                                                   // performing the specified
71                                                   // operation. Higher-level
72                                                   // errors (such as name
73                                                   // resolution errors, socket
74                                                   // timeouts, etc) are outside
75                                                   // of the control of plugins
76                                                   // and should generally NOT be
77                                                   // reported as UNKNOWN states.
78      private static final String UNKNOWN_STRING = "JMX UNKNOWN";
79  
80      protected void connect() throws IOException {
81          JMXServiceURL jmxUrl = new JMXServiceURL(url);
82  
83          if (username != null) {
84              Map<String, String[]> m = new HashMap<String, String[]>();
85              m.put(JMXConnector.CREDENTIALS, new String[] { username, password });
86              connector = JMXConnectorFactory.connect(jmxUrl, m);
87          } else {
88              connector = JMXConnectorFactory.connect(jmxUrl);
89          }
90          connection = connector.getMBeanServerConnection();
91      }
92  
93      protected void disconnect() throws IOException {
94          if (connector != null) {
95              connector.close();
96              connector = null;
97          }
98      }
99  
100     // /**
101     // * @param args
102     // */
103     // public static void main(String[] args) {
104     //
105     // JMXQuery query = new JMXQuery();
106     // Status status;
107     // try{
108     // query.parse(args);
109     // query.connect();
110     // query.execute();
111     // status = query.report(System.out);
112     //
113     // }catch(Exception ex){
114     // status = query.report(ex, System.out);
115     // }finally{
116     // try {
117     // query.disconnect();
118     // } catch (IOException e) {
119     // status = query.report(e, System.out);
120     // }
121     // }
122     // System.exit(status.intValue());
123     // }
124 
125     protected Status report(Exception ex, PrintStream out) {
126         if (ex instanceof ParseError) {
127             out.print(UNKNOWN_STRING + " ");
128             reportException(ex, out);
129             out.println(" Usage: check_jmx -help ");
130             return Status.UNKNOWN;
131         } else {
132             out.print(CRITICAL_STRING + " ");
133             reportException(ex, out);
134             out.println();
135             return Status.CRITICAL;
136         }
137     }
138 
139     protected void reportException(Exception ex, PrintStream out) {
140 
141         if (verbatim < 2)
142             out.print(rootCause(ex).getMessage());
143         else {
144             out.print(ex.getMessage() + " connecting to " + object + " by URL "
145                     + url);
146         }
147 
148         if (verbatim >= 3)
149             ex.printStackTrace(out);
150 
151     }
152 
153     private static Throwable rootCause(Throwable ex) {
154         if (ex.getCause() == null)
155             return ex;
156         return rootCause(ex.getCause());
157     }
158 
159     protected Status report(PrintStream out) {
160         Status status;
161         if (compare(critical)) {
162             status = Status.CRITICAL;
163             out.print(CRITICAL_STRING);
164         } else if (compare(warning)) {
165             status = Status.WARNING;
166             out.print(WARNING_STRING);
167         } else {
168             status = Status.OK;
169             out.print(OK_STRING);
170         }
171 
172         boolean shown = false;
173         if (infoData == null || verbatim >= 2) {
174             out.print(' ');
175             if (attribute_key != null)
176                 out.print(attribute + '.' + attribute_key + " is " + checkData);
177             else {
178                 out.print(attribute + " is " + checkData);
179                 shown = true;
180             }
181 
182         }
183 
184         if (!shown && infoData != null) {
185             if (infoData instanceof CompositeDataSupport)
186                 report((CompositeDataSupport) infoData, out);
187             else
188                 out.print(infoData.toString());
189         }
190 
191         out.println();
192         return status;
193     }
194 
195     public String getUrl() {
196         return url;
197     }
198 
199     public void setUrl(String url) {
200         this.url = url;
201     }
202 
203     public int getVerbatim() {
204         return verbatim;
205     }
206 
207     public void setVerbatim(int verbatim) {
208         this.verbatim = verbatim;
209     }
210 
211     public String getWarning() {
212         return warning;
213     }
214 
215     public void setWarning(String warning) {
216         this.warning = warning;
217     }
218 
219     public String getCritical() {
220         return critical;
221     }
222 
223     public void setCritical(String critical) {
224         this.critical = critical;
225     }
226 
227     public String getAttribute() {
228         return attribute;
229     }
230 
231     public void setAttribute(String attribute) {
232         this.attribute = attribute;
233     }
234 
235     public String getInfo_attribute() {
236         return info_attribute;
237     }
238 
239     public void setInfo_attribute(String info_attribute) {
240         this.info_attribute = info_attribute;
241     }
242 
243     public String getAttribute_key() {
244         return attribute_key;
245     }
246 
247     public void setAttribute_key(String attribute_key) {
248         this.attribute_key = attribute_key;
249     }
250 
251     public String getInfo_key() {
252         return info_key;
253     }
254 
255     public void setInfo_key(String info_key) {
256         this.info_key = info_key;
257     }
258 
259     public String getObject() {
260         return object;
261     }
262 
263     public void setObject(String object) {
264         this.object = object;
265     }
266 
267     public String getUsername() {
268         return username;
269     }
270 
271     public void setUsername(String username) {
272         this.username = username;
273     }
274 
275     public String getPassword() {
276         return password;
277     }
278 
279     public void setPassword(String password) {
280         this.password = password;
281     }
282 
283     public Object getInfoData() {
284         return infoData;
285     }
286 
287     public void setInfoData(Object infoData) {
288         this.infoData = infoData;
289     }
290 
291     private void report(CompositeDataSupport data, PrintStream out) {
292         CompositeType type = data.getCompositeType();
293         out.print(",");
294         for (Iterator it = type.keySet().iterator(); it.hasNext();) {
295             String key = (String) it.next();
296             if (data.containsKey(key))
297                 out.print(key + '=' + data.get(key));
298             if (it.hasNext())
299                 out.print(';');
300         }
301     }
302 
303     private boolean compare(String level) {
304         if (checkData instanceof Number) {
305             Number check = (Number) checkData;
306             if (check.doubleValue() == Math.floor(check.doubleValue())) {
307                 return check.doubleValue() >= Double.parseDouble(level);
308             } else {
309                 return check.longValue() >= Long.parseLong(level);
310             }
311         }
312         if (checkData instanceof String) {
313             return checkData.equals(level);
314         }
315         if (checkData instanceof Boolean) {
316             return checkData.equals(Boolean.parseBoolean(level));
317         }
318         throw new RuntimeException(level
319                 + "is not of type Number,String or Boolean");
320     }
321 
322     protected void execute() throws Exception {
323         Object attr =
324                 connection.getAttribute(new ObjectName(object), attribute);
325         if (attr instanceof CompositeDataSupport) {
326             CompositeDataSupport cds = (CompositeDataSupport) attr;
327             if (attribute_key == null)
328                 throw new ParseError("Attribute key is null for composed data "
329                         + object);
330             checkData = cds.get(attribute_key);
331         } else {
332             checkData = attr;
333         }
334 
335         if (info_attribute != null) {
336             Object info_attr =
337                     info_attribute.equals(attribute) ? attr : connection
338                             .getAttribute(new ObjectName(object),
339                                     info_attribute);
340             if (info_key != null && (info_attr instanceof CompositeDataSupport)
341                     && verbatim < 4) {
342                 CompositeDataSupport cds = (CompositeDataSupport) attr;
343                 infoData = cds.get(info_key);
344             } else {
345                 infoData = info_attr;
346             }
347         }
348 
349     }
350 
351     private void parse(String[] args) throws ParseError {
352         try {
353             for (int i = 0; i < args.length; i++) {
354                 String option = args[i];
355                 if (option.equals("-help")) {
356                     printHelp(System.out);
357                     System.exit(RETURN_UNKNOWN);
358                 } else if (option.equals("-U")) {
359                     this.url = args[++i];
360                 } else if (option.equals("-O")) {
361                     this.object = args[++i];
362                 } else if (option.equals("-A")) {
363                     this.attribute = args[++i];
364                 } else if (option.equals("-I")) {
365                     this.info_attribute = args[++i];
366                 } else if (option.equals("-J")) {
367                     this.info_key = args[++i];
368                 } else if (option.equals("-K")) {
369                     this.attribute_key = args[++i];
370                 } else if (option.startsWith("-v")) {
371                     this.verbatim = option.length() - 1;
372                 } else if (option.equals("-w")) {
373                     this.warning = args[++i];
374                 } else if (option.equals("-c")) {
375                     this.critical = args[++i];
376                 } else if (option.equals("-username")) {
377                     this.username = args[++i];
378                 } else if (option.equals("-password")) {
379                     this.password = args[++i];
380                 }
381             }
382 
383             if (url == null || object == null || attribute == null)
384                 throw new Exception("Required options not specified");
385         } catch (Exception e) {
386             throw new ParseError(e);
387         }
388 
389     }
390 
391     private void printHelp(PrintStream out) {
392         InputStream is =
393                 JMXQuery.class.getClassLoader().getResourceAsStream(
394                         "jmxquery/HELP");
395         BufferedReader reader = new BufferedReader(new InputStreamReader(is));
396         try {
397             while (true) {
398                 String s = reader.readLine();
399                 if (s == null)
400                     break;
401                 out.println(s);
402             }
403         } catch (IOException e) {
404             out.println(e);
405         } finally {
406             try {
407                 reader.close();
408             } catch (IOException e) {
409                 out.println(e);
410             }
411         }
412     }
413 
414 }