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 }