| | |
| | | */ |
| | | 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.*; |
| | | |
| | | |
| | |
| | | * 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. |
| | |
| | | * @param publisher The access log publisher to add. |
| | | */ |
| | | public synchronized static void addAccessLogPublisher( |
| | | AccessLogPublisher<?> publisher) |
| | | AccessLogPublisher publisher) |
| | | { |
| | | accessPublishers.add(publisher); |
| | | loggerStorage.addLogPublisher(publisher); |
| | | } |
| | | |
| | | /** |
| | |
| | | * @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); |
| | | } |
| | | |
| | | /** |
| | |
| | | */ |
| | | 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 |
| | |
| | | */ |
| | | public static void logConnect(ClientConnection clientConnection) |
| | | { |
| | | for (AccessLogPublisher<?> publisher : accessPublishers) |
| | | for (AccessLogPublisher<?> publisher : getAccessLogPublishers()) |
| | | { |
| | | publisher.logConnect(clientConnection); |
| | | } |
| | |
| | | DisconnectReason disconnectReason, |
| | | Message message) |
| | | { |
| | | for (AccessLogPublisher<?> publisher : accessPublishers) |
| | | for (AccessLogPublisher<?> publisher : getAccessLogPublishers()) |
| | | { |
| | | publisher.logDisconnect(clientConnection, disconnectReason, message); |
| | | } |
| | |
| | | */ |
| | | public static void logAbandonRequest(AbandonOperation abandonOperation) |
| | | { |
| | | for (AccessLogPublisher<?> publisher : accessPublishers) |
| | | for (AccessLogPublisher<?> publisher : getAccessLogPublishers()) |
| | | { |
| | | publisher.logAbandonRequest(abandonOperation); |
| | | } |
| | |
| | | */ |
| | | public static void logAbandonResult(AbandonOperation abandonOperation) |
| | | { |
| | | for (AccessLogPublisher<?> publisher : accessPublishers) |
| | | for (AccessLogPublisher<?> publisher : getAccessLogPublishers()) |
| | | { |
| | | publisher.logAbandonResult(abandonOperation); |
| | | } |
| | |
| | | */ |
| | | public static void logAddRequest(AddOperation addOperation) |
| | | { |
| | | for (AccessLogPublisher<?> publisher : accessPublishers) |
| | | for (AccessLogPublisher<?> publisher : getAccessLogPublishers()) |
| | | { |
| | | publisher.logAddRequest(addOperation); |
| | | } |
| | |
| | | */ |
| | | public static void logAddResponse(AddOperation addOperation) |
| | | { |
| | | for (AccessLogPublisher<?> publisher : accessPublishers) |
| | | for (AccessLogPublisher<?> publisher : getAccessLogPublishers()) |
| | | { |
| | | publisher.logAddResponse(addOperation); |
| | | } |
| | |
| | | */ |
| | | public static void logBindRequest(BindOperation bindOperation) |
| | | { |
| | | for (AccessLogPublisher<?> publisher : accessPublishers) |
| | | for (AccessLogPublisher<?> publisher : getAccessLogPublishers()) |
| | | { |
| | | publisher.logBindRequest(bindOperation); |
| | | } |
| | |
| | | */ |
| | | public static void logBindResponse(BindOperation bindOperation) |
| | | { |
| | | for (AccessLogPublisher<?> publisher : accessPublishers) |
| | | for (AccessLogPublisher<?> publisher : getAccessLogPublishers()) |
| | | { |
| | | publisher.logBindResponse(bindOperation); |
| | | } |
| | |
| | | */ |
| | | public static void logCompareRequest(CompareOperation compareOperation) |
| | | { |
| | | for (AccessLogPublisher<?> publisher : accessPublishers) |
| | | for (AccessLogPublisher<?> publisher : getAccessLogPublishers()) |
| | | { |
| | | publisher.logCompareRequest(compareOperation); |
| | | } |
| | |
| | | */ |
| | | public static void logCompareResponse(CompareOperation compareOperation) |
| | | { |
| | | for (AccessLogPublisher<?> publisher : accessPublishers) |
| | | for (AccessLogPublisher<?> publisher : getAccessLogPublishers()) |
| | | { |
| | | publisher.logCompareResponse(compareOperation); |
| | | } |
| | |
| | | */ |
| | | public static void logDeleteRequest(DeleteOperation deleteOperation) |
| | | { |
| | | for (AccessLogPublisher<?> publisher : accessPublishers) |
| | | for (AccessLogPublisher<?> publisher : getAccessLogPublishers()) |
| | | { |
| | | publisher.logDeleteRequest(deleteOperation); |
| | | } |
| | |
| | | */ |
| | | public static void logDeleteResponse(DeleteOperation deleteOperation) |
| | | { |
| | | for (AccessLogPublisher<?> publisher : accessPublishers) |
| | | for (AccessLogPublisher<?> publisher : getAccessLogPublishers()) |
| | | { |
| | | publisher.logDeleteResponse(deleteOperation); |
| | | } |
| | |
| | | */ |
| | | public static void logExtendedRequest(ExtendedOperation extendedOperation) |
| | | { |
| | | for (AccessLogPublisher<?> publisher : accessPublishers) |
| | | for (AccessLogPublisher<?> publisher : getAccessLogPublishers()) |
| | | { |
| | | publisher.logExtendedRequest(extendedOperation); |
| | | } |
| | |
| | | */ |
| | | public static void logExtendedResponse(ExtendedOperation extendedOperation) |
| | | { |
| | | for (AccessLogPublisher<?> publisher : accessPublishers) |
| | | for (AccessLogPublisher<?> publisher : getAccessLogPublishers()) |
| | | { |
| | | publisher.logExtendedResponse(extendedOperation); |
| | | } |
| | |
| | | */ |
| | | public static void logModifyRequest(ModifyOperation modifyOperation) |
| | | { |
| | | for (AccessLogPublisher<?> publisher : accessPublishers) |
| | | for (AccessLogPublisher<?> publisher : getAccessLogPublishers()) |
| | | { |
| | | publisher.logModifyRequest(modifyOperation); |
| | | } |
| | |
| | | */ |
| | | public static void logModifyResponse(ModifyOperation modifyOperation) |
| | | { |
| | | for (AccessLogPublisher<?> publisher : accessPublishers) |
| | | for (AccessLogPublisher<?> publisher : getAccessLogPublishers()) |
| | | { |
| | | publisher.logModifyResponse(modifyOperation); |
| | | } |
| | |
| | | */ |
| | | public static void logModifyDNRequest(ModifyDNOperation modifyDNOperation) |
| | | { |
| | | for (AccessLogPublisher<?> publisher : accessPublishers) |
| | | for (AccessLogPublisher<?> publisher : getAccessLogPublishers()) |
| | | { |
| | | publisher.logModifyDNRequest(modifyDNOperation); |
| | | } |
| | |
| | | */ |
| | | public static void logModifyDNResponse(ModifyDNOperation modifyDNOperation) |
| | | { |
| | | for (AccessLogPublisher<?> publisher : accessPublishers) |
| | | for (AccessLogPublisher<?> publisher : getAccessLogPublishers()) |
| | | { |
| | | publisher.logModifyDNResponse(modifyDNOperation); |
| | | } |
| | |
| | | */ |
| | | public static void logSearchRequest(SearchOperation searchOperation) |
| | | { |
| | | for (AccessLogPublisher<?> publisher : accessPublishers) |
| | | for (AccessLogPublisher<?> publisher : getAccessLogPublishers()) |
| | | { |
| | | publisher.logSearchRequest(searchOperation); |
| | | } |
| | |
| | | public static void logSearchResultEntry(SearchOperation searchOperation, |
| | | SearchResultEntry searchEntry) |
| | | { |
| | | for (AccessLogPublisher<?> publisher : accessPublishers) |
| | | for (AccessLogPublisher<?> publisher : getAccessLogPublishers()) |
| | | { |
| | | publisher.logSearchResultEntry(searchOperation, searchEntry); |
| | | } |
| | |
| | | public static void logSearchResultReference(SearchOperation searchOperation, |
| | | SearchResultReference searchReference) |
| | | { |
| | | for (AccessLogPublisher<?> publisher : accessPublishers) |
| | | for (AccessLogPublisher<?> publisher : getAccessLogPublishers()) |
| | | { |
| | | publisher.logSearchResultReference(searchOperation, searchReference); |
| | | } |
| | |
| | | */ |
| | | public static void logSearchResultDone(SearchOperation searchOperation) |
| | | { |
| | | for (AccessLogPublisher<?> publisher : accessPublishers) |
| | | for (AccessLogPublisher<?> publisher : getAccessLogPublishers()) |
| | | { |
| | | publisher.logSearchResultDone(searchOperation); |
| | | } |
| | |
| | | */ |
| | | public static void logUnbind(UnbindOperation unbindOperation) |
| | | { |
| | | for (AccessLogPublisher<?> publisher : accessPublishers) |
| | | for (AccessLogPublisher<?> publisher : getAccessLogPublishers()) |
| | | { |
| | | publisher.logUnbind(unbindOperation); |
| | | } |