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-2016 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.forgerock.opendj.config.ClassPropertyDefinition;
026import org.forgerock.opendj.server.config.meta.ErrorLogPublisherCfgDefn;
027import org.forgerock.opendj.server.config.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  /** The constructor for this class. */
059  private ErrorLogger()
060  {
061    super((Class) ErrorLogPublisher.class,
062        ERR_CONFIG_LOGGER_INVALID_ERROR_LOGGER_CLASS);
063  }
064
065  @Override
066  protected ClassPropertyDefinition getJavaClassPropertyDefinition()
067  {
068    return ErrorLogPublisherCfgDefn.getInstance()
069        .getJavaClassPropertyDefinition();
070  }
071
072  @Override
073  protected Collection<ErrorLogPublisher<ErrorLogPublisherCfg>> getLogPublishers()
074  {
075    return loggerStorage.getLogPublishers();
076  }
077
078  /**
079   * Writes a message to the error log using the provided information.
080   * <p>
081   * Category is defined using either short name (used for classes in well
082   * defined packages) or fully qualified classname. Conversion to short name is
083   * done automatically when loggers are created, see
084   * {@code LoggingCategoryNames} for list of existing short names.
085   *
086   * @param category
087   *          The category of the message, which is either a classname or a
088   *          simple category name defined in {@code LoggingCategoryNames}
089   *          class.
090   * @param severity
091   *          The severity of the message.
092   * @param message
093   *          The message to be logged.
094   * @param exception
095   *          The exception to be logged. May be {@code null}.
096   */
097  public static void log(String category, Severity severity, LocalizableMessage message, Throwable exception)
098  {
099    for (ErrorLogPublisher<?> publisher : loggerStorage.getLogPublishers())
100    {
101      publisher.log(category, severity, message, exception);
102    }
103
104    if (Thread.currentThread() instanceof DirectoryThread)
105    {
106      DirectoryThread thread = (DirectoryThread) Thread.currentThread();
107      Task task = thread.getAssociatedTask();
108      if (task != null)
109      {
110        task.addLogMessage(severity, message, exception);
111      }
112    }
113  }
114
115  /**
116   * Check if logging is enabled for the provided category and severity.
117   *
118   * @param category
119   *          The category of the logging event, which is either a classname or
120   *          a simple category name defined in {@code LoggingCategoryNames}
121   *          class.
122   * @param severity
123   *          The severity of logging event.
124   * @return {@code true} if logger is enabled
125   */
126  public static boolean isEnabledFor(String category, Severity severity)
127  {
128    if (Thread.currentThread() instanceof DirectoryThread)
129    {
130      DirectoryThread thread = (DirectoryThread) Thread.currentThread();
131      Task task = thread.getAssociatedTask();
132      if (task != null)
133      {
134        return true;
135      }
136    }
137    for (ErrorLogPublisher<ErrorLogPublisherCfg> publisher : loggerStorage.getLogPublishers())
138    {
139      if (publisher.isEnabledFor(category, severity))
140      {
141        return true;
142      }
143    }
144    return false;
145  }
146
147  @Override
148  public final synchronized void addLogPublisher(final ErrorLogPublisher<ErrorLogPublisherCfg> publisher)
149  {
150    loggerStorage.addLogPublisher(publisher);
151    adjustJulLevel();
152  }
153
154  @Override
155  public final synchronized boolean removeLogPublisher(final ErrorLogPublisher<ErrorLogPublisherCfg> publisher)
156  {
157    final boolean removed = loggerStorage.removeLogPublisher(publisher);
158    adjustJulLevel();
159    return removed;
160  }
161
162  @Override
163  public final synchronized void removeAllLogPublishers()
164  {
165    loggerStorage.removeAllLogPublishers();
166    adjustJulLevel();
167  }
168
169  private void adjustJulLevel()
170  {
171    final ServerContext serverContext = getServerContext();
172    if (serverContext != null && serverContext.getLoggerConfigManager() != null)
173    {
174      serverContext.getLoggerConfigManager().adjustJulLevel();
175    }
176  }
177}