001/*
002 * The contents of this file are subject to the terms of the Common Development and
003 * Distribution License (the License). You may not use this file except in compliance with the
004 * License.
005 *
006 * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the
007 * specific language governing permission and limitations under the License.
008 *
009 * When distributing Covered Software, include this CDDL Header Notice in each file and include
010 * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL
011 * Header, with the fields enclosed by brackets [] replaced by your own identifying
012 * information: "Portions Copyright [year] [name of copyright owner]".
013 *
014 * Copyright 2014-2016 ForgeRock AS.
015 */
016package org.opends.server.loggers;
017
018import java.io.PrintStream;
019import java.util.logging.ErrorManager;
020import java.util.logging.Formatter;
021import java.util.logging.Handler;
022import java.util.logging.Level;
023import java.util.logging.LogManager;
024import java.util.logging.LogRecord;
025import java.util.logging.Logger;
026import java.util.logging.SimpleFormatter;
027
028/** Utility class for java.util.logging support. */
029public class JDKLogging
030{
031  /** Root packages that contains all OpenDJ related classes. */
032  private static final String[] LOGGING_ROOTS = new String[] { "org.opends", "org.forgerock.opendj"};
033
034  /** Disable java.util.logging. */
035  public static void disableLogging()
036  {
037    LogManager.getLogManager().reset();
038    Logger.getLogger("").setLevel(Level.OFF);
039  }
040
041  /**
042   * Enable JDK logging to stderr at provided level for OpenDJ classes.
043   * <p>
044   * Error and warning messages will be printed on stderr, other messages will be printed on stdout.
045   */
046  public static void enableVerboseConsoleLoggingForOpenDJ()
047  {
048    enableConsoleLoggingForOpenDJ(Level.ALL, System.out, System.err);
049  }
050
051  /**
052   * Enable JDK logging for OpenDJ tool.
053   * <p>
054   * Error and warning messages will be printed on stderr, other messages will be printed on stdout.
055   * This method should only be used by external tool classes.
056   */
057  public static void enableConsoleLoggingForOpenDJTool()
058  {
059    enableConsoleLoggingForOpenDJ(Level.FINE, System.out, System.err);
060  }
061
062  /**
063   * Enable JDK logging in provided {@link PrintStream} for OpenDJ tool.
064   * <p>
065   * All messages will be printed on the provided {@link PrintStream}.
066   * This method should only be used by external tool classes.
067   *
068   * @param stream
069   *          The stream to use to print messages.
070   */
071  public static void enableLoggingForOpenDJTool(final PrintStream stream)
072  {
073    enableConsoleLoggingForOpenDJ(Level.FINE, stream, stream);
074  }
075
076  /**
077   * Enable JDK logging at provided {@link Level} in provided {@link PrintStream} for OpenDJ classes.
078   *
079   * @param level
080   *          The level to log.
081   * @param out
082   *          The stream to use to print messages from {@link Level#FINEST} and {@link Level#INFO} included.
083   * @param err
084   *          The stream to use to print {@link Level#SEVERE} and {@link Level#WARNING} messages.
085   */
086  private static void enableConsoleLoggingForOpenDJ(final Level level, final PrintStream out, final PrintStream err)
087  {
088    LogManager.getLogManager().reset();
089    Handler handler = new OpenDJHandler(out, err);
090    handler.setFormatter(getFormatter());
091    handler.setLevel(level);
092    for (String loggingRoot : LOGGING_ROOTS)
093    {
094      Logger logger = Logger.getLogger(loggingRoot);
095      logger.setLevel(level);
096      logger.addHandler(handler);
097    }
098  }
099
100  /** Custom handler to log to either stdout or stderr depending on the log level. */
101  private static final class OpenDJHandler extends Handler
102  {
103    private final PrintStream out;
104    private final PrintStream err;
105
106    private OpenDJHandler(final PrintStream out, final PrintStream err)
107    {
108      this.out = out;
109      this.err = err;
110    }
111
112    @Override
113    public void publish(LogRecord record)
114    {
115      if (getFormatter() == null)
116      {
117        setFormatter(new SimpleFormatter());
118      }
119
120      try
121      {
122        String message = getFormatter().format(record);
123        if (record.getLevel().intValue() >= Level.WARNING.intValue())
124        {
125          err.write(message.getBytes());
126        }
127        else
128        {
129          out.write(message.getBytes());
130        }
131      }
132      catch (Exception exception)
133      {
134        reportError(null, exception, ErrorManager.FORMAT_FAILURE);
135        return;
136      }
137    }
138
139    @Override
140    public void close() throws SecurityException
141    {
142    }
143
144    @Override
145    public void flush()
146    {
147      System.out.flush();
148      System.err.flush();
149    }
150  }
151
152  /**
153   * Get a formatter.
154   *
155   * @return a formatter for loggers
156   */
157  public static Formatter getFormatter()
158  {
159    return new JDKLoggingFormater();
160  }
161
162  /**
163   * Returns the packages to be used as root for logging.
164   * <p>
165   * This package covers all OpenDJ classes.
166   *
167   * @return the root packages to log
168   */
169  public static String[] getOpendDJLoggingRoots() {
170    return LOGGING_ROOTS;
171  }
172
173}