001/** 002 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 003 * 004 * Copyright (c) 2006 Sun Microsystems Inc. All Rights Reserved 005 * 006 * The contents of this file are subject to the terms 007 * of the Common Development and Distribution License 008 * (the License). You may not use this file except in 009 * compliance with the License. 010 * 011 * You can obtain a copy of the License at 012 * https://opensso.dev.java.net/public/CDDLv1.0.html or 013 * opensso/legal/CDDLv1.0.txt 014 * See the License for the specific language governing 015 * permission and limitations under the License. 016 * 017 * When distributing Covered Code, include this CDDL 018 * Header Notice in each file and include the License file 019 * at opensso/legal/CDDLv1.0.txt. 020 * If applicable, add the following below the CDDL Header, 021 * with the fields enclosed by brackets [] replaced by 022 * your own identifying information: 023 * "Portions Copyrighted [year] [name of copyright owner]" 024 * 025 * $Id: Debug.java,v 1.6 2009/08/19 05:41:17 veiming Exp $ 026 * 027 * Portions Copyrighted 2013 Forgerock AS. 028 * 029 */ 030 031package com.sun.identity.shared.debug; 032 033import com.sun.identity.shared.configuration.SystemPropertiesManager; 034import com.sun.identity.shared.debug.impl.DebugProviderImpl; 035import java.util.Collection; 036import java.util.HashMap; 037import java.util.Map; 038import java.util.ResourceBundle; 039 040 041// NOTE: Since JVM specs guarantee atomic access/updates to int variables 042// (actually all variables except double and long), the design consciously 043// avoids synchronized methods, particularly for message(). This is done to 044// reduce the performance overhead of synchronized message() when debugging 045// is disabled. This does not have serious side-effects other than an occasional 046// invocation of message() missing concurrent update of 'debugLevel'. 047 048/******************************************************************************* 049 * <p> 050 * Allows a uniform interface to file debug and exception information in a 051 * uniform format. <code>Debug</code> supports different levels/states of 052 * filing debug information (in the ascending order): <code>OFF</code>, 053 * <code>ERROR</code>, <code>WARNING</code>, <code>MESSAGE</code> and 054 * <code>ON</code>. A given debug level/state is enabled if the debug 055 * state/level is set to at least that state/level. For example, if the debug 056 * state is <code>ERROR</code>, only errors will be filed. If the debug state 057 * is <code>WARNING</code>, only errors and warnings will be filed. If the 058 * debug state is <code>MESSAGE</code>, everything will be filed. 059 * <code>MESSAGE</code> and <code>ON</code> are of the same levels; the 060 * difference between them being <code>MESSAGE</code> writes to a file, 061 * whereas <code>ON</code> writes to System.out. 062 * </p> 063 * <p> 064 * Debug service uses the property file, <code>AMConfig.properties</code>, to 065 * set the default debug level and the output directory where the debug files 066 * will be placed. The properties file is located (using 067 * {@link java.util.ResourceBundle} semantics) from one of the directories in 068 * the CLASSPATH. 069 * </p> 070 * <p> 071 * The following keys are used to configure the Debug service. Possible values 072 * for the key 'com.iplanet.services.debug.level' are: off | error | warning | 073 * message. The key 'com.iplanet.services.debug.directory' specifies the output 074 * directory where the debug files will be created. Optionally, the key 075 * 'com.sun.identity.util.debug.provider' may be used to plugin a non-default 076 * implementation of the debug service where necessary. 077 * </p> 078 * 079 * <blockquote> 080 * 081 * <pre> 082 * com.iplanet.services.debug.level 083 * com.iplanet.services.debug.directory 084 * com.sun.identity.util.debug.provider 085 * </pre> 086 * 087 * </blockquote> 088 * 089 * If there is an error reading or loading the properties, Debug service will 090 * redirect all debug information to <code>System.out</code> 091 * 092 * If these properties are changed, the server must be restarted for the changes 093 * to take effect. 094 * 095 * <p> 096 * <b>NOTE:</b> Debugging is an IO intensive operation and may hurt application 097 * performance when abused. Particularly, note that Java evaluates the arguments 098 * to <code>message()</code> and <code>warning()</code> even when debugging 099 * is turned off. It is recommended that the debug state be checked before 100 * invoking any <code>message()</code> or <code>warning()</code> methods to 101 * avoid unnecessary argument evaluation and to maximize application 102 * performance. 103 * </p> 104 * @supported.all.api 105 */ 106public class Debug { 107 108 /* Static fields and methods */ 109 110 /** flags the disabled debug state. */ 111 public static final int OFF = 0; 112 113 /** 114 * flags the state where error debugging is enabled. When debugging is set 115 * to less than <code>ERROR</code>, error debugging is also disabled. 116 */ 117 public static final int ERROR = 1; 118 119 /** 120 * flags the state where warning debugging is enabled, but message debugging 121 * is disabled. When debugging is set to less than <code>WARNING</code>, 122 * warning debugging is also disabled. 123 */ 124 public static final int WARNING = 2; 125 126 /** This state enables debugging of messages, warnings and errors. */ 127 public static final int MESSAGE = 3; 128 129 /** 130 * flags the enabled debug state for warnings, errors and messages. Printing 131 * to a file is disabled. All printing is done on System.out. 132 */ 133 public static final int ON = 4; 134 135 /** flags the disabled debug state. */ 136 public static final String STR_OFF = "off"; 137 138 /** 139 * flags the state where error debugging is enabled. When debugging is set 140 * to less than <code>ERROR</code>, error debugging is also disabled. 141 */ 142 public static final String STR_ERROR = "error"; 143 144 /** 145 * flags the state where warning debugging is enabled, but message debugging 146 * is disabled. When debugging is set to less than <code>WARNING</code>, 147 * warning debugging is also disabled. 148 */ 149 public static final String STR_WARNING = "warning"; 150 151 /** This state enables debugging of messages, warnings and errors. */ 152 public static final String STR_MESSAGE = "message"; 153 154 /** 155 * flags the enables debug state for warnings, errors and messages. Printing 156 * to a file is disabled. All printing is done on System.out. 157 */ 158 public static final String STR_ON = "on"; 159 160 /** 161 * debugMap is a container of all active Debug objects. Log file name is the 162 * key and Debug is the value of this map. 163 */ 164 private static Map debugMap = new HashMap(); 165 166 /** 167 * serviceInitialized indicates if the service is already initialized. 168 */ 169 private static boolean serviceInitialized = false; 170 171 /** 172 * the provider instance that will be used for Debug service. 173 */ 174 private static IDebugProvider debugProvider; 175 176 /** 177 * Constant string used as property key to look up the debug provider class 178 * name. 179 */ 180 private static final String CONFIG_DEBUG_PROVIDER = 181 "com.sun.identity.util.debug.provider"; 182 183 /** 184 * Gets an existing instance of Debug for the specified debug name or a new 185 * one if no such instance already exists. If a Debug object has to be 186 * created, its level is set to the level defined in the 187 * <code>AMConfig.properties</code> file. The level can be changed later 188 * by using {@link #setDebug(int)} or {@link #setDebug(String)} methods. 189 * 190 * @param debugName 191 * name of the debug instances to be created 192 * @return a Debug instance corresponding to the specified debug name. 193 */ 194 public static synchronized Debug getInstance(String debugName) { 195 Debug debug = (Debug)getDebugMap().get(debugName); 196 if (debug == null) { 197 debug = new Debug(getDebugProvider().getInstance(debugName)); 198 getDebugMap().put(debugName, debug); 199 } 200 return debug; 201 } 202 203 /** 204 * Returns a collection of all Debug instances that exist in the system at 205 * the current instance. This is a live collection that will be updated as 206 * and when new Debug instances are created. Note that if an iterator is 207 * used, it could potentially cause a 208 * <code>ConcurrentModificationException</code> if during the process of 209 * iteration, the collection is modified by the system. 210 * 211 * @return a collection of all Debug instances in the system. 212 */ 213 public static Collection getInstances() { 214 return getDebugMap().values(); 215 } 216 217 /** 218 * Gets the <code>Map</code> of all Debug instances being used in the 219 * system currently. 220 * 221 * @return the <code>Map</code> of all Debug instances 222 */ 223 private static Map getDebugMap() { 224 return debugMap; 225 } 226 227 /** 228 * Sets the provider instance to be used by Debug service. 229 * 230 * @param provider 231 * the <code>IDebugProvider</code> instance that is used by the 232 * Debug service. 233 */ 234 private static void setDebugProvider(IDebugProvider provider) { 235 debugProvider = provider; 236 } 237 238 /** 239 * Gets the configured debug provider being used by the Debug service. 240 * 241 * @return the configured debug provider. 242 */ 243 static IDebugProvider getDebugProvider() { 244 return debugProvider; 245 } 246 247 /** 248 * Initializes the Debug Service by locating the SPI implementations and 249 * instantiating the appropriate classes. 250 */ 251 private static synchronized void initialize() { 252 if (!serviceInitialized) { 253 String providerName = SystemPropertiesManager.get( 254 CONFIG_DEBUG_PROVIDER); 255 IDebugProvider provider = null; 256 boolean providerLoadFailed = false; 257 if (providerName != null && providerName.trim().length() > 0) { 258 try { 259 provider = (IDebugProvider) Class.forName(providerName) 260 .newInstance(); 261 } catch (ClassNotFoundException cnex) { 262 providerLoadFailed = true; 263 } catch (InstantiationException iex) { 264 providerLoadFailed = true; 265 } catch (IllegalAccessException iaex) { 266 providerLoadFailed = true; 267 } catch (ClassCastException ccex) { 268 providerLoadFailed = true; 269 } 270 } 271 if (provider == null) { 272 if (providerLoadFailed) { 273 ResourceBundle bundle =com.sun.identity.shared.locale.Locale 274 .getInstallResourceBundle("amUtilMsgs"); 275 System.err.println(bundle.getString( 276 "com.iplanet.services.debug.invalidprovider")); 277 } 278 provider = new DebugProviderImpl(); 279 } 280 setDebugProvider(provider); 281 serviceInitialized = true; 282 } 283 } 284 285 /* Instance fields and methods */ 286 287 /** 288 * The instance of the actual debug service class as obtained from the 289 * configured provider. 290 */ 291 private IDebug debugServiceInstance; 292 293 /** 294 * Convinience method to query the name being used for this Debug instance. 295 * The return value of this method is a string exactly equal to the name 296 * that was used while creating this instance. 297 * 298 * @return the name of this Debug instance 299 */ 300 public String getName() { 301 return getDebugServiceInstance().getName(); 302 } 303 304 /** 305 * Checks if message debugging is enabled. 306 * 307 * <p> 308 * <b>NOTE:</b> Debugging is an IO intensive operation and may hurt 309 * application performance when abused. Particularly, note that Java 310 * evaluates arguments to <code>message()</code> even when debugging is 311 * turned off. It is recommended that <code>messageEnabled()</code> be 312 * called to check the debug state before invoking any 313 * <code>message()</code> methods to avoid unnecessary argument evaluation 314 * and maximize application performance. 315 * </p> 316 * 317 * @return <code>true</code> if message debugging is enabled 318 * <code>false</code> if message debugging is disabled 319 */ 320 public boolean messageEnabled() { 321 return getDebugServiceInstance().messageEnabled(); 322 } 323 324 /** 325 * Checks if warning debugging is enabled. 326 * 327 * <p> 328 * <b>NOTE:</b> Debugging is an IO intensive operation and may hurt 329 * application performance when abused. Particularly, note that Java 330 * evaluates arguments to <code>warning()</code> even when warning 331 * debugging is turned off. It is recommended that 332 * <code>warningEnabled()</code> be called to check the debug state before 333 * invoking any <code>warning()</code> methods to avoid unnecessary 334 * argument evaluation and maximize application performance. 335 * </p> 336 * 337 * @return <code>true</code> if warning debugging is enabled 338 * <code>false</code> if warning debugging is disabled 339 */ 340 public boolean warningEnabled() { 341 return getDebugServiceInstance().warningEnabled(); 342 } 343 344 /** 345 * Checks if error debugging is enabled. 346 * 347 * <p> 348 * <b>NOTE:</b> Debugging is an IO intensive operation and may hurt 349 * application performance when abused. Particularly, note that Java 350 * evaluates arguments to <code>error()</code> even when error debugging 351 * is turned off. It is recommended that <code>errorEnabled()</code> be 352 * called to check the debug state before invoking any <code>error()</code> 353 * methods to avoid unnecessary argument evaluation and maximize application 354 * performance. 355 * </p> 356 * 357 * @return <code>true</code> if error debugging is enabled 358 * <code>false</code> if error debugging is disabled 359 */ 360 public boolean errorEnabled() { 361 return getDebugServiceInstance().errorEnabled(); 362 } 363 364 /** 365 * Returns one of the five possible values: 366 * <ul> 367 * <li>Debug.OFF 368 * <li>Debug.ERROR 369 * <li>Debug.WARNING 370 * <li>Debug.MESSAGE 371 * <li>Debug.ON 372 * </ul> 373 * 374 * @return the debug level 375 */ 376 public int getState() { 377 return getDebugServiceInstance().getState(); 378 } 379 380 /** 381 * Prints messages only when the debug state is either Debug.MESSAGE or 382 * Debug.ON. 383 * 384 * <p> 385 * <b>NOTE:</b> Debugging is an IO intensive operation and may hurt 386 * application performance when abused. Particularly, note that Java 387 * evaluates arguments to <code>message()</code> even when debugging is 388 * turned off. So when the argument to this method involves the String 389 * concatenation operator '+' or any other method invocation, 390 * <code>messageEnabled</code> <b>MUST</b> be used. It is recommended 391 * that the debug state be checked by invoking <code>messageEnabled()</code> 392 * before invoking any <code>message()</code> methods to avoid unnecessary 393 * argument evaluation and maximize application performance. 394 * </p> 395 * 396 * @param msg 397 * debug message. 398 * @see Debug#message(String, Throwable) 399 */ 400 public void message(String msg) { 401 getDebugServiceInstance().message(msg, null); 402 } 403 404 /** 405 * <p> 406 * Prints debug and exception messages only when the debug state is either 407 * Debug.MESSAGE or Debug.ON. If the debug file is not accessible and 408 * debugging is enabled, the message along with a time stamp and thread info 409 * will be printed on <code>System.out</code>. 410 * </p> 411 * 412 * <p> 413 * This method creates the debug file if does not exist; otherwise it starts 414 * appending to the existing debug file. When invoked for the first time on 415 * this object, the method writes a line delimiter of '*'s. 416 * </p> 417 * 418 * <p> 419 * Note that the debug file will remain open until <code>destroy()</code> 420 * is invoked. To conserve file resources, you should invoke 421 * <code>destroy()</code> explicitly rather than wait for the garbage 422 * collector to clean up. 423 * </p> 424 * 425 * <p> 426 * <b>NOTE:</b> Debugging is an IO intensive operation and may hurt 427 * application performance when abused. Particularly, note that Java 428 * evaluates arguments to <code>message()</code> even when debugging is 429 * turned off. It is recommended that the debug state be checked by invoking 430 * <code>messageEnabled()</code> before invoking any 431 * <code>message()</code> methods to avoid unnecessary argument evaluation 432 * and to maximize application performance. 433 * </p> 434 * 435 * @param msg 436 * message to be printed. A newline will be appended to the 437 * message before printing either to <code>System.out</code> or 438 * to the debug file. If <code>msg</code> is null, it is 439 * ignored. 440 * @param t 441 * <code>Throwable</code>, on which 442 * <code>printStackTrace</code> will be invoked to print the 443 * stack trace. If <code>t</code> is null, it is ignored. 444 * @see Debug#error(String, Throwable) 445 */ 446 public void message(String msg, Throwable t) { 447 getDebugServiceInstance().message(msg, t); 448 } 449 450 /** 451 * Prints warning messages only when debug level is greater than 452 * Debug.ERROR. 453 * 454 * <p> 455 * <b>NOTE:</b> Debugging is an IO intensive operation and may hurt 456 * application performance when abused. Particularly, note that Java 457 * evaluates arguments to <code>warning()</code> even when debugging is 458 * turned off. So when the argument to this method involves the String 459 * concatenation operator '+' or any other method invocation, 460 * <code>warningEnabled</code> <b>MUST</b> be used. It is recommended 461 * that the debug state be checked by invoking <code>warningEnabled()</code> 462 * before invoking any <code>warning()</code> methods to avoid unnecessary 463 * argument evaluation and to maximize application performance. 464 * </p> 465 * 466 * @param msg 467 * message to be printed. A newline will be appended to the 468 * message before printing either to <code>System.out</code> or 469 * to the debug file. If <code>msg</code> is null, it is 470 * ignored. 471 * 472 * @see Debug#warning(String, Throwable) 473 */ 474 public void warning(String msg) { 475 getDebugServiceInstance().warning(msg, null); 476 } 477 478 /** 479 * Prints warning messages only when debug level is greater than 480 * Debug.ERROR. 481 * 482 * <p> 483 * <b>NOTE:</b> Debugging is an IO intensive operation and may hurt 484 * application performance when abused. Particularly, note that Java 485 * evaluates arguments to <code>warning()</code> even when debugging is 486 * turned off. It is recommended that the debug state be checked by invoking 487 * <code>warningEnabled()</code> before invoking any 488 * <code>warning()</code> methods to avoid unnecessary argument evaluation 489 * and to maximize application performance. 490 * </p> 491 * 492 * <p> 493 * If the debug file is not accessible and debugging is enabled, the message 494 * along with a time stamp and thread info will be printed on 495 * <code>System.out</code>. 496 * </p> 497 * 498 * <p> 499 * This method creates the debug file if does not exist; otherwise it starts 500 * appending to the existing debug file. When invoked for the first time on 501 * this object, the method writes a line delimiter of '*'s. 502 * </p> 503 * 504 * <p> 505 * Note that the debug file will remain open until <code>destroy()</code> 506 * is invoked. To conserve file resources, you should invoke 507 * <code>destroy()</code> explicitly rather than wait for the garbage 508 * collector to clean up. 509 * </p> 510 * 511 * @param msg 512 * message to be printed. A newline will be appended to the 513 * message before printing either to <code>System.out</code> or 514 * to the debug file. If <code>msg</code> is null, it is 515 * ignored. 516 * 517 * @param t 518 * <code>Throwable</code>, on which 519 * <code>printStackTrace()</code> will be invoked to print the 520 * stack trace. If <code>t</code> is null, it is ignored. 521 */ 522 public void warning(String msg, Throwable t) { 523 getDebugServiceInstance().warning(msg, t); 524 } 525 526 /** 527 * Prints error messages only when debug level is greater than DEBUG.OFF. 528 * 529 * @param msg 530 * message to be printed. A newline will be appended to the 531 * message before printing either to <code>System.out</code> or 532 * to the debug file. If <code>msg</code> is null, it is 533 * ignored. 534 * 535 * @see Debug#error(String, Throwable) 536 */ 537 public void error(String msg) { 538 getDebugServiceInstance().error(msg, null); 539 } 540 541 /** 542 * Prints error messages only if debug state is greater than Debug.OFF. If 543 * the debug file is not accessible and debugging is enabled, the message 544 * along with a time stamp and thread info will be printed on 545 * <code>System.out</code>. 546 * </p> 547 * 548 * <p> 549 * This method creates the debug file if does not exist; otherwise it starts 550 * appending to the existing debug file. When invoked for the first time on 551 * this object, the method writes a line delimiter of '*'s. 552 * </p> 553 * 554 * <p> 555 * Note that the debug file will remain open until <code>destroy()</code> 556 * is invoked. To conserve file resources, you should invoke 557 * <code>destroy()</code> explicitly rather than wait for the garbage 558 * collector to clean up. 559 * </p> 560 * 561 * @param msg 562 * message to be printed. A newline will be appended to the 563 * message before printing either to <code>System.out</code> or 564 * to the debug file. If <code>msg</code> is null, it is 565 * ignored. 566 * 567 * @param t 568 * <code>Throwable</code>, on which 569 * <code>printStackTrace()</code> will be invoked to print the 570 * stack trace. If <code>t</code> is null, it is ignored. 571 */ 572 public void error(String msg, Throwable t) { 573 getDebugServiceInstance().error(msg, t); 574 } 575 576 /** 577 * Sets the debug capabilities based on the values of the 578 * <code>debugType</code> argument. 579 * 580 * @param debugType 581 * is any one of five possible values: 582 * <ul> 583 * <li><code>Debug.OFF</code> 584 * <li><code>Debug.ERROR</code> 585 * <li><code>Debug.WARNING</code> 586 * <li><code>Debug.MESSAGE</code> 587 * <li><code>Debug.ON</code> 588 * </ul> 589 */ 590 public void setDebug(int debugType) { 591 getDebugServiceInstance().setDebug(debugType); 592 } 593 594 /** 595 * Allows runtime modification of the backend used by this instance. 596 * by resetting the debug instance to reinitialize itself. 597 * @param mf merge flag - on for creating a single debug file. 598 */ 599 public void resetDebug(String mf) { 600 getDebugServiceInstance().resetDebug(mf); 601 } 602 /** 603 * Sets the debug capabilities based on the values of the 604 * <code>debugType</code> argument. 605 * 606 * @param debugType 607 * is any one of the following possible values: 608 * <ul> 609 * <li><code>Debug.STR_OFF</code> 610 * <li><code>Debug.STR_ERROR</code> 611 * <li><code>Debug.STR_WARNING</code> 612 * <li><code>Debug.STR_MESSAGE</code> 613 * <li><code>Debug.STR_ON</code> 614 * </ul> 615 */ 616 public void setDebug(String debugType) { 617 getDebugServiceInstance().setDebug(debugType); 618 } 619 620 /** 621 * Destroys the debug object, closes the debug file and releases any system 622 * resources. Note that the debug file will remain open until 623 * <code>destroy()</code> is invoked. To conserve file resources, you 624 * should invoke <code>destroy()</code> explicitly rather than wait for 625 * the garbage collector to clean up. 626 * 627 * <p> 628 * If this object is accessed after <code>destroy()</code> has been 629 * invoked, the results are undefined. 630 * </p> 631 */ 632 public void destroy() { 633 // No handling required 634 } 635 636 /** 637 * Setter for setting the actual debug service class which is obtained from 638 * the configured provider. 639 */ 640 private void setDebugServiceInstance(IDebug debugServiceInstance) { 641 this.debugServiceInstance = debugServiceInstance; 642 } 643 644 /** 645 * Returns the actual debug service class. 646 * 647 * @return The underlying debug service class. 648 */ 649 private IDebug getDebugServiceInstance() { 650 return this.debugServiceInstance; 651 } 652 653 /** 654 * The sole constructor of the Debug instances. This constructor is declared 655 * private to ensure the use of the factory method provided in this class 656 * called {@link #getInstance(String)}. 657 */ 658 private Debug(IDebug debugServiceInstance) { 659 setDebugServiceInstance(debugServiceInstance); 660 } 661 662 /* Static Initializer */ 663 static { 664 initialize(); 665 } 666}
Copyright © 2010-2017, ForgeRock All Rights Reserved.