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