opends/src/admin/defn/org/opends/server/admin/std/AccessLogPublisherConfiguration.xml
@@ -24,7 +24,7 @@ ! ! ! Copyright 2007-2008 Sun Microsystems, Inc. ! Portions copyright 2011 ForgeRock AS. ! Portions copyright 2011-2013 ForgeRock AS ! --> <adm:managed-object name="access-log-publisher" plural-name="access-log-publishers" @@ -59,25 +59,13 @@ <ldap:rdn-sequence>cn=Filtering Criteria</ldap:rdn-sequence> </adm:profile> </adm:relation> <adm:property name="java-class" mandatory="true"> <adm:synopsis> The fully-qualified name of the Java class that provides the <adm:user-friendly-name /> implementation. </adm:synopsis> <adm:syntax> <adm:java-class> <adm:instance-of> org.opends.server.api.AccessLogPublisher </adm:instance-of> </adm:java-class> </adm:syntax> <adm:profile name="ldap"> <ldap:attribute> <ldap:name>ds-cfg-java-class</ldap:name> </ldap:attribute> </adm:profile> </adm:property> <adm:property-override name="java-class"> <adm:default-behavior> <adm:defined> <adm:value>org.opends.server.api.AccessLogPublisher</adm:value> </adm:defined> </adm:default-behavior> </adm:property-override> <adm:property name="filtering-policy"> <adm:synopsis> Specifies how filtering criteria should be applied to log records. opends/src/admin/defn/org/opends/server/admin/std/DebugLogPublisherConfiguration.xml
@@ -24,6 +24,7 @@ ! ! ! Copyright 2007-2008 Sun Microsystems, Inc. ! Portions copyright 2013 ForgeRock AS ! --> <adm:managed-object name="debug-log-publisher" plural-name="debug-log-publishers" @@ -62,25 +63,13 @@ </cli:relation> </adm:profile> </adm:relation> <adm:property name="java-class" mandatory="true"> <adm:synopsis> The fully-qualified name of the Java class that provides the <adm:user-friendly-name /> implementation. </adm:synopsis> <adm:syntax> <adm:java-class> <adm:instance-of> org.opends.server.api.DebugLogPublisher </adm:instance-of> </adm:java-class> </adm:syntax> <adm:profile name="ldap"> <ldap:attribute> <ldap:name>ds-cfg-java-class</ldap:name> </ldap:attribute> </adm:profile> </adm:property> <adm:property-override name="java-class"> <adm:default-behavior> <adm:defined> <adm:value>org.opends.server.api.DebugLogPublisher</adm:value> </adm:defined> </adm:default-behavior> </adm:property-override> <adm:property name="default-debug-level" mandatory="true"> <adm:synopsis> The lowest severity level of debug messages to log when none of opends/src/admin/defn/org/opends/server/admin/std/ErrorLogPublisherConfiguration.xml
@@ -24,6 +24,7 @@ ! ! ! Copyright 2007-2008 Sun Microsystems, Inc. ! Portions copyright 2013 ForgeRock AS ! --> <adm:managed-object name="error-log-publisher" plural-name="error-log-publishers" @@ -49,25 +50,13 @@ <adm:profile name="cli"> <cli:managed-object custom="true" /> </adm:profile> <adm:property name="java-class" mandatory="true"> <adm:synopsis> The fully-qualified name of the Java class that provides the <adm:user-friendly-name /> implementation. </adm:synopsis> <adm:syntax> <adm:java-class> <adm:instance-of> org.opends.server.api.ErrorLogPublisher </adm:instance-of> </adm:java-class> </adm:syntax> <adm:profile name="ldap"> <ldap:attribute> <ldap:name>ds-cfg-java-class</ldap:name> </ldap:attribute> </adm:profile> </adm:property> <adm:property-override name="java-class"> <adm:default-behavior> <adm:defined> <adm:value>org.opends.server.api.ErrorLogPublisher</adm:value> </adm:defined> </adm:default-behavior> </adm:property-override> <adm:property name="default-severity" multi-valued="true"> <adm:synopsis> Specifies the default severity levels for the logger. opends/src/admin/defn/org/opends/server/admin/std/LogPublisherConfiguration.xml
@@ -24,6 +24,7 @@ ! ! ! Copyright 2007-2008 Sun Microsystems, Inc. ! Portions copyright 2013 ForgeRock AS ! --> <adm:managed-object name="log-publisher" plural-name="log-publishers" package="org.opends.server.admin.std" abstract="true" @@ -56,4 +57,23 @@ </ldap:attribute> </adm:profile> </adm:property> <adm:property name="java-class" mandatory="true"> <adm:synopsis> The fully-qualified name of the Java class that provides the <adm:user-friendly-name /> implementation. </adm:synopsis> <adm:syntax> <adm:java-class> <adm:instance-of> org.opends.server.api.LogPublisher </adm:instance-of> </adm:java-class> </adm:syntax> <adm:profile name="ldap"> <ldap:attribute> <ldap:name>ds-cfg-java-class</ldap:name> </ldap:attribute> </adm:profile> </adm:property> </adm:managed-object> opends/src/admin/messages/LogPublisherCfgDefn.properties
@@ -2,3 +2,4 @@ user-friendly-plural-name=Log Publishers synopsis=Log Publishers are responsible for distributing log messages from different loggers to a destination. property.enabled.synopsis=Indicates whether the Log Publisher is enabled for use. property.java-class.synopsis=The fully-qualified name of the Java class that provides the Log Publisher implementation. opends/src/server/org/opends/server/core/LoggerConfigManager.java
@@ -23,27 +23,29 @@ * * * Copyright 2006-2008 Sun Microsystems, Inc. * Portions copyright 2013 ForgeRock AS */ package org.opends.server.core; import org.opends.messages.Message; import java.util.*; import org.opends.server.config.ConfigException; import org.opends.server.types.*; import org.opends.server.loggers.debug.DebugLogger; import org.opends.server.loggers.ErrorLogger; import org.opends.server.loggers.AccessLogger; import static org.opends.messages.ConfigMessages.*; import static org.opends.server.loggers.ErrorLogger.*; import org.opends.server.admin.std.server.*; import java.util.ArrayList; import java.util.List; import org.opends.messages.Message; import org.opends.server.admin.server.ConfigurationAddListener; import org.opends.server.admin.server.ConfigurationDeleteListener; import org.opends.server.admin.server.ServerManagementContext; import org.opends.server.admin.std.server.*; import org.opends.server.config.ConfigException; import org.opends.server.loggers.AbstractLogger; import org.opends.server.loggers.AccessLogger; import org.opends.server.loggers.ErrorLogger; import org.opends.server.loggers.debug.DebugLogger; import org.opends.server.types.ConfigChangeResult; import org.opends.server.types.InitializationException; import org.opends.server.types.ResultCode; /** @@ -123,67 +125,77 @@ logError(WARN_CONFIG_LOGGER_NO_ACTIVE_ERROR_LOGGERS.get()); } DebugLogger.getInstance().initializeDebugLogger(debugPublisherCfgs); AccessLogger.getInstance().initializeAccessLogger(accessPublisherCfgs); ErrorLogger.getInstance().initializeErrorLogger(errorPublisherCfgs); DebugLogger.getInstance().initializeLogger(debugPublisherCfgs); AccessLogger.getInstance().initializeLogger(accessPublisherCfgs); ErrorLogger.getInstance().initializeLogger(errorPublisherCfgs); } /** * Returns the logger instance corresponding to the provided config. If no * logger corresponds to it, null will be returned and a message will be added * to the provided messages list. * * @param config * the config for which to return the logger instance * @param messages * where the error message will be output if no logger correspond to * the provided config. * @return the logger corresponding to the provided config, null if no logger * corresponds. */ private AbstractLogger getLoggerInstance(LogPublisherCfg config, List<Message> messages) { if (config instanceof DebugLogPublisherCfg) { return DebugLogger.getInstance(); } else if (config instanceof AccessLogPublisherCfg) { return AccessLogger.getInstance(); } else if (config instanceof ErrorLogPublisherCfg) { return ErrorLogger.getInstance(); } else { messages.add(ERR_CONFIG_LOGGER_INVALID_OBJECTCLASS.get(String .valueOf(config.dn()))); return null; } } /** * {@inheritDoc} */ @Override public boolean isConfigurationAddAcceptable(LogPublisherCfg config, List<Message> unacceptableReasons) { if(config instanceof DebugLogPublisherCfg) AbstractLogger instance = getLoggerInstance(config, unacceptableReasons); if (instance != null) { return DebugLogger.getInstance().isConfigurationAddAcceptable( (DebugLogPublisherCfg)config, unacceptableReasons); return instance.isConfigurationAddAcceptable(config, unacceptableReasons); } else if(config instanceof AccessLogPublisherCfg) { return AccessLogger.getInstance().isConfigurationAddAcceptable( (AccessLogPublisherCfg)config, unacceptableReasons); } else if(config instanceof ErrorLogPublisherCfg) { return ErrorLogger.getInstance().isConfigurationAddAcceptable( (ErrorLogPublisherCfg)config, unacceptableReasons); } else { unacceptableReasons.add(ERR_CONFIG_LOGGER_INVALID_OBJECTCLASS.get( String.valueOf(config.dn()))); return false; } return false; } /** * {@inheritDoc} */ @Override public ConfigChangeResult applyConfigurationAdd(LogPublisherCfg config) { if(config instanceof DebugLogPublisherCfg) List<Message> messages = new ArrayList<Message>(1); AbstractLogger instance = getLoggerInstance(config, messages); if (instance != null) { return DebugLogger.getInstance().applyConfigurationAdd( (DebugLogPublisherCfg)config); return instance.applyConfigurationAdd(config); } else if(config instanceof AccessLogPublisherCfg) { return AccessLogger.getInstance().applyConfigurationAdd( (AccessLogPublisherCfg)config); } else if(config instanceof ErrorLogPublisherCfg) { return ErrorLogger.getInstance().applyConfigurationAdd( (ErrorLogPublisherCfg)config); } else { ArrayList<Message> messages = new ArrayList<Message>(); messages.add(ERR_CONFIG_LOGGER_INVALID_OBJECTCLASS. get(String.valueOf(config.dn()))); boolean adminActionRequired = false; boolean adminActionRequired = false; ResultCode resultCode = ResultCode.UNWILLING_TO_PERFORM; return new ConfigChangeResult(resultCode, adminActionRequired, messages); } @@ -192,61 +204,36 @@ /** * {@inheritDoc} */ @Override public boolean isConfigurationDeleteAcceptable(LogPublisherCfg config, List<Message> unacceptableReasons) { if(config instanceof DebugLogPublisherCfg) AbstractLogger instance = getLoggerInstance(config, unacceptableReasons); if (instance != null) { return DebugLogger.getInstance().isConfigurationDeleteAcceptable( (DebugLogPublisherCfg)config, unacceptableReasons); return instance.isConfigurationDeleteAcceptable(config, unacceptableReasons); } else if(config instanceof AccessLogPublisherCfg) { return AccessLogger.getInstance().isConfigurationDeleteAcceptable( (AccessLogPublisherCfg)config, unacceptableReasons); } else if(config instanceof ErrorLogPublisherCfg) { return ErrorLogger.getInstance().isConfigurationDeleteAcceptable( (ErrorLogPublisherCfg)config, unacceptableReasons); } else { unacceptableReasons.add(ERR_CONFIG_LOGGER_INVALID_OBJECTCLASS.get( String.valueOf(config.dn()))); return false; } return false; } /** * {@inheritDoc} */ @Override public ConfigChangeResult applyConfigurationDelete(LogPublisherCfg config) { if(config instanceof DebugLogPublisherCfg) List<Message> messages = new ArrayList<Message>(1); AbstractLogger instance = getLoggerInstance(config, messages); if (instance != null) { return DebugLogger.getInstance().applyConfigurationDelete( (DebugLogPublisherCfg)config); return instance.applyConfigurationDelete(config); } else if(config instanceof AccessLogPublisherCfg) { return AccessLogger.getInstance().applyConfigurationDelete( (AccessLogPublisherCfg)config); } else if(config instanceof ErrorLogPublisherCfg) { return ErrorLogger.getInstance().applyConfigurationDelete( (ErrorLogPublisherCfg)config); } else { ArrayList<Message> messages = new ArrayList<Message>(); messages.add(ERR_CONFIG_LOGGER_INVALID_OBJECTCLASS.get( String.valueOf(config.dn()))); boolean adminActionRequired = false; ResultCode resultCode = ResultCode.UNWILLING_TO_PERFORM; return new ConfigChangeResult(resultCode, adminActionRequired, messages); } } } opends/src/server/org/opends/server/loggers/AbstractLogger.java
New file @@ -0,0 +1,409 @@ /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License, Version 1.0 only * (the "License"). You may not use this file except in compliance * with the License. * * You can obtain a copy of the license at * trunk/opends/resource/legal-notices/OpenDS.LICENSE * or https://OpenDS.dev.java.net/OpenDS.LICENSE. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable, * add the following below this CDDL HEADER, with the fields enclosed * by brackets "[]" replaced with your own identifying information: * Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END * * * Copyright 2006-2008 Sun Microsystems, Inc. * Portions copyright 2011-2013 ForgeRock AS. */ package org.opends.server.loggers; import static org.opends.messages.ConfigMessages.*; import static org.opends.server.util.StaticUtils.*; import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.concurrent.CopyOnWriteArrayList; import org.opends.messages.Message; import org.opends.messages.MessageDescriptor.Arg3; import org.opends.server.admin.ClassPropertyDefinition; import org.opends.server.admin.server.ConfigurationAddListener; import org.opends.server.admin.server.ConfigurationChangeListener; import org.opends.server.admin.server.ConfigurationDeleteListener; import org.opends.server.admin.std.server.LogPublisherCfg; import org.opends.server.api.LogPublisher; import org.opends.server.config.ConfigException; import org.opends.server.core.DirectoryServer; import org.opends.server.loggers.debug.DebugLogger; import org.opends.server.types.ConfigChangeResult; import org.opends.server.types.DN; import org.opends.server.types.DebugLogLevel; import org.opends.server.types.InitializationException; import org.opends.server.types.ResultCode; import org.opends.server.util.StaticUtils; /** * This class defines the wrapper that will invoke all registered loggers for * each type of request received or response sent. If no log publishers are * registered, messages will be directed to standard out. * * @param <P> * The type of the LogPublisher corresponding to this logger * @param <C> * The type of the LogPublisherCfg corresponding to this logger */ public abstract class AbstractLogger <P extends LogPublisher<C>, C extends LogPublisherCfg> implements ConfigurationAddListener<C>, ConfigurationDeleteListener<C>, ConfigurationChangeListener<C> { /** * The storage designed to store log publishers. It is helpful in abstracting * away the methods used to manage the collection. * * @param <P> * The concrete {@link LogPublisher} type * @param <C> * The concrete {@link LogPublisherCfg} type */ protected static class LoggerStorage<P extends LogPublisher<C>, C extends LogPublisherCfg> { /** * Defined as public to allow subclasses of {@link AbstractLogger} to * instantiate it. */ public LoggerStorage() { super(); } /** * The set of loggers that have been registered with the server. It will * initially be empty. */ private Collection<P> logPublishers = new CopyOnWriteArrayList<P>(); /** * Add a log publisher to the logger. * * @param publisher * The log publisher to add. */ public synchronized void addLogPublisher(P publisher) { logPublishers.add(publisher); } /** * Remove a log publisher from the logger. * * @param publisher * The log publisher to remove. * @return True if the log publisher is removed or false otherwise. */ public synchronized boolean removeLogPublisher(P publisher) { boolean removed = logPublishers.remove(publisher); if (removed) { publisher.close(); } return removed; } /** * Removes all existing log publishers from the logger. */ public synchronized void removeAllLogPublishers() { StaticUtils.close((Collection) logPublishers); logPublishers.clear(); } /** * Returns the logPublishers. * * @return the collection of {@link LogPublisher}s */ public Collection<P> getLogPublishers() { return logPublishers; } } /** * Returns the logger storage for the current logger. * * @return the logger storage for the current logger */ protected abstract LoggerStorage<P, C> getStorage(); /** * Returns the java {@link ClassPropertyDefinition} for the current logger. * * @return the java {@link ClassPropertyDefinition} for the current logger. */ protected abstract ClassPropertyDefinition getJavaClassPropertyDefinition(); private final Class<P> logPublisherClass; private final Arg3<CharSequence, CharSequence, CharSequence> invalidLoggerClassErrorMessage; /** * The constructor for this class. * * @param logPublisherClass * the log publisher class * @param invalidLoggerClassErrorMessage * the error message to use if the logger class in invalid */ public AbstractLogger( final Class<P> logPublisherClass, final Arg3<CharSequence, CharSequence, CharSequence> invalidLoggerClassErrorMessage) { this.logPublisherClass = logPublisherClass; this.invalidLoggerClassErrorMessage = invalidLoggerClassErrorMessage; } /** * Initializes all the log publishers. * * @param configs The log publisher configurations. * @throws ConfigException * If an unrecoverable problem arises in the process of * performing the initialization as a result of the server * configuration. * @throws InitializationException * If a problem occurs during initialization that is not * related to the server configuration. */ public void initializeLogger(List<C> configs) throws ConfigException, InitializationException { for (C config : configs) { config.addChangeListener((ConfigurationChangeListener) this); if(config.isEnabled()) { getStorage().addLogPublisher(getLogPublisher(config)); } } } /** * {@inheritDoc} */ @Override public boolean isConfigurationAddAcceptable(C config, List<Message> unacceptableReasons) { return !config.isEnabled() || isJavaClassAcceptable(config, unacceptableReasons); } /** * {@inheritDoc} */ @Override public boolean isConfigurationChangeAcceptable(C config, List<Message> unacceptableReasons) { return !config.isEnabled() || isJavaClassAcceptable(config, unacceptableReasons); } /** * {@inheritDoc} */ @Override public ConfigChangeResult applyConfigurationAdd(C config) { // Default result code. ResultCode resultCode = ResultCode.SUCCESS; boolean adminActionRequired = false; ArrayList<Message> messages = new ArrayList<Message>(); config.addChangeListener((ConfigurationChangeListener) this); if(config.isEnabled()) { try { getStorage().addLogPublisher(getLogPublisher(config)); } catch(ConfigException e) { debugCaught(DebugLogLevel.ERROR, e); messages.add(e.getMessageObject()); resultCode = DirectoryServer.getServerErrorResultCode(); } catch (Exception e) { debugCaught(DebugLogLevel.ERROR, e); messages.add(ERR_CONFIG_LOGGER_CANNOT_CREATE_LOGGER.get( String.valueOf(config.dn().toString()), stackTraceToSingleLineString(e))); resultCode = DirectoryServer.getServerErrorResultCode(); } } return new ConfigChangeResult(resultCode, adminActionRequired, messages); } private void debugCaught(LogLevel error, Exception e) { if (DebugLogger.debugEnabled()) { DebugLogger.getTracer().debugCaught(DebugLogLevel.ERROR, e); } } private P findLogPublisher(DN dn) { Collection<P> logPublishers = getStorage().getLogPublishers(); for (P publisher : logPublishers) { if (publisher.getDN().equals(dn)) { return publisher; } } return null; } /** * {@inheritDoc} */ @Override public ConfigChangeResult applyConfigurationChange(C config) { // Default result code. ResultCode resultCode = ResultCode.SUCCESS; boolean adminActionRequired = false; ArrayList<Message> messages = new ArrayList<Message>(); P logPublisher = findLogPublisher(config.dn()); if(logPublisher == null) { if(config.isEnabled()) { // Needs to be added and enabled. return applyConfigurationAdd(config); } } else { if(config.isEnabled()) { // The publisher is currently active, so we don't need to do anything. // Changes to the class name cannot be // applied dynamically, so if the class name did change then // indicate that administrative action is required for that // change to take effect. String className = config.getJavaClass(); if(!className.equals(logPublisher.getClass().getName())) { adminActionRequired = true; } } else { // The publisher is being disabled so shut down and remove. getStorage().removeLogPublisher(logPublisher); } } return new ConfigChangeResult(resultCode, adminActionRequired, messages); } /** * {@inheritDoc} */ @Override public boolean isConfigurationDeleteAcceptable(C config, List<Message> unacceptableReasons) { return findLogPublisher(config.dn()) != null; } /** * {@inheritDoc} */ @Override public ConfigChangeResult applyConfigurationDelete(C config) { // Default result code. ResultCode resultCode = ResultCode.SUCCESS; boolean adminActionRequired = false; P logPublisher = findLogPublisher(config.dn()); if(logPublisher != null) { getStorage().removeLogPublisher(logPublisher); } else { resultCode = ResultCode.NO_SUCH_OBJECT; } return new ConfigChangeResult(resultCode, adminActionRequired); } private boolean isJavaClassAcceptable(C config, List<Message> unacceptableReasons) { String className = config.getJavaClass(); ClassPropertyDefinition pd = getJavaClassPropertyDefinition(); try { // Load the class and cast it to a LogPublisher. P publisher = pd.loadClass(className, logPublisherClass).newInstance(); // The class is valid as far as we can tell. return publisher.isConfigurationAcceptable(config, unacceptableReasons); } catch (Exception e) { Message message = invalidLoggerClassErrorMessage.get(className, config.dn().toString(), String.valueOf(e)); unacceptableReasons.add(message); return false; } } private P getLogPublisher(C config) throws ConfigException { String className = config.getJavaClass(); ClassPropertyDefinition pd = getJavaClassPropertyDefinition(); try { // Load the class and cast it to a LogPublisher. P logPublisher = pd.loadClass(className, logPublisherClass).newInstance(); logPublisher.initializeLogPublisher(config); // The log publisher has been successfully initialized. return logPublisher; } catch (Exception e) { Message message = invalidLoggerClassErrorMessage.get(className, config.dn().toString(), String.valueOf(e)); throw new ConfigException(message, e); } } } opends/src/server/org/opends/server/loggers/AccessLogger.java
@@ -27,25 +27,16 @@ */ package org.opends.server.loggers; import static org.opends.messages.ConfigMessages.*; import static org.opends.server.loggers.debug.DebugLogger.*; import static org.opends.server.util.StaticUtils.*; import java.util.ArrayList; import java.util.List; import java.util.concurrent.CopyOnWriteArrayList; import java.util.Collection; import org.opends.messages.Message; import org.opends.server.admin.ClassPropertyDefinition; import org.opends.server.admin.server.ConfigurationAddListener; import org.opends.server.admin.server.ConfigurationChangeListener; import org.opends.server.admin.server.ConfigurationDeleteListener; import org.opends.server.admin.std.meta.AccessLogPublisherCfgDefn; import org.opends.server.admin.std.server.AccessLogPublisherCfg; import org.opends.server.api.AccessLogPublisher; import org.opends.server.api.ClientConnection; import org.opends.server.config.ConfigException; import org.opends.server.core.*; import org.opends.server.loggers.debug.DebugTracer; import org.opends.server.types.*; @@ -53,25 +44,42 @@ * This class defines the wrapper that will invoke all registered access loggers * for each type of request received or response sent. */ public class AccessLogger implements ConfigurationAddListener<AccessLogPublisherCfg>, ConfigurationDeleteListener<AccessLogPublisherCfg>, ConfigurationChangeListener<AccessLogPublisherCfg> public class AccessLogger extends AbstractLogger <AccessLogPublisher<AccessLogPublisherCfg>, AccessLogPublisherCfg> { /** * The tracer object for the debug logger. */ private static final DebugTracer TRACER = getTracer(); // The set of access loggers that have been registered with the server. It // will initially be empty. private static CopyOnWriteArrayList<AccessLogPublisher<?>> accessPublishers = new CopyOnWriteArrayList<AccessLogPublisher<?>>(); private static LoggerStorage <AccessLogPublisher<AccessLogPublisherCfg>, AccessLogPublisherCfg> loggerStorage = new LoggerStorage <AccessLogPublisher<AccessLogPublisherCfg>, AccessLogPublisherCfg>(); // The singleton instance of this class for configuration purposes. /** The singleton instance of this class for configuration purposes. */ private static final AccessLogger instance = new AccessLogger(); /** * The constructor for this class. */ public AccessLogger() { super((Class) AccessLogPublisher.class, ERR_CONFIG_LOGGER_INVALID_ACCESS_LOGGER_CLASS); } /** {@inheritDoc} */ @Override protected ClassPropertyDefinition getJavaClassPropertyDefinition() { return AccessLogPublisherCfgDefn.getInstance() .getJavaClassPropertyDefinition(); } /** {@inheritDoc} */ @Override protected LoggerStorage<AccessLogPublisher<AccessLogPublisherCfg>, AccessLogPublisherCfg> getStorage() { return loggerStorage; } /** * Retrieve the singleton instance of this class. @@ -89,9 +97,9 @@ * @param publisher The access log publisher to add. */ public synchronized static void addAccessLogPublisher( AccessLogPublisher<?> publisher) AccessLogPublisher publisher) { accessPublishers.add(publisher); loggerStorage.addLogPublisher(publisher); } /** @@ -101,16 +109,9 @@ * @return The publisher that was removed or null if it was not found. */ public synchronized static boolean removeAccessLogPublisher( AccessLogPublisher<?> publisher) AccessLogPublisher<AccessLogPublisherCfg> publisher) { boolean removed = accessPublishers.remove(publisher); if(removed) { publisher.close(); } return removed; return loggerStorage.removeLogPublisher(publisher); } /** @@ -118,274 +119,20 @@ */ public synchronized static void removeAllAccessLogPublishers() { for(AccessLogPublisher<?> publisher : accessPublishers) { publisher.close(); } accessPublishers.clear(); loggerStorage.removeAllLogPublishers(); } /** * Initializes all the access log publishers. * Returns all the registered access log publishers. * * @param configs The access log publisher configurations. * @throws ConfigException * If an unrecoverable problem arises in the process of * performing the initialization as a result of the server * configuration. * @throws InitializationException * If a problem occurs during initialization that is not * related to the server configuration. * @return a Collection of {@link AccessLogPublisher} objects */ public void initializeAccessLogger(List<AccessLogPublisherCfg> configs) throws ConfigException, InitializationException private static Collection <AccessLogPublisher<AccessLogPublisherCfg>> getAccessLogPublishers() { for(AccessLogPublisherCfg config : configs) { config.addAccessChangeListener(this); if(config.isEnabled()) { AccessLogPublisher<?> AccessLogPublisher = getAccessPublisher(config); addAccessLogPublisher(AccessLogPublisher); } } return loggerStorage.getLogPublishers(); } /** * {@inheritDoc} */ @Override public boolean isConfigurationAddAcceptable( AccessLogPublisherCfg config, List<Message> unacceptableReasons) { return !config.isEnabled() || isJavaClassAcceptable(config, unacceptableReasons); } /** * {@inheritDoc} */ @Override public boolean isConfigurationChangeAcceptable( AccessLogPublisherCfg config, List<Message> unacceptableReasons) { return !config.isEnabled() || isJavaClassAcceptable(config, unacceptableReasons); } /** * {@inheritDoc} */ @Override public ConfigChangeResult applyConfigurationAdd(AccessLogPublisherCfg config) { // Default result code. ResultCode resultCode = ResultCode.SUCCESS; boolean adminActionRequired = false; ArrayList<Message> messages = new ArrayList<Message>(); config.addAccessChangeListener(this); if(config.isEnabled()) { try { AccessLogPublisher<?> AccessLogPublisher = getAccessPublisher(config); addAccessLogPublisher(AccessLogPublisher); } catch(ConfigException e) { if (debugEnabled()) { TRACER.debugCaught(DebugLogLevel.ERROR, e); } messages.add(e.getMessageObject()); resultCode = DirectoryServer.getServerErrorResultCode(); } catch (Exception e) { if (debugEnabled()) { TRACER.debugCaught(DebugLogLevel.ERROR, e); } messages.add(ERR_CONFIG_LOGGER_CANNOT_CREATE_LOGGER.get( String.valueOf(config.dn().toString()), stackTraceToSingleLineString(e))); resultCode = DirectoryServer.getServerErrorResultCode(); } } return new ConfigChangeResult(resultCode, adminActionRequired, messages); } /** * {@inheritDoc} */ @Override public ConfigChangeResult applyConfigurationChange( AccessLogPublisherCfg config) { // Default result code. ResultCode resultCode = ResultCode.SUCCESS; boolean adminActionRequired = false; ArrayList<Message> messages = new ArrayList<Message>(); DN dn = config.dn(); AccessLogPublisher<?> accessLogPublisher = null; for(AccessLogPublisher<?> publisher : accessPublishers) { if(publisher.getDN().equals(dn)) { accessLogPublisher = publisher; break; } } if(accessLogPublisher == null) { if(config.isEnabled()) { // Needs to be added and enabled. return applyConfigurationAdd(config); } } else { if(config.isEnabled()) { // The publisher is currently active, so we don't need to do anything. // Changes to the class name cannot be // applied dynamically, so if the class name did change then // indicate that administrative action is required for that // change to take effect. String className = config.getJavaClass(); if(!className.equals(accessLogPublisher.getClass().getName())) { adminActionRequired = true; } } else { // The publisher is being disabled so shut down and remove. removeAccessLogPublisher(accessLogPublisher); } } return new ConfigChangeResult(resultCode, adminActionRequired, messages); } /** * {@inheritDoc} */ @Override public boolean isConfigurationDeleteAcceptable( AccessLogPublisherCfg config, List<Message> unacceptableReasons) { DN dn = config.dn(); AccessLogPublisher<?> accessLogPublisher = null; for(AccessLogPublisher<?> publisher : accessPublishers) { if(publisher.getDN().equals(dn)) { accessLogPublisher = publisher; break; } } return accessLogPublisher != null; } /** * {@inheritDoc} */ @Override public ConfigChangeResult applyConfigurationDelete( AccessLogPublisherCfg config) { // Default result code. ResultCode resultCode = ResultCode.SUCCESS; boolean adminActionRequired = false; AccessLogPublisher<?> accessLogPublisher = null; for(AccessLogPublisher<?> publisher : accessPublishers) { if(publisher.getDN().equals(config.dn())) { accessLogPublisher = publisher; break; } } if(accessLogPublisher != null) { removeAccessLogPublisher(accessLogPublisher); } else { resultCode = ResultCode.NO_SUCH_OBJECT; } return new ConfigChangeResult(resultCode, adminActionRequired); } @SuppressWarnings("unchecked") private boolean isJavaClassAcceptable(AccessLogPublisherCfg config, List<Message> unacceptableReasons) { String className = config.getJavaClass(); AccessLogPublisherCfgDefn d = AccessLogPublisherCfgDefn.getInstance(); ClassPropertyDefinition pd = d.getJavaClassPropertyDefinition(); try { // Load the class and cast it to a AccessLogPublisher. AccessLogPublisher<AccessLogPublisherCfg> publisher = pd.loadClass(className, AccessLogPublisher.class).newInstance(); // The class is valid as far as we can tell. return publisher.isConfigurationAcceptable(config, unacceptableReasons); } catch (Exception e) { Message message = ERR_CONFIG_LOGGER_INVALID_ACCESS_LOGGER_CLASS.get( className, config.dn().toString(), String.valueOf(e)); unacceptableReasons.add(message); return false; } } private AccessLogPublisher<?> getAccessPublisher(AccessLogPublisherCfg config) throws ConfigException { String className = config.getJavaClass(); AccessLogPublisherCfgDefn d = AccessLogPublisherCfgDefn.getInstance(); ClassPropertyDefinition pd = d.getJavaClassPropertyDefinition(); try { // Load the class and cast it to a AccessLogPublisher. AccessLogPublisher<AccessLogPublisherCfg> accessLogPublisher = pd.loadClass(className, AccessLogPublisher.class).newInstance(); accessLogPublisher.initializeLogPublisher(config); // The access publisher has been successfully initialized. return accessLogPublisher; } catch (Exception e) { Message message = ERR_CONFIG_LOGGER_INVALID_ACCESS_LOGGER_CLASS.get( className, config.dn().toString(), String.valueOf(e)); throw new ConfigException(message, e); } } /** * Writes a message to the access logger with information about a new client @@ -396,7 +143,7 @@ */ public static void logConnect(ClientConnection clientConnection) { for (AccessLogPublisher<?> publisher : accessPublishers) for (AccessLogPublisher<?> publisher : getAccessLogPublishers()) { publisher.logConnect(clientConnection); } @@ -418,7 +165,7 @@ DisconnectReason disconnectReason, Message message) { for (AccessLogPublisher<?> publisher : accessPublishers) for (AccessLogPublisher<?> publisher : getAccessLogPublishers()) { publisher.logDisconnect(clientConnection, disconnectReason, message); } @@ -435,7 +182,7 @@ */ public static void logAbandonRequest(AbandonOperation abandonOperation) { for (AccessLogPublisher<?> publisher : accessPublishers) for (AccessLogPublisher<?> publisher : getAccessLogPublishers()) { publisher.logAbandonRequest(abandonOperation); } @@ -452,7 +199,7 @@ */ public static void logAbandonResult(AbandonOperation abandonOperation) { for (AccessLogPublisher<?> publisher : accessPublishers) for (AccessLogPublisher<?> publisher : getAccessLogPublishers()) { publisher.logAbandonResult(abandonOperation); } @@ -469,7 +216,7 @@ */ public static void logAddRequest(AddOperation addOperation) { for (AccessLogPublisher<?> publisher : accessPublishers) for (AccessLogPublisher<?> publisher : getAccessLogPublishers()) { publisher.logAddRequest(addOperation); } @@ -486,7 +233,7 @@ */ public static void logAddResponse(AddOperation addOperation) { for (AccessLogPublisher<?> publisher : accessPublishers) for (AccessLogPublisher<?> publisher : getAccessLogPublishers()) { publisher.logAddResponse(addOperation); } @@ -503,7 +250,7 @@ */ public static void logBindRequest(BindOperation bindOperation) { for (AccessLogPublisher<?> publisher : accessPublishers) for (AccessLogPublisher<?> publisher : getAccessLogPublishers()) { publisher.logBindRequest(bindOperation); } @@ -520,7 +267,7 @@ */ public static void logBindResponse(BindOperation bindOperation) { for (AccessLogPublisher<?> publisher : accessPublishers) for (AccessLogPublisher<?> publisher : getAccessLogPublishers()) { publisher.logBindResponse(bindOperation); } @@ -537,7 +284,7 @@ */ public static void logCompareRequest(CompareOperation compareOperation) { for (AccessLogPublisher<?> publisher : accessPublishers) for (AccessLogPublisher<?> publisher : getAccessLogPublishers()) { publisher.logCompareRequest(compareOperation); } @@ -554,7 +301,7 @@ */ public static void logCompareResponse(CompareOperation compareOperation) { for (AccessLogPublisher<?> publisher : accessPublishers) for (AccessLogPublisher<?> publisher : getAccessLogPublishers()) { publisher.logCompareResponse(compareOperation); } @@ -571,7 +318,7 @@ */ public static void logDeleteRequest(DeleteOperation deleteOperation) { for (AccessLogPublisher<?> publisher : accessPublishers) for (AccessLogPublisher<?> publisher : getAccessLogPublishers()) { publisher.logDeleteRequest(deleteOperation); } @@ -588,7 +335,7 @@ */ public static void logDeleteResponse(DeleteOperation deleteOperation) { for (AccessLogPublisher<?> publisher : accessPublishers) for (AccessLogPublisher<?> publisher : getAccessLogPublishers()) { publisher.logDeleteResponse(deleteOperation); } @@ -605,7 +352,7 @@ */ public static void logExtendedRequest(ExtendedOperation extendedOperation) { for (AccessLogPublisher<?> publisher : accessPublishers) for (AccessLogPublisher<?> publisher : getAccessLogPublishers()) { publisher.logExtendedRequest(extendedOperation); } @@ -622,7 +369,7 @@ */ public static void logExtendedResponse(ExtendedOperation extendedOperation) { for (AccessLogPublisher<?> publisher : accessPublishers) for (AccessLogPublisher<?> publisher : getAccessLogPublishers()) { publisher.logExtendedResponse(extendedOperation); } @@ -639,7 +386,7 @@ */ public static void logModifyRequest(ModifyOperation modifyOperation) { for (AccessLogPublisher<?> publisher : accessPublishers) for (AccessLogPublisher<?> publisher : getAccessLogPublishers()) { publisher.logModifyRequest(modifyOperation); } @@ -656,7 +403,7 @@ */ public static void logModifyResponse(ModifyOperation modifyOperation) { for (AccessLogPublisher<?> publisher : accessPublishers) for (AccessLogPublisher<?> publisher : getAccessLogPublishers()) { publisher.logModifyResponse(modifyOperation); } @@ -673,7 +420,7 @@ */ public static void logModifyDNRequest(ModifyDNOperation modifyDNOperation) { for (AccessLogPublisher<?> publisher : accessPublishers) for (AccessLogPublisher<?> publisher : getAccessLogPublishers()) { publisher.logModifyDNRequest(modifyDNOperation); } @@ -691,7 +438,7 @@ */ public static void logModifyDNResponse(ModifyDNOperation modifyDNOperation) { for (AccessLogPublisher<?> publisher : accessPublishers) for (AccessLogPublisher<?> publisher : getAccessLogPublishers()) { publisher.logModifyDNResponse(modifyDNOperation); } @@ -708,7 +455,7 @@ */ public static void logSearchRequest(SearchOperation searchOperation) { for (AccessLogPublisher<?> publisher : accessPublishers) for (AccessLogPublisher<?> publisher : getAccessLogPublishers()) { publisher.logSearchRequest(searchOperation); } @@ -728,7 +475,7 @@ public static void logSearchResultEntry(SearchOperation searchOperation, SearchResultEntry searchEntry) { for (AccessLogPublisher<?> publisher : accessPublishers) for (AccessLogPublisher<?> publisher : getAccessLogPublishers()) { publisher.logSearchResultEntry(searchOperation, searchEntry); } @@ -747,7 +494,7 @@ public static void logSearchResultReference(SearchOperation searchOperation, SearchResultReference searchReference) { for (AccessLogPublisher<?> publisher : accessPublishers) for (AccessLogPublisher<?> publisher : getAccessLogPublishers()) { publisher.logSearchResultReference(searchOperation, searchReference); } @@ -764,7 +511,7 @@ */ public static void logSearchResultDone(SearchOperation searchOperation) { for (AccessLogPublisher<?> publisher : accessPublishers) for (AccessLogPublisher<?> publisher : getAccessLogPublishers()) { publisher.logSearchResultDone(searchOperation); } @@ -781,7 +528,7 @@ */ public static void logUnbind(UnbindOperation unbindOperation) { for (AccessLogPublisher<?> publisher : accessPublishers) for (AccessLogPublisher<?> publisher : getAccessLogPublishers()) { publisher.logUnbind(unbindOperation); } opends/src/server/org/opends/server/loggers/ErrorLogger.java
@@ -28,53 +28,30 @@ package org.opends.server.loggers; import static org.opends.messages.ConfigMessages.*; import static org.opends.server.loggers.debug.DebugLogger.*; import static org.opends.server.util.StaticUtils.*; import java.util.ArrayList; import java.util.List; import java.util.concurrent.CopyOnWriteArrayList; import org.opends.messages.Message; import org.opends.server.admin.ClassPropertyDefinition; import org.opends.server.admin.server.ConfigurationAddListener; import org.opends.server.admin.server.ConfigurationChangeListener; import org.opends.server.admin.server.ConfigurationDeleteListener; import org.opends.server.admin.std.meta.ErrorLogPublisherCfgDefn; import org.opends.server.admin.std.server.ErrorLogPublisherCfg; import org.opends.server.api.DirectoryThread; import org.opends.server.api.ErrorLogPublisher; import org.opends.server.backends.task.Task; import org.opends.server.config.ConfigException; import org.opends.server.core.DirectoryServer; import org.opends.server.loggers.debug.DebugTracer; import org.opends.server.types.ConfigChangeResult; import org.opends.server.types.DN; import org.opends.server.types.DebugLogLevel; import org.opends.server.types.InitializationException; import org.opends.server.types.ResultCode; /** * This class defines the wrapper that will invoke all registered error loggers * for each type of request received or response sent. If no error log * publishers are registered, messages will be directed to standard out. */ public class ErrorLogger implements ConfigurationAddListener<ErrorLogPublisherCfg>, ConfigurationDeleteListener<ErrorLogPublisherCfg>, ConfigurationChangeListener<ErrorLogPublisherCfg> public class ErrorLogger extends AbstractLogger <ErrorLogPublisher<ErrorLogPublisherCfg>, ErrorLogPublisherCfg> { /** * The tracer object for the debug logger. */ private static final DebugTracer TRACER = getTracer(); // The set of error loggers that have been registered with the server. It // will initially be empty. private static CopyOnWriteArrayList<ErrorLogPublisher> errorPublishers = new CopyOnWriteArrayList<ErrorLogPublisher>(); private static LoggerStorage <ErrorLogPublisher<ErrorLogPublisherCfg>, ErrorLogPublisherCfg> loggerStorage = new LoggerStorage <ErrorLogPublisher<ErrorLogPublisherCfg>, ErrorLogPublisherCfg>(); // The singleton instance of this class for configuration purposes. /** The singleton instance of this class for configuration purposes. */ private static final ErrorLogger instance = new ErrorLogger(); /** @@ -88,6 +65,31 @@ } /** * The constructor for this class. */ public ErrorLogger() { super((Class) ErrorLogPublisher.class, ERR_CONFIG_LOGGER_INVALID_ERROR_LOGGER_CLASS); } /** {@inheritDoc} */ @Override protected ClassPropertyDefinition getJavaClassPropertyDefinition() { return ErrorLogPublisherCfgDefn.getInstance() .getJavaClassPropertyDefinition(); } /** {@inheritDoc} */ @Override protected LoggerStorage<ErrorLogPublisher<ErrorLogPublisherCfg>, ErrorLogPublisherCfg> getStorage() { return loggerStorage; } /** * Add an error log publisher to the error logger. * * @param publisher The error log publisher to add. @@ -95,7 +97,7 @@ public synchronized static void addErrorLogPublisher( ErrorLogPublisher publisher) { errorPublishers.add(publisher); loggerStorage.addLogPublisher(publisher); } /** @@ -107,14 +109,7 @@ public synchronized static boolean removeErrorLogPublisher( ErrorLogPublisher publisher) { boolean removed = errorPublishers.remove(publisher); if(removed) { publisher.close(); } return removed; return loggerStorage.removeLogPublisher(publisher); } /** @@ -122,278 +117,17 @@ */ public synchronized static void removeAllErrorLogPublishers() { for(ErrorLogPublisher publisher : errorPublishers) { publisher.close(); } errorPublishers.clear(); loggerStorage.removeAllLogPublishers(); } /** * Initializes all the error log publishers. * * @param configs The error log publisher configurations. * @throws ConfigException * If an unrecoverable problem arises in the process of * performing the initialization as a result of the server * configuration. * @throws InitializationException * If a problem occurs during initialization that is not * related to the server configuration. */ public void initializeErrorLogger(List<ErrorLogPublisherCfg> configs) throws ConfigException, InitializationException { for(ErrorLogPublisherCfg config : configs) { config.addErrorChangeListener(this); if(config.isEnabled()) { ErrorLogPublisher errorLogPublisher = getErrorPublisher(config); addErrorLogPublisher(errorLogPublisher); } } } /** * {@inheritDoc} */ @Override public boolean isConfigurationAddAcceptable(ErrorLogPublisherCfg config, List<Message> unacceptableReasons) { return !config.isEnabled() || isJavaClassAcceptable(config, unacceptableReasons); } /** * {@inheritDoc} */ @Override public boolean isConfigurationChangeAcceptable( ErrorLogPublisherCfg config, List<Message> unacceptableReasons) { return !config.isEnabled() || isJavaClassAcceptable(config, unacceptableReasons); } /** * {@inheritDoc} */ @Override public ConfigChangeResult applyConfigurationAdd(ErrorLogPublisherCfg config) { // Default result code. ResultCode resultCode = ResultCode.SUCCESS; boolean adminActionRequired = false; ArrayList<Message> messages = new ArrayList<Message>(); config.addErrorChangeListener(this); if(config.isEnabled()) { try { ErrorLogPublisher errorLogPublisher = getErrorPublisher(config); addErrorLogPublisher(errorLogPublisher); } catch(ConfigException e) { if (debugEnabled()) { TRACER.debugCaught(DebugLogLevel.ERROR, e); } messages.add(e.getMessageObject()); resultCode = DirectoryServer.getServerErrorResultCode(); } catch (Exception e) { if (debugEnabled()) { TRACER.debugCaught(DebugLogLevel.ERROR, e); } messages.add(ERR_CONFIG_LOGGER_CANNOT_CREATE_LOGGER.get( String.valueOf(config.dn().toString()), stackTraceToSingleLineString(e))); resultCode = DirectoryServer.getServerErrorResultCode(); } } return new ConfigChangeResult(resultCode, adminActionRequired, messages); } /** * {@inheritDoc} */ @Override public ConfigChangeResult applyConfigurationChange( ErrorLogPublisherCfg config) { // Default result code. ResultCode resultCode = ResultCode.SUCCESS; boolean adminActionRequired = false; ArrayList<Message> messages = new ArrayList<Message>(); DN dn = config.dn(); ErrorLogPublisher errorLogPublisher = null; for(ErrorLogPublisher publisher : errorPublishers) { if(publisher.getDN().equals(dn)) { errorLogPublisher = publisher; break; } } if(errorLogPublisher == null) { if(config.isEnabled()) { // Needs to be added and enabled. return applyConfigurationAdd(config); } } else { if(config.isEnabled()) { // The publisher is currently active, so we don't need to do anything. // Changes to the class name cannot be // applied dynamically, so if the class name did change then // indicate that administrative action is required for that // change to take effect. String className = config.getJavaClass(); if(!className.equals(errorLogPublisher.getClass().getName())) { adminActionRequired = true; } } else { // The publisher is being disabled so shut down and remove. removeErrorLogPublisher(errorLogPublisher); } } return new ConfigChangeResult(resultCode, adminActionRequired, messages); } /** * {@inheritDoc} */ @Override public boolean isConfigurationDeleteAcceptable( ErrorLogPublisherCfg config, List<Message> unacceptableReasons) { DN dn = config.dn(); ErrorLogPublisher errorLogPublisher = null; for(ErrorLogPublisher publisher : errorPublishers) { if(publisher.getDN().equals(dn)) { errorLogPublisher = publisher; break; } } return errorLogPublisher != null; } /** * {@inheritDoc} */ @Override public ConfigChangeResult applyConfigurationDelete( ErrorLogPublisherCfg config) { // Default result code. ResultCode resultCode = ResultCode.SUCCESS; boolean adminActionRequired = false; ErrorLogPublisher errorLogPublisher = null; for(ErrorLogPublisher publisher : errorPublishers) { if(publisher.getDN().equals(config.dn())) { errorLogPublisher = publisher; break; } } if(errorLogPublisher != null) { removeErrorLogPublisher(errorLogPublisher); } else { resultCode = ResultCode.NO_SUCH_OBJECT; } return new ConfigChangeResult(resultCode, adminActionRequired); } private boolean isJavaClassAcceptable(ErrorLogPublisherCfg config, List<Message> unacceptableReasons) { String className = config.getJavaClass(); ErrorLogPublisherCfgDefn d = ErrorLogPublisherCfgDefn.getInstance(); ClassPropertyDefinition pd = d.getJavaClassPropertyDefinition(); try { // Load the class and cast it to a ErrorLogPublisher. ErrorLogPublisher<ErrorLogPublisherCfg> publisher = pd.loadClass(className, ErrorLogPublisher.class).newInstance(); // The class is valid as far as we can tell. return publisher.isConfigurationAcceptable(config, unacceptableReasons); } catch (Exception e) { Message message = ERR_CONFIG_LOGGER_INVALID_ERROR_LOGGER_CLASS.get( className, config.dn().toString(), String.valueOf(e)); unacceptableReasons.add(message); return false; } } private ErrorLogPublisher getErrorPublisher(ErrorLogPublisherCfg config) throws ConfigException { String className = config.getJavaClass(); ErrorLogPublisherCfgDefn d = ErrorLogPublisherCfgDefn.getInstance(); ClassPropertyDefinition pd = d.getJavaClassPropertyDefinition(); try { // Load the class and cast it to a ErrorLogPublisher. ErrorLogPublisher<ErrorLogPublisherCfg> errorLogPublisher = pd.loadClass(className, ErrorLogPublisher.class).newInstance(); errorLogPublisher.initializeLogPublisher(config); // The error publisher has been successfully initialized. return errorLogPublisher; } catch (Exception e) { Message message = ERR_CONFIG_LOGGER_INVALID_ERROR_LOGGER_CLASS.get( className, config.dn().toString(), String.valueOf(e)); throw new ConfigException(message, e); } } /** * Writes a message to the error log using the provided information. * * @param message The message to be logged. */ public static void logError(Message message) { for (ErrorLogPublisher publisher : errorPublishers) for (ErrorLogPublisher publisher : loggerStorage.getLogPublishers()) { publisher.logError(message); } @@ -409,4 +143,3 @@ } } } opends/src/server/org/opends/server/loggers/debug/DebugLogger.java
@@ -26,30 +26,19 @@ * Portions Copyright 2013 ForgeRock AS */ package org.opends.server.loggers.debug; import static org.opends.messages.ConfigMessages.*; import static org.opends.server.util.StaticUtils.*; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.CopyOnWriteArrayList; import org.opends.messages.Message; import org.opends.server.admin.ClassPropertyDefinition; import org.opends.server.admin.server.ConfigurationAddListener; import org.opends.server.admin.server.ConfigurationChangeListener; import org.opends.server.admin.server.ConfigurationDeleteListener; import org.opends.server.admin.std.meta.DebugLogPublisherCfgDefn; import org.opends.server.admin.std.server.DebugLogPublisherCfg; import org.opends.server.api.DebugLogPublisher; import org.opends.server.config.ConfigException; import org.opends.server.core.DirectoryServer; import org.opends.server.loggers.AbstractLogger; import org.opends.server.loggers.LogLevel; import org.opends.server.types.ConfigChangeResult; import org.opends.server.types.DN; import org.opends.server.types.DebugLogLevel; import org.opends.server.types.InitializationException; import org.opends.server.types.ResultCode; /** * A logger for debug and trace logging. DebugLogger provides a debugging @@ -63,46 +52,71 @@ * * DebugLogger is self-initializing. */ public class DebugLogger implements ConfigurationAddListener<DebugLogPublisherCfg>, ConfigurationDeleteListener<DebugLogPublisherCfg>, ConfigurationChangeListener<DebugLogPublisherCfg> public class DebugLogger extends AbstractLogger <DebugLogPublisher<DebugLogPublisherCfg>, DebugLogPublisherCfg> { //The default level to log constructor exectuions. /** The default level to log constructor executions. */ static final LogLevel DEFAULT_CONSTRUCTOR_LEVEL = DebugLogLevel.VERBOSE; //The default level to log method entry and exit pointcuts. /** The default level to log method entry and exit pointcuts. */ static final LogLevel DEFAULT_ENTRY_EXIT_LEVEL = DebugLogLevel.VERBOSE; //The default level to log method entry and exit pointcuts. /** The default level to log method entry and exit pointcuts. */ static final LogLevel DEFAULT_THROWN_LEVEL = DebugLogLevel.ERROR; // The set of all DebugTracer instances. private static ConcurrentHashMap<String, DebugTracer> classTracers = /** The set of all DebugTracer instances. */ private static Map<String, DebugTracer> classTracers = new ConcurrentHashMap<String, DebugTracer>(); // The set of debug loggers that have been registered with the server. It // will initially be empty. private static CopyOnWriteArrayList<DebugLogPublisher> debugPublishers = new CopyOnWriteArrayList<DebugLogPublisher>(); // Trace methods will use this static boolean to determine if debug is // enabled so to not incur the cost of calling debugPublishers.isEmtpty(). /** * Trace methods will use this static boolean to determine if debug is enabled * so to not incur the cost of calling debugPublishers.isEmpty(). */ static boolean enabled = false; // The singleton instance of this class for configuration purposes. private static final LoggerStorage <DebugLogPublisher<DebugLogPublisherCfg>, DebugLogPublisherCfg> loggerStorage = new LoggerStorage <DebugLogPublisher<DebugLogPublisherCfg>, DebugLogPublisherCfg>(); /** The singleton instance of this class for configuration purposes. */ static final DebugLogger instance = new DebugLogger(); /** * The constructor for this class. */ public DebugLogger() { super((Class) DebugLogPublisher.class, ERR_CONFIG_LOGGER_INVALID_DEBUG_LOGGER_CLASS); } /** {@inheritDoc} */ @Override protected ClassPropertyDefinition getJavaClassPropertyDefinition() { return DebugLogPublisherCfgDefn.getInstance() .getJavaClassPropertyDefinition(); } /** {@inheritDoc} */ @Override protected LoggerStorage<DebugLogPublisher<DebugLogPublisherCfg>, DebugLogPublisherCfg> getStorage() { return loggerStorage; } /** * Add an debug log publisher to the debug logger. * * @param publisher The error log publisher to add. * @param publisher The debug log publisher to add. */ public synchronized static void addDebugLogPublisher( DebugLogPublisher publisher) { debugPublishers.add(publisher); loggerStorage.addLogPublisher(publisher); updateTracerSettings(); @@ -118,19 +132,11 @@ public synchronized static boolean removeDebugLogPublisher( DebugLogPublisher publisher) { boolean removed = debugPublishers.remove(publisher); if(removed) { publisher.close(); } boolean removed = loggerStorage.removeLogPublisher(publisher); updateTracerSettings(); if(debugPublishers.isEmpty()) { enabled = false; } enabled = !loggerStorage.getLogPublishers().isEmpty(); return removed; } @@ -140,12 +146,7 @@ */ public synchronized static void removeAllDebugLogPublishers() { for(DebugLogPublisher publisher : debugPublishers) { publisher.close(); } debugPublishers.clear(); loggerStorage.removeAllLogPublishers(); updateTracerSettings(); @@ -153,256 +154,13 @@ } /** * Initializes all the debug log publishers. * * @param configs The debug log publisher configurations. * @throws ConfigException * If an unrecoverable problem arises in the process of * performing the initialization as a result of the server * configuration. * @throws InitializationException * If a problem occurs during initialization that is not * related to the server configuration. */ public void initializeDebugLogger(List<DebugLogPublisherCfg> configs) throws ConfigException, InitializationException { for(DebugLogPublisherCfg config : configs) { config.addDebugChangeListener(this); if(config.isEnabled()) { DebugLogPublisher debugLogPublisher = getDebugPublisher(config); addDebugLogPublisher(debugLogPublisher); } } } /** * {@inheritDoc} */ @Override public boolean isConfigurationAddAcceptable(DebugLogPublisherCfg config, List<Message> unacceptableReasons) { return !config.isEnabled() || isJavaClassAcceptable(config, unacceptableReasons); } /** * {@inheritDoc} */ @Override public boolean isConfigurationChangeAcceptable(DebugLogPublisherCfg config, List<Message> unacceptableReasons) { return !config.isEnabled() || isJavaClassAcceptable(config, unacceptableReasons); } /** * {@inheritDoc} */ @Override public ConfigChangeResult applyConfigurationAdd(DebugLogPublisherCfg config) { // Default result code. ResultCode resultCode = ResultCode.SUCCESS; boolean adminActionRequired = false; ArrayList<Message> messages = new ArrayList<Message>(); config.addDebugChangeListener(this); if(config.isEnabled()) { try { DebugLogPublisher debugLogPublisher = getDebugPublisher(config); addDebugLogPublisher(debugLogPublisher); } catch(ConfigException e) { messages.add(e.getMessageObject()); resultCode = DirectoryServer.getServerErrorResultCode(); } catch (Exception e) { messages.add(ERR_CONFIG_LOGGER_CANNOT_CREATE_LOGGER.get( String.valueOf(config.dn().toString()), stackTraceToSingleLineString(e))); resultCode = DirectoryServer.getServerErrorResultCode(); } } return new ConfigChangeResult(resultCode, adminActionRequired, messages); } /** * {@inheritDoc} */ @Override public ConfigChangeResult applyConfigurationChange( DebugLogPublisherCfg config) { // Default result code. ResultCode resultCode = ResultCode.SUCCESS; boolean adminActionRequired = false; ArrayList<Message> messages = new ArrayList<Message>(); DN dn = config.dn(); DebugLogPublisher debugLogPublisher = null; for(DebugLogPublisher publisher : debugPublishers) { if(publisher.getDN().equals(dn)) { debugLogPublisher = publisher; } } if(debugLogPublisher == null) { if(config.isEnabled()) { // Needs to be added and enabled. return applyConfigurationAdd(config); } } else { if(config.isEnabled()) { // The publisher is currently active, so we don't need to do anything. // Changes to the class name cannot be // applied dynamically, so if the class name did change then // indicate that administrative action is required for that // change to take effect. String className = config.getJavaClass(); if(!className.equals(debugLogPublisher.getClass().getName())) { adminActionRequired = true; } } else { // The publisher is being disabled so shut down and remove. removeDebugLogPublisher(debugLogPublisher); } } return new ConfigChangeResult(resultCode, adminActionRequired, messages); } /** * {@inheritDoc} */ @Override public boolean isConfigurationDeleteAcceptable(DebugLogPublisherCfg config, List<Message> unacceptableReasons) { DN dn = config.dn(); DebugLogPublisher debugLogPublisher = null; for(DebugLogPublisher publisher : debugPublishers) { if(publisher.getDN().equals(dn)) { debugLogPublisher = publisher; } } return debugLogPublisher != null; } /** * {@inheritDoc} */ @Override public ConfigChangeResult applyConfigurationDelete(DebugLogPublisherCfg config) { // Default result code. ResultCode resultCode = ResultCode.SUCCESS; boolean adminActionRequired = false; DebugLogPublisher debugLogPublisher = null; for(DebugLogPublisher publisher : debugPublishers) { if(publisher.getDN().equals(config.dn())) { debugLogPublisher = publisher; } } if(debugLogPublisher != null) { removeDebugLogPublisher(debugLogPublisher); } else { resultCode = ResultCode.NO_SUCH_OBJECT; } return new ConfigChangeResult(resultCode, adminActionRequired); } private boolean isJavaClassAcceptable(DebugLogPublisherCfg config, List<Message> unacceptableReasons) { String className = config.getJavaClass(); DebugLogPublisherCfgDefn d = DebugLogPublisherCfgDefn.getInstance(); ClassPropertyDefinition pd = d.getJavaClassPropertyDefinition(); try { // Load the class and cast it to a DebugLogPublisher. DebugLogPublisher<DebugLogPublisherCfg> publisher = pd.loadClass(className, DebugLogPublisher.class).newInstance(); // The class is valid as far as we can tell. return publisher.isConfigurationAcceptable(config, unacceptableReasons); } catch (Exception e) { Message message = ERR_CONFIG_LOGGER_INVALID_DEBUG_LOGGER_CLASS.get( className, config.dn().toString(), String.valueOf(e)); unacceptableReasons.add(message); return false; } } private DebugLogPublisher getDebugPublisher(DebugLogPublisherCfg config) throws ConfigException { String className = config.getJavaClass(); DebugLogPublisherCfgDefn d = DebugLogPublisherCfgDefn.getInstance(); ClassPropertyDefinition pd = d.getJavaClassPropertyDefinition(); try { // Load the class and cast it to a DebugLogPublisher. DebugLogPublisher<DebugLogPublisherCfg> debugLogPublisher = pd.loadClass(className, DebugLogPublisher.class).newInstance(); debugLogPublisher.initializeLogPublisher(config); // The debug publisher has been successfully initialized. return debugLogPublisher; } catch (Exception e) { Message message = ERR_CONFIG_LOGGER_INVALID_DEBUG_LOGGER_CLASS.get( className, config.dn().toString(), String.valueOf(e)); throw new ConfigException(message, e); } } /** * Update all debug tracers with the settings in the registered * publishers. */ static void updateTracerSettings() { DebugLogPublisher[] publishers = debugPublishers.toArray(new DebugLogPublisher[0]); DebugLogPublisher<DebugLogPublisherCfg>[] publishers = loggerStorage.getLogPublishers().toArray(new DebugLogPublisher[0]); for(DebugTracer tracer : classTracers.values()) { @@ -439,7 +197,8 @@ public static DebugTracer getTracer() { DebugTracer tracer = new DebugTracer(debugPublishers.toArray(new DebugLogPublisher[0])); new DebugTracer(loggerStorage.getLogPublishers().toArray( new DebugLogPublisher[0])); classTracers.put(tracer.getTracedClassName(), tracer); return tracer; opends/src/server/org/opends/server/util/StaticUtils.java
@@ -51,6 +51,7 @@ import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Date; import java.util.Enumeration; @@ -4622,6 +4623,25 @@ */ public static void close(Closeable... closeables) { if (closeables == null) { return; } close(Arrays.asList(closeables)); } /** * Closes the provided {@link Closeable}'s ignoring any errors which occurred. * * @param closeables * The closeables to be closed, which may be <code>null</code>. */ public static void close(Collection<Closeable> closeables) { if (closeables == null) { return; } for (Closeable closeable : closeables) { if (closeable != null)