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 * trunk/opends/resource/legal-notices/OpenDS.LICENSE
011 * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
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 * trunk/opends/resource/legal-notices/OpenDS.LICENSE. 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 2006-2008 Sun Microsystems, Inc.
026 */
027 package org.opends.server.core;
028 import org.opends.messages.Message;
029
030 import org.opends.server.admin.std.server.LogRetentionPolicyCfg;
031 import org.opends.server.admin.std.server.RootCfg;
032 import org.opends.server.admin.std.meta.LogRetentionPolicyCfgDefn;
033 import org.opends.server.admin.server.ConfigurationAddListener;
034 import org.opends.server.admin.server.ServerManagementContext;
035 import org.opends.server.admin.server.ConfigurationChangeListener;
036 import org.opends.server.admin.server.ConfigurationDeleteListener;
037 import org.opends.server.admin.ClassPropertyDefinition;
038 import org.opends.server.types.InitializationException;
039 import org.opends.server.types.ConfigChangeResult;
040 import org.opends.server.types.ResultCode;
041 import org.opends.server.types.DebugLogLevel;
042 import org.opends.server.loggers.RetentionPolicy;
043 import org.opends.server.config.ConfigException;
044
045 import static org.opends.server.loggers.debug.DebugLogger.*;
046 import org.opends.server.loggers.debug.DebugTracer;
047 import static org.opends.messages.ConfigMessages.*;
048
049 import static org.opends.server.util.StaticUtils.*;
050
051 import java.util.List;
052 import java.util.ArrayList;
053 import java.lang.reflect.Method;
054 import java.lang.reflect.InvocationTargetException;
055
056 /**
057 * This class defines a utility that will be used to manage the set of
058 * log retention policies used in the Directory Server. It will perform the
059 * initialization when the server is starting, and then will manage any
060 * additions, and removals of policies while the server is running.
061 */
062 public class LogRetentionPolicyConfigManager implements
063 ConfigurationAddListener<LogRetentionPolicyCfg>,
064 ConfigurationDeleteListener<LogRetentionPolicyCfg>,
065 ConfigurationChangeListener<LogRetentionPolicyCfg>
066 {
067 /**
068 * The tracer object for the debug logger.
069 */
070 private static final DebugTracer TRACER = getTracer();
071
072
073 /**
074 * Initializes all the log retention policies.
075 *
076 * @throws ConfigException
077 * If an unrecoverable problem arises in the process of
078 * performing the initialization as a result of the server
079 * configuration.
080 * @throws InitializationException
081 * If a problem occurs during initialization that is not
082 * related to the server configuration.
083 */
084 public void initializeLogRetentionPolicyConfig()
085 throws ConfigException, InitializationException
086 {
087 ServerManagementContext context = ServerManagementContext.getInstance();
088 RootCfg root = context.getRootConfiguration();
089
090 root.addLogRetentionPolicyAddListener(this);
091 root.addLogRetentionPolicyDeleteListener(this);
092
093 for(String name : root.listLogRetentionPolicies())
094 {
095 LogRetentionPolicyCfg config = root.getLogRetentionPolicy(name);
096
097 RetentionPolicy RetentionPolicy = getRetentionPolicy(config);
098
099 DirectoryServer.registerRetentionPolicy(config.dn(), RetentionPolicy);
100 }
101 }
102
103 /**
104 * {@inheritDoc}
105 */
106 public boolean isConfigurationAddAcceptable(
107 LogRetentionPolicyCfg configuration,
108 List<Message> unacceptableReasons)
109 {
110 return isJavaClassAcceptable(configuration, unacceptableReasons);
111 }
112
113 /**
114 * {@inheritDoc}
115 */
116 public boolean isConfigurationDeleteAcceptable(
117 LogRetentionPolicyCfg configuration,
118 List<Message> unacceptableReasons)
119 {
120 // TODO: Make sure nothing is using this policy before deleting it.
121 return true;
122 }
123
124 /**
125 * {@inheritDoc}
126 */
127 public ConfigChangeResult applyConfigurationAdd(LogRetentionPolicyCfg config)
128 {
129 // Default result code.
130 ResultCode resultCode = ResultCode.SUCCESS;
131 boolean adminActionRequired = false;
132 ArrayList<Message> messages = new ArrayList<Message>();
133
134 try
135 {
136 RetentionPolicy RetentionPolicy = getRetentionPolicy(config);
137
138 DirectoryServer.registerRetentionPolicy(config.dn(), RetentionPolicy);
139 }
140 catch (ConfigException e) {
141 if (debugEnabled())
142 {
143 TRACER.debugCaught(DebugLogLevel.ERROR, e);
144 }
145 messages.add(e.getMessageObject());
146 resultCode = DirectoryServer.getServerErrorResultCode();
147 } catch (Exception e) {
148 if (debugEnabled())
149 {
150 TRACER.debugCaught(DebugLogLevel.ERROR, e);
151 }
152
153 messages.add(ERR_CONFIG_RETENTION_POLICY_CANNOT_CREATE_POLICY.get(
154 String.valueOf(config.dn().toString()),
155 stackTraceToSingleLineString(e)));
156 resultCode = DirectoryServer.getServerErrorResultCode();
157 }
158
159 return new ConfigChangeResult(resultCode, adminActionRequired, messages);
160 }
161
162 /**
163 * {@inheritDoc}
164 */
165 public ConfigChangeResult applyConfigurationDelete(
166 LogRetentionPolicyCfg config)
167 {
168 // Default result code.
169 ResultCode resultCode = ResultCode.SUCCESS;
170 boolean adminActionRequired = false;
171 ArrayList<Message> messages = new ArrayList<Message>();
172
173 RetentionPolicy policy = DirectoryServer.getRetentionPolicy(config.dn());
174 if(policy != null)
175 {
176 DirectoryServer.deregisterRetentionPolicy(config.dn());
177 }
178 else
179 {
180 // TODO: Add message and check for usage
181 resultCode = DirectoryServer.getServerErrorResultCode();
182 }
183
184 return new ConfigChangeResult(resultCode, adminActionRequired, messages);
185 }
186
187 /**
188 * {@inheritDoc}
189 */
190 public boolean isConfigurationChangeAcceptable(
191 LogRetentionPolicyCfg configuration,
192 List<Message> unacceptableReasons)
193 {
194 return isJavaClassAcceptable(configuration, unacceptableReasons);
195 }
196
197 /**
198 * {@inheritDoc}
199 */
200 public ConfigChangeResult applyConfigurationChange(
201 LogRetentionPolicyCfg configuration)
202 {
203 // Default result code.
204 ResultCode resultCode = ResultCode.SUCCESS;
205 boolean adminActionRequired = false;
206 ArrayList<Message> messages = new ArrayList<Message>();
207
208 RetentionPolicy policy =
209 DirectoryServer.getRetentionPolicy(configuration.dn());
210 String className = configuration.getJavaClass();
211 if(!className.equals(policy.getClass().getName()))
212 {
213 adminActionRequired = true;
214 }
215
216 return new ConfigChangeResult(resultCode, adminActionRequired, messages);
217 }
218
219 private boolean isJavaClassAcceptable(LogRetentionPolicyCfg config,
220 List<Message> unacceptableReasons)
221 {
222 String className = config.getJavaClass();
223 LogRetentionPolicyCfgDefn d = LogRetentionPolicyCfgDefn.getInstance();
224 ClassPropertyDefinition pd =
225 d.getJavaClassPropertyDefinition();
226 // Load the class and cast it to a RetentionPolicy.
227 Class<? extends RetentionPolicy> theClass;
228 try {
229 theClass = pd.loadClass(className, RetentionPolicy.class);
230 theClass.newInstance();
231 } catch (Exception e) {
232 Message message = ERR_CONFIG_RETENTION_POLICY_INVALID_CLASS.get(className,
233 config.dn().toString(),
234 String.valueOf(e));
235 unacceptableReasons.add(message);
236 return false;
237 }
238 // Check that the implementation class implements the correct interface.
239 try {
240 // Determine the initialization method to use: it must take a
241 // single parameter which is the exact type of the configuration
242 // object.
243 theClass.getMethod("initializeLogRetentionPolicy", config
244 .configurationClass());
245 } catch (Exception e) {
246 Message message = ERR_CONFIG_RETENTION_POLICY_INVALID_CLASS.get(className,
247 config.dn().toString(),
248 String.valueOf(e));
249 unacceptableReasons.add(message);
250 return false;
251 }
252 // The class is valid as far as we can tell.
253 return true;
254 }
255
256 private RetentionPolicy getRetentionPolicy(LogRetentionPolicyCfg config)
257 throws ConfigException {
258 String className = config.getJavaClass();
259 LogRetentionPolicyCfgDefn d = LogRetentionPolicyCfgDefn.getInstance();
260 ClassPropertyDefinition pd =
261 d.getJavaClassPropertyDefinition();
262 // Load the class and cast it to a RetentionPolicy.
263 Class<? extends RetentionPolicy> theClass;
264 RetentionPolicy RetentionPolicy;
265 try {
266 theClass = pd.loadClass(className, RetentionPolicy.class);
267 RetentionPolicy = theClass.newInstance();
268
269 // Determine the initialization method to use: it must take a
270 // single parameter which is the exact type of the configuration
271 // object.
272 Method method = theClass.getMethod("initializeLogRetentionPolicy", config
273 .configurationClass());
274 method.invoke(RetentionPolicy, config);
275 }
276 catch (InvocationTargetException ite)
277 {
278 // Rethrow the exceptions thrown be the invoked method.
279 Throwable e = ite.getTargetException();
280 Message message = ERR_CONFIG_RETENTION_POLICY_INVALID_CLASS.get(
281 className, config.dn().toString(), stackTraceToSingleLineString(e));
282 throw new ConfigException(message, e);
283 } catch (Exception e) {
284 Message message = ERR_CONFIG_RETENTION_POLICY_INVALID_CLASS.get(
285 className, config.dn().toString(), String.valueOf(e));
286 throw new ConfigException(message, e);
287 }
288
289 // The connection handler has been successfully initialized.
290 return RetentionPolicy;
291 }
292 }
293