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}