6209N/A/*
6209N/A * CDDL HEADER START
6209N/A *
6209N/A * The contents of this file are subject to the terms of the
6209N/A * Common Development and Distribution License, Version 1.0 only
6209N/A * (the "License"). You may not use this file except in compliance
6209N/A * with the License.
6209N/A *
6983N/A * You can obtain a copy of the license at legal-notices/CDDLv1_0.txt
6983N/A * or http://forgerock.org/license/CDDLv1.0.html.
6209N/A * See the License for the specific language governing permissions
6209N/A * and limitations under the License.
6209N/A *
6209N/A * When distributing Covered Code, include this CDDL HEADER in each
6983N/A * file and include the License file at legal-notices/CDDLv1_0.txt.
6983N/A * If applicable, add the following below this CDDL HEADER, with the
6983N/A * fields enclosed by brackets "[]" replaced with your own identifying
6983N/A * information:
6209N/A * Portions Copyright [yyyy] [name of copyright owner]
6209N/A *
6209N/A * CDDL HEADER END
6209N/A *
6209N/A *
6209N/A * Copyright 2006-2008 Sun Microsystems, Inc.
6209N/A * Portions copyright 2011-2013 ForgeRock AS.
6209N/A */
6209N/Apackage org.opends.server.loggers;
6209N/A
6209N/Aimport static org.opends.messages.ConfigMessages.*;
6209N/Aimport static org.opends.server.util.StaticUtils.*;
6209N/A
6209N/Aimport java.util.ArrayList;
6209N/Aimport java.util.Collection;
6209N/Aimport java.util.List;
6209N/Aimport java.util.concurrent.CopyOnWriteArrayList;
6209N/A
6209N/Aimport org.opends.messages.Message;
6209N/Aimport org.opends.messages.MessageDescriptor.Arg3;
6209N/Aimport org.opends.server.admin.ClassPropertyDefinition;
6209N/Aimport org.opends.server.admin.server.ConfigurationAddListener;
6209N/Aimport org.opends.server.admin.server.ConfigurationChangeListener;
6209N/Aimport org.opends.server.admin.server.ConfigurationDeleteListener;
6209N/Aimport org.opends.server.admin.std.server.LogPublisherCfg;
6209N/Aimport org.opends.server.api.LogPublisher;
6209N/Aimport org.opends.server.config.ConfigException;
6209N/Aimport org.opends.server.core.DirectoryServer;
6209N/Aimport org.opends.server.loggers.debug.DebugLogger;
6209N/Aimport org.opends.server.types.ConfigChangeResult;
6209N/Aimport org.opends.server.types.DN;
6209N/Aimport org.opends.server.types.DebugLogLevel;
6209N/Aimport org.opends.server.types.InitializationException;
6209N/Aimport org.opends.server.types.ResultCode;
6209N/Aimport org.opends.server.util.StaticUtils;
6209N/A
6209N/A/**
6209N/A * This class defines the wrapper that will invoke all registered loggers for
6209N/A * each type of request received or response sent. If no log publishers are
6209N/A * registered, messages will be directed to standard out.
6209N/A *
6209N/A * @param <P>
6209N/A * The type of the LogPublisher corresponding to this logger
6209N/A * @param <C>
6209N/A * The type of the LogPublisherCfg corresponding to this logger
6209N/A */
6209N/Apublic abstract class AbstractLogger
6209N/A <P extends LogPublisher<C>, C extends LogPublisherCfg>
6209N/A implements ConfigurationAddListener<C>, ConfigurationDeleteListener<C>,
6209N/A ConfigurationChangeListener<C>
6209N/A{
6209N/A
6209N/A /**
6209N/A * The storage designed to store log publishers. It is helpful in abstracting
6209N/A * away the methods used to manage the collection.
6209N/A *
6209N/A * @param <P>
6209N/A * The concrete {@link LogPublisher} type
6209N/A * @param <C>
6209N/A * The concrete {@link LogPublisherCfg} type
6209N/A */
6209N/A protected static class LoggerStorage<P extends LogPublisher<C>,
6209N/A C extends LogPublisherCfg>
6209N/A {
6209N/A /**
6209N/A * Defined as public to allow subclasses of {@link AbstractLogger} to
6209N/A * instantiate it.
6209N/A */
6209N/A public LoggerStorage()
6209N/A {
6209N/A super();
6209N/A }
6209N/A
6209N/A /**
6209N/A * The set of loggers that have been registered with the server. It will
6209N/A * initially be empty.
6209N/A */
6209N/A private Collection<P> logPublishers = new CopyOnWriteArrayList<P>();
6209N/A
6209N/A
6209N/A /**
6209N/A * Add a log publisher to the logger.
6209N/A *
6209N/A * @param publisher
6209N/A * The log publisher to add.
6209N/A */
6209N/A public synchronized void addLogPublisher(P publisher)
6209N/A {
6209N/A logPublishers.add(publisher);
6209N/A }
6209N/A
6209N/A /**
6209N/A * Remove a log publisher from the logger.
6209N/A *
6209N/A * @param publisher
6209N/A * The log publisher to remove.
6209N/A * @return True if the log publisher is removed or false otherwise.
6209N/A */
6209N/A public synchronized boolean removeLogPublisher(P publisher)
6209N/A {
6209N/A boolean removed = logPublishers.remove(publisher);
6209N/A
6209N/A if (removed)
6209N/A {
6209N/A publisher.close();
6209N/A }
6209N/A
6209N/A return removed;
6209N/A }
6209N/A
6209N/A /**
6209N/A * Removes all existing log publishers from the logger.
6209N/A */
6209N/A public synchronized void removeAllLogPublishers()
6209N/A {
6209N/A StaticUtils.close((Collection) logPublishers);
6209N/A logPublishers.clear();
6209N/A }
6209N/A
6209N/A /**
6209N/A * Returns the logPublishers.
6209N/A *
6209N/A * @return the collection of {@link LogPublisher}s
6209N/A */
6209N/A public Collection<P> getLogPublishers()
6209N/A {
6209N/A return logPublishers;
6209N/A }
6209N/A }
6209N/A
6209N/A /**
6209N/A * Returns the logger storage for the current logger.
6209N/A *
6209N/A * @return the logger storage for the current logger
6209N/A */
6209N/A protected abstract LoggerStorage<P, C> getStorage();
6209N/A
6209N/A /**
6209N/A * Returns the java {@link ClassPropertyDefinition} for the current logger.
6209N/A *
6209N/A * @return the java {@link ClassPropertyDefinition} for the current logger.
6209N/A */
6209N/A protected abstract ClassPropertyDefinition getJavaClassPropertyDefinition();
6209N/A
6209N/A private final Class<P> logPublisherClass;
6209N/A
6209N/A private final Arg3<CharSequence, CharSequence, CharSequence>
6209N/A invalidLoggerClassErrorMessage;
6209N/A
6209N/A /**
6209N/A * The constructor for this class.
6209N/A *
6209N/A * @param logPublisherClass
6209N/A * the log publisher class
6209N/A * @param invalidLoggerClassErrorMessage
6209N/A * the error message to use if the logger class in invalid
6209N/A */
6209N/A public AbstractLogger(
6209N/A final Class<P> logPublisherClass,
6209N/A final Arg3<CharSequence, CharSequence, CharSequence>
6209N/A invalidLoggerClassErrorMessage)
6209N/A {
6209N/A this.logPublisherClass = logPublisherClass;
6209N/A this.invalidLoggerClassErrorMessage = invalidLoggerClassErrorMessage;
6209N/A }
6209N/A
6209N/A /**
6209N/A * Initializes all the log publishers.
6209N/A *
6209N/A * @param configs The log publisher configurations.
6209N/A * @throws ConfigException
6209N/A * If an unrecoverable problem arises in the process of
6209N/A * performing the initialization as a result of the server
6209N/A * configuration.
6209N/A * @throws InitializationException
6209N/A * If a problem occurs during initialization that is not
6209N/A * related to the server configuration.
6209N/A */
6209N/A public void initializeLogger(List<C> configs)
6209N/A throws ConfigException, InitializationException
6209N/A {
6209N/A for (C config : configs)
6209N/A {
6209N/A config.addChangeListener((ConfigurationChangeListener) this);
6209N/A
6209N/A if(config.isEnabled())
6209N/A {
6209N/A getStorage().addLogPublisher(getLogPublisher(config));
6209N/A }
6209N/A }
6209N/A }
6209N/A
6209N/A /**
6209N/A * {@inheritDoc}
6209N/A */
6209N/A @Override
6209N/A public boolean isConfigurationAddAcceptable(C config,
6209N/A List<Message> unacceptableReasons)
6209N/A {
6209N/A return !config.isEnabled() ||
6209N/A isJavaClassAcceptable(config, unacceptableReasons);
6209N/A }
6209N/A
6209N/A /**
6209N/A * {@inheritDoc}
6209N/A */
6209N/A @Override
6209N/A public boolean isConfigurationChangeAcceptable(C config,
6209N/A List<Message> unacceptableReasons)
6209N/A {
6209N/A return !config.isEnabled() ||
6209N/A isJavaClassAcceptable(config, unacceptableReasons);
6209N/A }
6209N/A
6209N/A /**
6209N/A * {@inheritDoc}
6209N/A */
6209N/A @Override
6209N/A public ConfigChangeResult applyConfigurationAdd(C config)
6209N/A {
6209N/A // Default result code.
6209N/A ResultCode resultCode = ResultCode.SUCCESS;
6209N/A boolean adminActionRequired = false;
6209N/A ArrayList<Message> messages = new ArrayList<Message>();
6209N/A
6209N/A config.addChangeListener((ConfigurationChangeListener) this);
6209N/A
6209N/A if(config.isEnabled())
6209N/A {
6209N/A try
6209N/A {
6209N/A getStorage().addLogPublisher(getLogPublisher(config));
6209N/A }
6209N/A catch(ConfigException e)
6209N/A {
6209N/A debugCaught(DebugLogLevel.ERROR, e);
6209N/A messages.add(e.getMessageObject());
6209N/A resultCode = DirectoryServer.getServerErrorResultCode();
6209N/A }
6209N/A catch (Exception e)
6209N/A {
6209N/A debugCaught(DebugLogLevel.ERROR, e);
6209N/A messages.add(ERR_CONFIG_LOGGER_CANNOT_CREATE_LOGGER.get(
6209N/A String.valueOf(config.dn().toString()),
6209N/A stackTraceToSingleLineString(e)));
6209N/A resultCode = DirectoryServer.getServerErrorResultCode();
6209N/A }
6209N/A }
6209N/A return new ConfigChangeResult(resultCode, adminActionRequired, messages);
6209N/A }
6209N/A
6209N/A private void debugCaught(LogLevel error, Exception e)
6209N/A {
6209N/A if (DebugLogger.debugEnabled())
6209N/A {
6209N/A DebugLogger.getTracer().debugCaught(DebugLogLevel.ERROR, e);
6209N/A }
6209N/A }
6209N/A
6209N/A private P findLogPublisher(DN dn)
6209N/A {
6209N/A Collection<P> logPublishers = getStorage().getLogPublishers();
6209N/A for (P publisher : logPublishers)
6209N/A {
6209N/A if (publisher.getDN().equals(dn))
6209N/A {
6209N/A return publisher;
6209N/A }
6209N/A }
6209N/A return null;
6209N/A }
6209N/A
6209N/A /**
6209N/A * {@inheritDoc}
6209N/A */
6209N/A @Override
6209N/A public ConfigChangeResult applyConfigurationChange(C config)
6209N/A {
6209N/A // Default result code.
6209N/A ResultCode resultCode = ResultCode.SUCCESS;
6209N/A boolean adminActionRequired = false;
6209N/A ArrayList<Message> messages = new ArrayList<Message>();
6209N/A
6209N/A P logPublisher = findLogPublisher(config.dn());
6209N/A if(logPublisher == null)
6209N/A {
6209N/A if(config.isEnabled())
6209N/A {
6209N/A // Needs to be added and enabled.
6209N/A return applyConfigurationAdd(config);
6209N/A }
6209N/A }
6209N/A else
6209N/A {
6209N/A if(config.isEnabled())
6209N/A {
6209N/A // The publisher is currently active, so we don't need to do anything.
6209N/A // Changes to the class name cannot be
6209N/A // applied dynamically, so if the class name did change then
6209N/A // indicate that administrative action is required for that
6209N/A // change to take effect.
6209N/A String className = config.getJavaClass();
6209N/A if(!className.equals(logPublisher.getClass().getName()))
6209N/A {
6209N/A adminActionRequired = true;
6209N/A }
6209N/A }
6209N/A else
6209N/A {
6209N/A // The publisher is being disabled so shut down and remove.
6209N/A getStorage().removeLogPublisher(logPublisher);
6209N/A }
6209N/A }
6209N/A
6209N/A return new ConfigChangeResult(resultCode, adminActionRequired, messages);
6209N/A }
6209N/A
6209N/A /**
6209N/A * {@inheritDoc}
6209N/A */
6209N/A @Override
6209N/A public boolean isConfigurationDeleteAcceptable(C config,
6209N/A List<Message> unacceptableReasons)
6209N/A {
6209N/A return findLogPublisher(config.dn()) != null;
6209N/A }
6209N/A
6209N/A /**
6209N/A * {@inheritDoc}
6209N/A */
6209N/A @Override
6209N/A public ConfigChangeResult applyConfigurationDelete(C config)
6209N/A {
6209N/A // Default result code.
6209N/A ResultCode resultCode = ResultCode.SUCCESS;
6209N/A boolean adminActionRequired = false;
6209N/A
6209N/A P logPublisher = findLogPublisher(config.dn());
6209N/A if(logPublisher != null)
6209N/A {
6209N/A getStorage().removeLogPublisher(logPublisher);
6209N/A }
6209N/A else
6209N/A {
6209N/A resultCode = ResultCode.NO_SUCH_OBJECT;
6209N/A }
6209N/A
6209N/A return new ConfigChangeResult(resultCode, adminActionRequired);
6209N/A }
6209N/A
6209N/A private boolean isJavaClassAcceptable(C config,
6209N/A List<Message> unacceptableReasons)
6209N/A {
6209N/A String className = config.getJavaClass();
6209N/A ClassPropertyDefinition pd = getJavaClassPropertyDefinition();
6209N/A try {
6209N/A // Load the class and cast it to a LogPublisher.
6209N/A P publisher = pd.loadClass(className, logPublisherClass).newInstance();
6209N/A // The class is valid as far as we can tell.
6209N/A return publisher.isConfigurationAcceptable(config, unacceptableReasons);
6209N/A } catch (Exception e) {
6209N/A Message message =
6209N/A invalidLoggerClassErrorMessage.get(className, config.dn().toString(),
6209N/A String.valueOf(e));
6209N/A unacceptableReasons.add(message);
6209N/A return false;
6209N/A }
6209N/A }
6209N/A
6209N/A private P getLogPublisher(C config) throws ConfigException
6209N/A {
6209N/A String className = config.getJavaClass();
6209N/A ClassPropertyDefinition pd = getJavaClassPropertyDefinition();
6209N/A try {
6209N/A // Load the class and cast it to a LogPublisher.
6209N/A P logPublisher = pd.loadClass(className, logPublisherClass).newInstance();
6209N/A logPublisher.initializeLogPublisher(config);
6209N/A // The log publisher has been successfully initialized.
6209N/A return logPublisher;
6209N/A }
6209N/A catch (Exception e)
6209N/A {
6209N/A Message message =
6209N/A invalidLoggerClassErrorMessage.get(className, config.dn().toString(),
6209N/A String.valueOf(e));
6209N/A throw new ConfigException(message, e);
6209N/A }
6209N/A }
6209N/A
6209N/A}