001 /*
002 * CDDL HEADER START
003 *
004 * The contents of this file are subject to the terms of the
005 * Common Development and Distribution License, Version 1.0 only
006 * (the "License"). You may not use this file except in compliance
007 * with the License.
008 *
009 * You can obtain a copy of the license at
010 * trunk/opends/resource/legal-notices/OpenDS.LICENSE
011 * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
012 * See the License for the specific language governing permissions
013 * and limitations under the License.
014 *
015 * When distributing Covered Code, include this CDDL HEADER in each
016 * file and include the License file at
017 * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable,
018 * add the following below this CDDL HEADER, with the fields enclosed
019 * by brackets "[]" replaced with your own identifying information:
020 * Portions Copyright [yyyy] [name of copyright owner]
021 *
022 * CDDL HEADER END
023 *
024 *
025 * Copyright 2006-2008 Sun Microsystems, Inc.
026 */
027 package org.opends.server.util;
028 import org.opends.messages.Message;
029
030 import static org.opends.server.loggers.debug.DebugLogger.*;
031 import org.opends.server.loggers.debug.DebugTracer;
032 import org.opends.server.loggers.ErrorLogger;
033
034 /**
035 * This utility class provides static methods that make parameter checking
036 * easier (e.g. in constructors and setters).
037 * In particular the ensureNotNull methods provide an easy way to validate that
038 * certain parameters are not null, and the ensureTrue methods provide the
039 * ability to check arbitrary boolean conditions.
040 * <p>
041 * Invocation of these methods should be limited to situations where the only
042 * way that they should fail is if there is a defect somewhere in the
043 * system (including 3rd-party plugins).
044 * <p>
045 * You can think of these methods as being similar to <code>assert</code>,
046 * but there are some additional advantages:
047 * <ul>
048 * <li>All failures are logged to the debug and error logs</li>
049 * <li>Checks are always enabled (even if asserts are off)</li>
050 * <li>This class tracks the number of failures, allowing it to
051 * be exposed via monitoring, etc.<li>
052 * <li>The unit tests can track unnoticed internal failures and
053 * report on them.</li>
054 * <li>Developers can catch all Validator failures with a single
055 * break point.</li>
056 * </ul>
057 *
058 * In general, you should not worry about the performance impact of calling
059 * these methods. Some micro-benchmarking has shown that ensureNotNull can be
060 * called 200M times per second on a single CPU laptop. The value of catching
061 * defects early will almost always out-weigh any overhead that is introduced.
062 * There are a couple of exceptions to this. Any execution overhead that
063 * happens before the method is invoked cannot be eliminated, e.g.
064 * <code>Validator.ensureTrue(someExpensiveCheck())</code> will always invoke
065 * <code>someExpensiveCheck()</code>. When this code is on the critical path,
066 * and we do not expect the validation to fail, you can guard the call with
067 * an <code>assert</code> because each method returns true, and this code will
068 * only be executed when asserts are enabled.
069 * <p>
070 * These methods are provided primarily to check parameter values for
071 * constructors, setters, etc, and when they are used in this way, the javadoc
072 * for the method must be updated to reflect what constraints are placed on the
073 * parameters (e.g. attributeType cannot be null).
074 * <p>
075 * Feel free to add any method to this class that makes sense. Be sure to
076 * ensure that they don't violate the spirit of this class in that performance
077 * is second only to correctness.
078 * <p>
079 * There are a few issues open for remaining tasks:
080 * <ul>
081 * <li>757 Validator should expose a way to turn it off</li>
082 * <li>758 Validator should provide a way to throttle it's error messages</li>
083 * <li>759 Unit tests should always check that no unexpected Validator checks
084 * failed</li>
085 * </ul>
086 */
087 @org.opends.server.types.PublicAPI(
088 stability=org.opends.server.types.StabilityLevel.UNCOMMITTED,
089 mayInstantiate=false,
090 mayExtend=false,
091 mayInvoke=true)
092 public class Validator {
093 /**
094 * The tracer object for the debug logger.
095 */
096 private static final DebugTracer TRACER = getTracer();
097
098 /** This static final variable theoretically allows us to compile out all of
099 * these checks. Since all of the code below is guarded with this check,
100 * the compiler should eliminate it if ENABLE_CHECKS is false.
101 * From doing a little bit of micro-benchmarking, it appears that setting
102 * ENABLE_CHECKS=false speeds the code up by about a factor of four, but
103 * it's still not the same as not having the invocation in the first place.
104 * On a single CPU laptop, I was able to get 200M
105 * invocations per second with ENABLE_CHECKS=true, and 350M with
106 * ENABLE_CHECKS=false.
107 * <p>
108 * Setting this to false, will not eliminate any expensive computation
109 * done in a parameter list (e.g. some self-check that returns true).*/
110 public static final boolean ENABLE_CHECKS = true;
111
112
113
114
115 /** A one-based array for parameter descriptions. */
116 private static final String[] PARAM_DESCRIPTIONS =
117 {"** A ZERO-BASED INDEX IS INVALID **",
118 "(1st parameter)",
119 "(2nd parameter)",
120 "(3rd parameter)",
121 "(4th parameter)",
122 "(5th parameter)",
123 "(6th parameter)",
124 "(7th parameter)",
125 "(8th parameter)",
126 "(9th parameter)",
127 "(10th parameter)"};
128
129 /** A count of the errors detected by the methods in this class since the
130 * last time that resetErrorCount was called. */
131 private static long _errorCount = 0;
132
133
134 /**
135 * This method validates that the specified parameter is not null. It
136 * throws an AssertionError if it is null after logging this error.
137 * <p>
138 * This should be used like an assert, except it is not turned
139 * off at runtime. That is, it should only be used in situations where
140 * there is a bug in someone's code if param is null.
141 *
142 * @param param the parameter to validate as non-null.
143 * @return true always. This allows this call to be used in an assert
144 * statement, which can skip this check and remove all
145 * overhead from the calling code. This idiom should only be used when
146 * performance testing proves that it is necessary.
147 *
148 * @throws AssertionError if and only if param is null
149 * if assertions are enabled
150 */
151 public static boolean ensureNotNull(Object param)
152 throws AssertionError {
153 if (ENABLE_CHECKS) {
154 if (param == null) throwNull("");
155 }
156 return true;
157 }
158
159
160
161 /**
162 * This method validates that the specified parameters are not null. It
163 * throws an AssertionError if one of them are null after logging this error.
164 * It's similar to the ensureNotNull(Object) call except it provides the
165 * convenience of checking two parameters at once.
166 * <p>
167 * This should be used like an assert, except it is not turned
168 * off at runtime. That is, it should only be used in situations where
169 * there is a bug in someone's code if param is null.
170 * <p>
171 * See the class level javadoc for why we did not use varargs to
172 * implement this method.
173 *
174 * @param param1 the first parameter to validate as non-null.
175 * @param param2 the second parameter to validate as non-null.
176 * @return true always. This allows this call to be used in an assert
177 * statement, which can skip this check and remove all
178 * overhead from the calling code. This idiom should only be used when
179 * performance testing proves that it is necessary.
180 *
181 * @throws AssertionError if and only if any of the parameters is null
182 */
183 public static boolean ensureNotNull(Object param1, Object param2)
184 throws AssertionError {
185 if (ENABLE_CHECKS) {
186 if (param1 == null) throwNull(PARAM_DESCRIPTIONS[1]);
187 if (param2 == null) throwNull(PARAM_DESCRIPTIONS[2]);
188 }
189 return true;
190 }
191
192
193
194 /**
195 * This method validates that the specified parameters are not null. It
196 * throws an AssertionError if one of them are null after logging this error.
197 * It's similar to the ensureNotNull(Object) call except it provides the
198 * convenience of checking three parameters at once.
199 * <p>
200 * This should be used like an assert, except it is not turned
201 * off at runtime. That is, it should only be used in situations where
202 * there is a bug in someone's code if param is null.
203 * <p>
204 * See the class level javadoc for why we did not use varargs to
205 * implement this method.
206 *
207 * @param param1 the first parameter to validate as non-null.
208 * @param param2 the second parameter to validate as non-null.
209 * @param param3 the third parameter to validate as non-null.
210 * @return true always. This allows this call to be used in an assert
211 * statement, which can skip this check and remove all
212 * overhead from the calling code. This idiom should only be used when
213 * performance testing proves that it is necessary.
214 *
215 * @throws AssertionError if and only if one of the parameters is null
216 */
217 public static boolean ensureNotNull(Object param1, Object param2,
218 Object param3)
219 throws AssertionError {
220 if (ENABLE_CHECKS) {
221 if (param1 == null) throwNull(PARAM_DESCRIPTIONS[1]);
222 if (param2 == null) throwNull(PARAM_DESCRIPTIONS[2]);
223 if (param3 == null) throwNull(PARAM_DESCRIPTIONS[3]);
224 }
225 return true;
226 }
227
228
229
230 /**
231 * This method validates that the specified parameters are not null. It
232 * throws an AssertionError if one of them are null after logging this error.
233 * It's similar to the ensureNotNull(Object) call except it provides the
234 * convenience of checking four parameters at once.
235 * <p>
236 * This should be used like an assert, except it is not turned
237 * off at runtime. That is, it should only be used in situations where
238 * there is a bug in someone's code if param is null.
239 * <p>
240 * See the class level javadoc for why we did not use varargs to
241 * implement this method.
242 *
243 * @param param1 the first parameter to validate as non-null.
244 * @param param2 the second parameter to validate as non-null.
245 * @param param3 the third parameter to validate as non-null.
246 * @param param4 the fourth parameter to validate as non-null.
247 * @return true always. This allows this call to be used in an assert
248 * statement, which can skip this check and remove all
249 * overhead from the calling code. This idiom should only be used when
250 * performance testing proves that it is necessary.
251 *
252 * @throws AssertionError if and only if one of the parameters is null
253 */
254 public static boolean ensureNotNull(Object param1, Object param2,
255 Object param3, Object param4)
256 throws AssertionError {
257 if (ENABLE_CHECKS) {
258 if (param1 == null) throwNull(PARAM_DESCRIPTIONS[1]);
259 if (param2 == null) throwNull(PARAM_DESCRIPTIONS[2]);
260 if (param3 == null) throwNull(PARAM_DESCRIPTIONS[3]);
261 if (param4 == null) throwNull(PARAM_DESCRIPTIONS[4]);
262 }
263 return true;
264 }
265
266
267 /**
268 * This method validates that the specified parameter is true. It
269 * throws an AssertionError if it is not true.
270 * <p>
271 * This should be used like an assert, except it is not turned
272 * off at runtime. That is, it should only be used in situations where
273 * there is a bug in someone's code if param is null. The other advantage of
274 * using this method instead of an assert is that it logs the error to the
275 * debug and error logs.
276 *
277 * @param condition the condition that must be true.
278 * @return true always. This allows this call to be used in an assert
279 * statement, which can skip this check and remove all
280 * overhead from the calling code. This idiom should only be used when
281 * performance testing proves that it is necessary.
282 *
283 * @throws AssertionError if condition is false
284 */
285 public static boolean ensureTrue(boolean condition)
286 throws AssertionError {
287 if (ENABLE_CHECKS) {
288 if (!condition) {
289 ensureTrue(condition, "");
290 }
291 }
292 return true;
293 }
294
295
296
297 /**
298 * This method validates that the specified parameter is true. It
299 * throws an AssertionError if it is not true. The supplied message is
300 * included in the error message.
301 * <p>
302 * This should be used like an assert, except it is not turned
303 * off at runtime. That is, it should only be used in situations where
304 * there is a bug in someone's code if param is null. The other advantage of
305 * using this method instead of an assert is that it logs the error to the
306 * debug and error logs.
307 *
308 * @param condition the condition that must be true.
309 * @param message the textual message to include in the error message.
310 * @return true always. This allows this call to be used in an assert
311 * statement, which can skip this check and remove all
312 * overhead from the calling code. This idiom should only be used when
313 * performance testing proves that it is necessary.
314 *
315 * @throws AssertionError if condition is false
316 */
317 public static boolean ensureTrue(boolean condition, String message)
318 throws AssertionError {
319 if (ENABLE_CHECKS) {
320 if (!condition) {
321 StringBuilder mb = new StringBuilder();
322 mb.append("The specified condition must be true. ");
323 mb.append(message);
324 String fullString = generateLineSpecificErrorString(mb.toString());
325
326 logError(fullString);
327
328 throw new AssertionError(fullString);
329 }
330 }
331 return true;
332 }
333
334 ////////////////////////////////////////////////////////////////////////////
335 //
336 // ERROR COUNT
337 //
338 ////////////////////////////////////////////////////////////////////////////
339
340
341 /**
342 * Returns the number of errors that this class has detected since the
343 * system started or the last time that resetErrorCount() was called.
344 * <p>
345 * This could be useful in the unit tests to validate that no background
346 * errors occurred during a test. It could also be exposed by the monitoring
347 * framekwork.
348 *
349 * @return the number of errors detected by this class since the error count
350 * was last reset.
351 */
352 public static synchronized long getErrorCount() {
353 return _errorCount;
354 }
355
356
357 /**
358 * Resets the error count to zero.
359 */
360 public static synchronized void resetErrorCount() {
361 _errorCount = 0;
362 }
363
364
365 private static synchronized void incrementErrorCount() {
366 _errorCount++;
367 }
368
369
370 ////////////////////////////////////////////////////////////////////////////
371 //
372 // PRIVATE
373 //
374 ////////////////////////////////////////////////////////////////////////////
375
376
377 private static String generateLineSpecificErrorString(String message) {
378 StringBuilder mb = new StringBuilder();
379 mb.append(message);
380 mb.append(" The error occurred at ");
381 mb.append(getOriginalCallerLineInfo());
382 return mb.toString();
383 }
384
385
386 private static void throwNull(String message)
387 throws AssertionError {
388 StringBuilder mb = new StringBuilder();
389 mb.append("The specified parameter must not be null. ");
390 mb.append(message);
391 String fullString = generateLineSpecificErrorString(mb.toString());
392
393 logError(fullString);
394
395 throw new AssertionError(fullString);
396 }
397
398
399
400 private static void logError(String message) {
401 incrementErrorCount();
402
403 StringBuilder mb = new StringBuilder();
404 mb.append(message);
405 mb.append(ServerConstants.EOL);
406 mb.append(getCallingStack());
407 String messageWithStack = mb.toString();
408
409 // Log to the debug log.
410 if (debugEnabled())
411 {
412 TRACER.debugError(messageWithStack.toString());
413 }
414
415 // Log to the error log.
416 ErrorLogger.logError(Message.raw(messageWithStack));
417 }
418
419
420 /*
421 * @return a String representation of the line that called the
422 * Validator method.
423 */
424 private static String getOriginalCallerLineInfo() {
425 StackTraceElement stackElements[] = Thread.currentThread().getStackTrace();
426 int callerIndex = getOriginalCallerStackIndex(stackElements);
427 return stackElements[callerIndex].toString();
428 }
429
430
431 /*
432 * @return a stack trace rooted at the line that called the first
433 * Validator method.
434 */
435 private static String getCallingStack() {
436 StackTraceElement stackElements[] = Thread.currentThread().getStackTrace();
437 int callerIndex = getOriginalCallerStackIndex(stackElements);
438
439 StringBuilder buffer = new StringBuilder();
440 for (int i = callerIndex; i < stackElements.length; i++) {
441 StackTraceElement stackElement = stackElements[i];
442 buffer.append(stackElement).append(ServerConstants.EOL);
443 }
444
445 return buffer.toString();
446 }
447
448
449 /*
450 * @return the index in the supplied stack trace of the first non-Validator
451 * method.
452 */
453 private static int getOriginalCallerStackIndex(StackTraceElement stack[]) {
454 // Go up the stack until we find who called the first Validator method.
455 StackTraceElement element = null;
456 int i;
457 for (i = 0; i < stack.length; i++) {
458 element = stack[i];
459 // The stack trace of this thread looks like
460 // java.lang.Thread.dumpThreads(Native Method)
461 // java.lang.Thread.getStackTrace(Thread.java:1383)
462 // org.opends.server.util.Validator.getOriginalCallerLineInfo...
463 // ...
464 // original caller <---- this is what we want to return
465 // more stack
466 if (!element.getClassName().equals(Validator.class.getName()) &&
467 !element.getClassName().equals(Thread.class.getName())) {
468 break;
469 }
470 }
471
472 return i;
473 }
474 }