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.plugins;
17
18 import it.jnrpe.ICommandLine;
19 import it.jnrpe.ReturnValue;
20 import it.jnrpe.events.EventParam;
21 import it.jnrpe.events.EventsUtil;
22 import it.jnrpe.events.IJNRPEEventListener;
23 import it.jnrpe.events.LogEvent;
24 import it.jnrpe.utils.BadThresholdException;
25 import it.jnrpe.utils.thresholds.ReturnValueBuilder;
26 import it.jnrpe.utils.thresholds.ThresholdsEvaluatorBuilder;
27
28 import java.util.Collection;
29 import java.util.Collections;
30 import java.util.HashSet;
31 import java.util.Set;
32
33 /**
34 * This class facilitates the implementation of plugins. If you don't need to
35 * extend other classes, than extending {@link PluginBase} is the best way.
36 *
37 * This class gives you out of the box:
38 * <ul>
39 * <li>Logging through the {@link #log} variable.
40 * <li>Events: you can easily send events by using the sendEvent methods.
41 * <li>Threshold evaluation: by overriding the
42 * {@link #gatherMetrics(ICommandLine)} you can demand to this class all the
43 * work required to evaluate thresholds. If you use the new threshold syntax,
44 * all the configuration is done automatically. Otherwise you just have to
45 * override the
46 * {@link #configureThresholdEvaluatorBuilder(ThresholdsEvaluatorBuilder, ICommandLine)}
47 * to set the all the thresholds.
48 * </ul>
49 *
50 * @author Massimiliano Ziccardi
51 */
52 public abstract class PluginBase implements IPluginInterfaceEx {
53 /**
54 * The list of listener registered for the events raised by this plugin.
55 */
56 private final Set<IJNRPEEventListener> listenersSet = new HashSet<IJNRPEEventListener>();
57
58 /**
59 * The logger object.
60 */
61 protected final Logger log = new Logger();
62
63 /**
64 * This class represent a generic logger that will be used by plugins
65 * extending the {@link PluginBase} to write logs.
66 *
67 * @author Massimiliano Ziccardi
68 *
69 */
70 protected class Logger {
71
72 /**
73 * Writes a trace message.
74 *
75 * @param message
76 * the message
77 */
78 public final void trace(final String message) {
79 EventsUtil.sendEvent(listenersSet, PluginBase.this, LogEvent.TRACE,
80 message);
81 }
82
83 /**
84 * Writes a trace message and logs the exception.
85 *
86 * @param message
87 * the message
88 * @param exc
89 * the exception to be logged
90 */
91 public final void trace(final String message, final Throwable exc) {
92 EventsUtil.sendEvent(listenersSet, PluginBase.this, LogEvent.TRACE,
93 message, exc);
94 }
95
96 /**
97 * Writes a debug message.
98 *
99 * @param message
100 * the message
101 */
102 public final void debug(final String message) {
103 EventsUtil.sendEvent(listenersSet, PluginBase.this, LogEvent.DEBUG,
104 message);
105 }
106
107 /**
108 * Writes a debug message and logs the exception.
109 *
110 * @param message
111 * the message
112 * @param exc
113 * the exception to be logged
114 */
115 public final void debug(final String message, final Throwable exc) {
116 EventsUtil.sendEvent(listenersSet, PluginBase.this, LogEvent.DEBUG,
117 message, exc);
118 }
119
120 /**
121 * Writes an info message.
122 *
123 * @param message
124 * the message
125 */
126 public final void info(final String message) {
127 EventsUtil.sendEvent(listenersSet, PluginBase.this, LogEvent.INFO,
128 message);
129 }
130
131 /**
132 * Writes an info message and logs the exception.
133 *
134 * @param message
135 * the message
136 * @param exc
137 * the exception to be logged
138 */
139 public final void info(final String message, final Throwable exc) {
140 EventsUtil.sendEvent(listenersSet, PluginBase.this, LogEvent.INFO,
141 message, exc);
142 }
143
144 /**
145 * Writes a warning message.
146 *
147 * @param message
148 * the message
149 */
150 public final void warn(final String message) {
151 EventsUtil.sendEvent(listenersSet, PluginBase.this,
152 LogEvent.WARNING, message);
153 }
154
155 /**
156 * Writes a warning message and logs the exception.
157 *
158 * @param message
159 * the message
160 * @param exc
161 * the exception to be logged
162 */
163 public final void warn(final String message, final Throwable exc) {
164 EventsUtil.sendEvent(listenersSet, PluginBase.this,
165 LogEvent.WARNING, message, exc);
166 }
167
168 /**
169 * Writes an error message.
170 *
171 * @param message
172 * the message
173 */
174 public final void error(final String message) {
175 EventsUtil.sendEvent(listenersSet, PluginBase.this, LogEvent.ERROR,
176 message);
177 }
178
179 /**
180 * Writes an error message and logs the exception.
181 *
182 * @param message
183 * the message
184 * @param exc
185 * the exception to be logged
186 */
187 public final void error(final String message, final Throwable exc) {
188 EventsUtil.sendEvent(listenersSet, PluginBase.this, LogEvent.ERROR,
189 message, exc);
190 }
191
192 /**
193 * Writes a fatal message.
194 *
195 * @param message
196 * the message
197 */
198 public final void fatal(final String message) {
199 EventsUtil.sendEvent(listenersSet, PluginBase.this, LogEvent.FATAL,
200 message);
201 }
202
203 /**
204 * Writes a fatal message and logs the exception.
205 *
206 * @param message
207 * the message
208 * @param exc
209 * the exception to be logged
210 */
211 public final void fatal(final String message, final Throwable exc) {
212 EventsUtil.sendEvent(listenersSet, PluginBase.this, LogEvent.FATAL,
213 message, exc);
214 }
215 }
216
217 /**
218 * Adds a new listener to the list of objects that will receive the messages
219 * sent by this class.
220 *
221 * @param listener
222 * The new listener
223 */
224 public final void addListener(final IJNRPEEventListener listener) {
225 listenersSet.add(listener);
226 }
227
228 /**
229 * Adds a new collection of listeners.
230 *
231 * @param listeners
232 * The collection of listeners to be added
233 */
234 public final void addListeners(
235 final Collection<IJNRPEEventListener> listeners) {
236 if (listeners == null) {
237 return;
238 }
239
240 listenersSet.addAll(listeners);
241 }
242
243 /**
244 * Sends an event.
245 *
246 * @param evt
247 * The event type
248 * @param message
249 * The message
250 */
251 public final void sendEvent(final LogEvent evt, final String message) {
252 EventsUtil.sendEvent(listenersSet, this, evt, message);
253 }
254
255 /**
256 * Sends an event.
257 *
258 * @param evt
259 * The event type
260 * @param message
261 * The message
262 * @param exc
263 * The exception to be attached to the event
264 */
265 public final void sendEvent(final LogEvent evt, final String message,
266 final Exception exc) {
267 EventsUtil.sendEvent(listenersSet, this, evt, message, exc);
268 }
269
270 /**
271 * Sends a custom event.
272 *
273 * @param customEventName
274 * The custom event identifier
275 * @param paramsAry
276 * The parameter of the event. Can be null.
277 */
278 public final void sendEvent(final String customEventName,
279 final EventParam... paramsAry) {
280 EventsUtil.sendEvent(listenersSet, this, customEventName, paramsAry);
281 }
282
283 /**
284 * @return the friendly name of this plugins.
285 */
286 protected abstract String getPluginName();
287
288 /**
289 * Returns all the registered listeners.
290 *
291 * @return All the listeners
292 */
293 protected final Set<IJNRPEEventListener> getListeners() {
294 return listenersSet;
295 }
296
297 /**
298 * Override this method if you don't use the new threshold syntax. Here you
299 * must tell the threshold evaluator all the threshold it must be able to
300 * evaluate. Give a look at the source of the CheckOracle plugin for an
301 * example of a plugin that supports both old and new syntax.
302 *
303 * @param thrb
304 * The {@link ThresholdsEvaluatorBuilder} object to be configured
305 * @param cl
306 * The command line
307 * @throws BadThresholdException
308 * -
309 */
310 public void configureThresholdEvaluatorBuilder(
311 final ThresholdsEvaluatorBuilder thrb, final ICommandLine cl)
312 throws BadThresholdException {
313 if (cl.hasOption("th")) {
314 for (Object obj : cl.getOptionValues("th")) {
315 thrb.withThreshold(obj.toString());
316 }
317 }
318 }
319
320 /**
321 * This method must be overridden if you don't override the
322 * {@link #execute(ICommandLine)} method. This way you can demand all the
323 * work about evaluating the thresholds to this class.
324 *
325 * @param cl
326 * The command line.
327 * @return All the collected metrics
328 * @throws MetricGatheringException
329 * -
330 */
331 public Collection<Metric> gatherMetrics(final ICommandLine cl)
332 throws MetricGatheringException {
333 return Collections.emptyList();
334 }
335
336 /**
337 * Executes the plugin. You must override this method if you want total
338 * control about what the plugins does. Most of the times, however, you'll
339 * want to override the {@link #gatherMetrics(ICommandLine)} instead.
340 *
341 * @param cl
342 * The command line
343 * @return The return value to be sent to Nagios.
344 * @throws BadThresholdException
345 * -
346 */
347 public ReturnValue execute(final ICommandLine cl)
348 throws BadThresholdException {
349 ThresholdsEvaluatorBuilder thrb = new ThresholdsEvaluatorBuilder();
350 configureThresholdEvaluatorBuilder(thrb, cl);
351 ReturnValueBuilder builder = ReturnValueBuilder.forPlugin(
352 getPluginName(), thrb.create());
353
354 try {
355 Collection<Metric> metrics = gatherMetrics(cl);
356
357 for (Metric m : metrics) {
358 builder.withValue(m);
359 }
360
361 return builder.create();
362 } catch (MetricGatheringException mge) {
363 return ReturnValueBuilder.forPlugin(getPluginName())
364 .withForcedMessage(mge.getMessage())
365 .withStatus(mge.getStatus()).create();
366 }
367
368 }
369 }