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    }