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.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 }