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 2006-2008 Sun Microsystems, Inc.
015 * Portions Copyright 2013-2015 ForgeRock AS.
016 */
017package org.opends.server.loggers;
018
019import static org.opends.messages.ConfigMessages.*;
020
021import java.util.Collection;
022
023import org.forgerock.i18n.LocalizableMessage;
024import org.opends.messages.Severity;
025import org.opends.server.admin.ClassPropertyDefinition;
026import org.opends.server.admin.std.meta.ErrorLogPublisherCfgDefn;
027import org.opends.server.admin.std.server.ErrorLogPublisherCfg;
028import org.opends.server.api.DirectoryThread;
029import org.opends.server.backends.task.Task;
030import org.opends.server.core.ServerContext;
031
032/**
033 * This class defines the wrapper that will invoke all registered error loggers
034 * for each type of request received or response sent. If no error log
035 * publishers are registered, messages will be directed to standard out.
036 */
037public class ErrorLogger extends AbstractLogger
038    <ErrorLogPublisher<ErrorLogPublisherCfg>, ErrorLogPublisherCfg>
039{
040
041  private static LoggerStorage
042      <ErrorLogPublisher<ErrorLogPublisherCfg>, ErrorLogPublisherCfg>
043      loggerStorage = new LoggerStorage<>();
044
045  /** The singleton instance of this class for configuration purposes. */
046  private static final ErrorLogger instance = new ErrorLogger();
047
048  /**
049   * Retrieve the singleton instance of this class.
050   *
051   * @return The singleton instance of this logger.
052   */
053  public static ErrorLogger getInstance()
054  {
055    return instance;
056  }
057
058  /**
059   * The constructor for this class.
060   */
061  private ErrorLogger()
062  {
063    super((Class) ErrorLogPublisher.class,
064        ERR_CONFIG_LOGGER_INVALID_ERROR_LOGGER_CLASS);
065  }
066
067  /** {@inheritDoc} */
068  @Override
069  protected ClassPropertyDefinition getJavaClassPropertyDefinition()
070  {
071    return ErrorLogPublisherCfgDefn.getInstance()
072        .getJavaClassPropertyDefinition();
073  }
074
075  /** {@inheritDoc} */
076  @Override
077  protected Collection<ErrorLogPublisher<ErrorLogPublisherCfg>> getLogPublishers()
078  {
079    return loggerStorage.getLogPublishers();
080  }
081
082  /**
083   * Writes a message to the error log using the provided information.
084   * <p>
085   * Category is defined using either short name (used for classes in well
086   * defined packages) or fully qualified classname. Conversion to short name is
087   * done automatically when loggers are created, see
088   * {@code LoggingCategoryNames} for list of existing short names.
089   *
090   * @param category
091   *          The category of the message, which is either a classname or a
092   *          simple category name defined in {@code LoggingCategoryNames}
093   *          class.
094   * @param severity
095   *          The severity of the message.
096   * @param message
097   *          The message to be logged.
098   * @param exception
099   *          The exception to be logged. May be {@code null}.
100   */
101  public static void log(String category, Severity severity, LocalizableMessage message, Throwable exception)
102  {
103    for (ErrorLogPublisher<?> publisher : loggerStorage.getLogPublishers())
104    {
105      publisher.log(category, severity, message, exception);
106    }
107
108    if (Thread.currentThread() instanceof DirectoryThread)
109    {
110      DirectoryThread thread = (DirectoryThread) Thread.currentThread();
111      Task task = thread.getAssociatedTask();
112      if (task != null)
113      {
114        task.addLogMessage(severity, message, exception);
115      }
116    }
117  }
118
119  /**
120   * Check if logging is enabled for the provided category and severity.
121   *
122   * @param category
123   *          The category of the logging event, which is either a classname or
124   *          a simple category name defined in {@code LoggingCategoryNames}
125   *          class.
126   * @param severity
127   *          The severity of logging event.
128   * @return {@code true} if logger is enabled
129   */
130  public static boolean isEnabledFor(String category, Severity severity)
131  {
132    if (Thread.currentThread() instanceof DirectoryThread)
133    {
134      DirectoryThread thread = (DirectoryThread) Thread.currentThread();
135      Task task = thread.getAssociatedTask();
136      if (task != null)
137      {
138        return true;
139      }
140    }
141    for (ErrorLogPublisher<ErrorLogPublisherCfg> publisher : loggerStorage.getLogPublishers())
142    {
143      if (publisher.isEnabledFor(category, severity))
144      {
145        return true;
146      }
147    }
148    return false;
149  }
150
151  @Override
152  public final synchronized void addLogPublisher(final ErrorLogPublisher<ErrorLogPublisherCfg> publisher)
153  {
154    loggerStorage.addLogPublisher(publisher);
155    adjustJulLevel();
156  }
157
158  @Override
159  public final synchronized boolean removeLogPublisher(final ErrorLogPublisher<ErrorLogPublisherCfg> publisher)
160  {
161    final boolean removed = loggerStorage.removeLogPublisher(publisher);
162    adjustJulLevel();
163    return removed;
164  }
165
166  @Override
167  public final synchronized void removeAllLogPublishers()
168  {
169    loggerStorage.removeAllLogPublishers();
170    adjustJulLevel();
171  }
172
173  private void adjustJulLevel()
174  {
175    final ServerContext serverContext = getServerContext();
176    if (serverContext != null)
177    {
178      serverContext.getLoggerConfigManager().adjustJulLevel();
179    }
180  }
181}