/* * 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 * docs/licenses/cddl.txt * or http://www.opensource.org/licenses/cddl1.php. * 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 * docs/licenses/cddl.txt. 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 * * * Portions Copyright 2016-2024 Ping Identity Corporation */ package com.unboundid.directory.sdk.examples; import java.io.File; import java.io.FileWriter; import java.io.PrintWriter; import java.util.Arrays; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import com.unboundid.directory.sdk.common.api.LogFileRotationListener; import com.unboundid.directory.sdk.common.config.LogFileRotationListenerConfig; import com.unboundid.directory.sdk.common.types.ServerContext; import com.unboundid.ldap.sdk.LDAPException; import com.unboundid.ldap.sdk.ResultCode; import com.unboundid.util.StaticUtils; import com.unboundid.util.args.ArgumentException; import com.unboundid.util.args.ArgumentParser; import com.unboundid.util.args.FileArgument; /** * This class provides a simple example of a log file rotation listener that * will just write a record of each log rotation to a specified file. It has * one configuration argument: * <UL> * <LI>output-file -- The path to the file that should be updated * whenever a log file is rotated.</LI> * </UL> */ public final class ExampleLogFileRotationListener extends LogFileRotationListener { /** * The name of the argument that will be used to specify the path to the file * to be updated whenever a log file is rotated. */ private static final String ARG_NAME_OUTPUT_FILE = "output-file"; // The output file to be written. private volatile File outputFile; /** * Creates a new instance of this log file rotation listener. All log file * rotation listener implementations must include a default constructor, but * any initialization should generally be done in the * {@code initializeLogFileRotationListener} method. */ public ExampleLogFileRotationListener() { // No implementation required. } /** * Retrieves a human-readable name for this extension. * * @return A human-readable name for this extension. */ @Override() public String getExtensionName() { return "Example Log File Rotation Listener"; } /** * Retrieves a human-readable description for this extension. Each element * of the array that is returned will be considered a separate paragraph in * generated documentation. * * @return A human-readable description for this extension, or {@code null} * or an empty array if no description should be available. */ @Override() public String[] getExtensionDescription() { return new String[] { "This log file rotation listener serves an example that may be used to " + "demonstrate the process for creating a third-party log file " + "rotation listener. It simply records a message in a specified " + "output file whenever a log file is rotated." }; } /** * Updates the provided argument parser to define any configuration arguments * which may be used by this log file rotation listener. The argument parser * may also be updated to define relationships between arguments (e.g., to * specify required, exclusive, or dependent argument sets). * * @param parser The argument parser to be updated with the configuration * arguments which may be used by this log file rotation * listener. * * @throws ArgumentException If a problem is encountered while updating the * provided argument parser. */ @Override() public void defineConfigArguments(final ArgumentParser parser) throws ArgumentException { // Add an argument that allows you to specify the output file. final Character shortIdentifier = null; final String longIdentifier = ARG_NAME_OUTPUT_FILE; final boolean required = true; final int maxOccurrences = 1; final String placeholder = "{path}"; final String description = "The output file to update whenever a log file is rotated."; final boolean fileMustExist = false; final boolean parentMustExist = true; final boolean mustBeFile = true; final boolean mustBeDirectory = false; parser.addArgument(new FileArgument(shortIdentifier, longIdentifier, required, maxOccurrences, placeholder, description, fileMustExist, parentMustExist, mustBeFile, mustBeDirectory)); } /** * Initializes this log file rotation listener. * * @param serverContext A handle to the server context for the server in * which this extension is running. * @param config The general configuration for this log file rotation * listener. * @param parser The argument parser which has been initialized from * the configuration for this log file rotation * listener. * * @throws LDAPException If a problem occurs while initializing this log * file rotation listener. */ @Override() public void initializeLogFileRotationListener( final ServerContext serverContext, final LogFileRotationListenerConfig config, final ArgumentParser parser) throws LDAPException { serverContext.debugInfo( "Beginning log file rotation listener initialization"); // Get the output file. final FileArgument outputFileArg = (FileArgument) parser.getNamedArgument(ARG_NAME_OUTPUT_FILE); outputFile = outputFileArg.getValue(); } /** * Indicates whether the configuration contained in the provided argument * parser represents a valid configuration for this extension. * * @param config The general configuration for this log file * rotation listener. * @param parser The argument parser which has been initialized * with the proposed configuration. * @param unacceptableReasons A list that can be updated with reasons that * the proposed configuration is not acceptable. * * @return {@code true} if the proposed configuration is acceptable, or * {@code false} if not. */ @Override() public boolean isConfigurationAcceptable( final LogFileRotationListenerConfig config, final ArgumentParser parser, final List<String> unacceptableReasons) { // No special validation is required. return true; } /** * Attempts to apply the configuration contained in the provided argument * parser. * * @param config The general configuration for this log file * rotation listener. * @param parser The argument parser which has been * initialized with the new configuration. * @param adminActionsRequired A list that can be updated with information * about any administrative actions that may be * required before one or more of the * configuration changes will be applied. * @param messages A list that can be updated with information * about the result of applying the new * configuration. * * @return A result code that provides information about the result of * attempting to apply the configuration change. */ @Override() public ResultCode applyConfiguration( final LogFileRotationListenerConfig config, final ArgumentParser parser, final List<String> adminActionsRequired, final List<String> messages) { // Get the new output file. final FileArgument outputFileArg = (FileArgument) parser.getNamedArgument(ARG_NAME_OUTPUT_FILE); outputFile = outputFileArg.getValue(); return ResultCode.SUCCESS; } /** * Performs any cleanup which may be necessary when this log file rotation * listener is to be taken out of service. */ @Override() public void finalizeLogFileRotationListener() { // No finalization is required. } /** * Performs any appropriate processing for a log file that has been rotated. * * @param f The log file that has been rotated. This file must not be * deleted, moved, renamed, or otherwise altered during processing. * * @throws LDAPException If a problem is encountered during processing. */ @Override() public void doPostRotationProcessing(final File f) throws LDAPException { final PrintWriter writer; try { final boolean appendToFile = true; writer = new PrintWriter(new FileWriter(outputFile, appendToFile)); } catch (final Exception e) { throw new LDAPException(ResultCode.LOCAL_ERROR, "Unable to open output file " + outputFile.getAbsolutePath() + " to record information about newly-rotated log file " + f.getAbsolutePath() + ": " + StaticUtils.getExceptionMessage(e), e); } try { writer.println( StaticUtils.encodeGeneralizedTime(System.currentTimeMillis()) + '\t' + f.getAbsolutePath()); } catch (final Exception e) { throw new LDAPException(ResultCode.LOCAL_ERROR, "An error occurred while attempting to update output file " + outputFile.getAbsolutePath() + " with information about " + "newly-rotated log file " + f.getAbsolutePath() + ": " + StaticUtils.getExceptionMessage(e), e); } finally { writer.close(); } } /** * Retrieves a map containing examples of configurations that may be used for * this extension. The map key should be a list of sample arguments, and the * corresponding value should be a description of the behavior that will be * exhibited by the extension when used with that configuration. * * @return A map containing examples of configurations that may be used for * this extension. It may be {@code null} or empty if there should * not be any example argument sets. */ @Override() public Map<List<String>,String> getExamplesArgumentSets() { final LinkedHashMap<List<String>,String> exampleMap = new LinkedHashMap<List<String>,String>(1); exampleMap.put( Arrays.asList( ARG_NAME_OUTPUT_FILE + "=logs/rotation.log"), "Update the logs/rotation.log file with a message every time a " + "log file is rotated."); return exampleMap; } }