001 /*
002 * CDDL HEADER START
003 *
004 * The contents of this file are subject to the terms of the
005 * Common Development and Distribution License, Version 1.0 only
006 * (the "License"). You may not use this file except in compliance
007 * with the License.
008 *
009 * You can obtain a copy of the license at
010 * docs/licenses/cddl.txt
011 * or http://www.opensource.org/licenses/cddl1.php.
012 * See the License for the specific language governing permissions
013 * and limitations under the License.
014 *
015 * When distributing Covered Code, include this CDDL HEADER in each
016 * file and include the License file at
017 * docs/licenses/cddl.txt. If applicable,
018 * add the following below this CDDL HEADER, with the fields enclosed
019 * by brackets "[]" replaced with your own identifying information:
020 * Portions Copyright [yyyy] [name of copyright owner]
021 *
022 * CDDL HEADER END
023 *
024 *
025 * Copyright 2011-2013 UnboundID Corp.
026 */
027 package com.unboundid.directory.sdk.common.scripting;
028
029
030
031 import java.util.List;
032
033 import com.unboundid.directory.sdk.common.config.FileBasedErrorLoggerConfig;
034 import com.unboundid.directory.sdk.common.internal.Reconfigurable;
035 import com.unboundid.directory.sdk.common.types.LogCategory;
036 import com.unboundid.directory.sdk.common.types.LogSeverity;
037 import com.unboundid.directory.sdk.common.types.ServerContext;
038 import com.unboundid.directory.sdk.proxy.internal.DirectoryProxyServerExtension;
039 import com.unboundid.directory.sdk.ds.internal.DirectoryServerExtension;
040 import com.unboundid.directory.sdk.sync.internal.SynchronizationServerExtension;
041 import com.unboundid.ldap.sdk.LDAPException;
042 import com.unboundid.ldap.sdk.ResultCode;
043 import com.unboundid.util.Extensible;
044 import com.unboundid.util.ThreadSafety;
045 import com.unboundid.util.ThreadSafetyLevel;
046 import com.unboundid.util.args.ArgumentException;
047 import com.unboundid.util.args.ArgumentParser;
048
049
050
051 /**
052 * This class defines an API that may be used to create a specific type of
053 * scripted error logger which is intended to write log messages to text files.
054 * This is a convenience for developers which wish to create custom error
055 * loggers that write to text files and provides support for a wide range of
056 * functionality including high-performance and highly-concurrent logging. All
057 * of the options available to {@link ScriptedErrorLogger} implementations are
058 * available for file-based error loggers, as well as options for indicating
059 * the log file path, the rotation and retention policies, whether to buffer the
060 * output, etc.
061 * <BR><BR>
062 * Note that scripted file-based error loggers will automatically be registered
063 * within the server as disk space consumers, so there is no need to implement
064 * the {@link com.unboundid.directory.sdk.common.api.DiskSpaceConsumer}
065 * interface. Also note that configuration change related to the log file
066 * (e.g., the log file path, buffer size, queue size, etc.) will also
067 * automatically be handled by the server, so subclasses only need to be
068 * concerned about changes to the custom arguments they define.
069 * <BR>
070 * <H2>Configuring File-Based Error Loggers</H2>
071 * In order to configure an error logger created using this API, use a command
072 * like:
073 * <PRE>
074 * dsconfig create-log-publisher \
075 * --publisher-name "<I>{logger-name}</I>" \
076 * --type groovy-scripted-file-based-error \
077 * --set enabled:true \
078 * --set "log-file:<I>{path}</I>" \
079 * --set "rotation-policy:<I>{rotation-policy-name}</I>" \
080 * --set "retention-policy:<I>{retention-policy-name}</I>" \
081 * --set "script-class:<I>{class-name}</I>" \
082 * --set "script-argument:<I>{name=value}</I>"
083 * </PRE>
084 * where "<I>{logger-name}</I>" is the name to use for the error logger
085 * instance, "<I>{path}</I>" is the path to the log file to be written,
086 * "<I>{rotation-policy-name}</I>" is the name of the log rotation policy to use
087 * for the log file, "<I>{retention-policy-name}</I>" is the name of the log
088 * retention policy to use for the log file, "<I>{class-name}</I>" is the
089 * fully-qualified name of the Groovy class written using this API, and
090 * "<I>{name=value}</I>" represents name-value pairs for any arguments to
091 * provide to the logger. If multiple arguments should be provided to the
092 * logger, then the "<CODE>--set script-argument:<I>{name=value}</I></CODE>"
093 * option should be provided multiple times. It is also possible to specify
094 * multiple log rotation and/or retention policies if desired.
095 *
096 * @see com.unboundid.directory.sdk.common.api.ErrorLogger
097 * @see com.unboundid.directory.sdk.common.api.FileBasedErrorLogger
098 * @see ScriptedErrorLogger
099 */
100 @Extensible()
101 @DirectoryServerExtension()
102 @DirectoryProxyServerExtension(appliesToLocalContent=true,
103 appliesToRemoteContent=false)
104 @SynchronizationServerExtension(appliesToLocalContent=true,
105 appliesToSynchronizedContent=false)
106 @ThreadSafety(level=ThreadSafetyLevel.INTERFACE_THREADSAFE)
107 public abstract class ScriptedFileBasedErrorLogger
108 implements Reconfigurable<FileBasedErrorLoggerConfig>
109 {
110 /**
111 * Creates a new instance of this file-based error logger. All file-based
112 * error logger implementations must include a default constructor, but any
113 * initialization should generally be done in the
114 * {@code initializeErrorLogger} method.
115 */
116 public ScriptedFileBasedErrorLogger()
117 {
118 // No implementation is required.
119 }
120
121
122
123 /**
124 * {@inheritDoc}
125 */
126 public void defineConfigArguments(final ArgumentParser parser)
127 throws ArgumentException
128 {
129 // No arguments will be allowed by default.
130 }
131
132
133
134 /**
135 * Initializes this file-based error logger.
136 *
137 * @param serverContext A handle to the server context for the server in
138 * which this extension is running.
139 * @param config The general configuration for this file-based error
140 * logger.
141 * @param parser The argument parser which has been initialized from
142 * the configuration for this file-based error logger.
143 *
144 * @throws LDAPException If a problem occurs while initializing this
145 * file-based error logger.
146 */
147 public void initializeErrorLogger(final ServerContext serverContext,
148 final FileBasedErrorLoggerConfig config,
149 final ArgumentParser parser)
150 throws LDAPException
151 {
152 // No initialization will be performed by default.
153 }
154
155
156
157 /**
158 * Performs any cleanup which may be necessary when this file-based error
159 * logger is to be taken out of service.
160 */
161 public void finalizeErrorLogger()
162 {
163 // No implementation is required.
164 }
165
166
167
168 /**
169 * {@inheritDoc}
170 */
171 public boolean isConfigurationAcceptable(
172 final FileBasedErrorLoggerConfig config,
173 final ArgumentParser parser,
174 final List<String> unacceptableReasons)
175 {
176 // No extended validation will be performed.
177 return true;
178 }
179
180
181
182 /**
183 * {@inheritDoc}
184 */
185 public ResultCode applyConfiguration(final FileBasedErrorLoggerConfig config,
186 final ArgumentParser parser,
187 final List<String> adminActionsRequired,
188 final List<String> messages)
189 {
190 // If there are any custom arguments, then add an admin action message
191 // indicating that the extension needs to be restarted for any changes to
192 // take effect.
193 if (! parser.getNamedArguments().isEmpty())
194 {
195 adminActionsRequired.add(
196 "If any extension-argument values have been altered, then " +
197 "those new values have not actually been applied. The new " +
198 "configuration for those arguments will not take effect " +
199 "until this file-based error logger is disabled and " +
200 "re-enabled, or until the server is restarted.");
201 }
202
203 return ResultCode.SUCCESS;
204 }
205
206
207
208 /**
209 * Records information about the provided message, if appropriate.
210 *
211 * @param category The category for the message to be logged.
212 * @param severity The severity for the message to be logged.
213 * @param messageID The unique identifier with which the message text is
214 * associated.
215 * @param message The message to be logged.
216 *
217 * @return The content of the log message that should be written. It may be
218 * {@code null} or empty if no message should be written. It may
219 * optionally include line breaks if the log message should span
220 * multiple lines.
221 */
222 public abstract CharSequence logError(final LogCategory category,
223 final LogSeverity severity,
224 final long messageID,
225 final String message);
226 }