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
031
032 import java.lang.reflect.Method;
033 import java.util.ArrayList;
034 import java.util.List;
035 import java.util.concurrent.ConcurrentHashMap;
036
037 import org.opends.server.admin.ClassPropertyDefinition;
038 import org.opends.server.admin.server.ConfigurationAddListener;
039 import org.opends.server.admin.server.ConfigurationChangeListener;
040 import org.opends.server.admin.server.ConfigurationDeleteListener;
041 import org.opends.server.admin.std.meta.MonitorProviderCfgDefn;
042 import org.opends.server.admin.std.server.MonitorProviderCfg;
043 import org.opends.server.admin.std.server.RootCfg;
044 import org.opends.server.admin.server.ServerManagementContext;
045 import org.opends.server.api.MonitorProvider;
046 import org.opends.server.config.ConfigException;
047 import org.opends.server.types.ConfigChangeResult;
048 import org.opends.server.types.DN;
049 import org.opends.server.types.InitializationException;
050 import org.opends.server.types.ResultCode;
051
052 import static org.opends.messages.ConfigMessages.*;
053 import static org.opends.server.loggers.ErrorLogger.*;
054
055 import static org.opends.server.util.StaticUtils.*;
056
057
058
059 /**
060 * This class defines a utility that will be used to manage the set of monitor
061 * providers defined in the Directory Server. It will initialize the monitor
062 * providers when the server starts, and then will manage any additions,
063 * removals, or modifications to any providers while the server is running.
064 */
065 public class MonitorConfigManager
066 implements ConfigurationChangeListener<MonitorProviderCfg>,
067 ConfigurationAddListener<MonitorProviderCfg>,
068 ConfigurationDeleteListener<MonitorProviderCfg>
069
070 {
071 // A mapping between the DNs of the config entries and the associated monitor
072 // providers.
073 private ConcurrentHashMap<DN,MonitorProvider> monitors;
074
075
076
077 /**
078 * Creates a new instance of this monitor provider config manager.
079 */
080 public MonitorConfigManager()
081 {
082 monitors = new ConcurrentHashMap<DN,MonitorProvider>();
083 }
084
085
086
087 /**
088 * Initializes all monitor providers currently defined in the Directory Server
089 * configuration. This should only be called at Directory Server startup.
090 *
091 * @throws ConfigException If a configuration problem causes the monitor
092 * provider initialization process to fail.
093 *
094 * @throws InitializationException If a problem occurs while initializing
095 * the monitor providers that is not related
096 * to the server configuration.
097 */
098 public void initializeMonitorProviders()
099 throws ConfigException, InitializationException
100 {
101 // Get the root configuration object.
102 ServerManagementContext managementContext =
103 ServerManagementContext.getInstance();
104 RootCfg rootConfiguration =
105 managementContext.getRootConfiguration();
106
107
108 // Register as an add and delete listener with the root configuration so we
109 // can be notified if any monitor provider entries are added or removed.
110 rootConfiguration.addMonitorProviderAddListener(this);
111 rootConfiguration.addMonitorProviderDeleteListener(this);
112
113
114 //Initialize the existing monitor providers.
115 for (String name : rootConfiguration.listMonitorProviders())
116 {
117 MonitorProviderCfg monitorConfig =
118 rootConfiguration.getMonitorProvider(name);
119 monitorConfig.addChangeListener(this);
120
121 if (monitorConfig.isEnabled())
122 {
123 String className = monitorConfig.getJavaClass();
124 try
125 {
126 MonitorProvider<? extends MonitorProviderCfg> monitor =
127 loadMonitor(className, monitorConfig);
128 monitors.put(monitorConfig.dn(), monitor);
129 if (monitor.getUpdateInterval() > 0)
130 {
131 monitor.start();
132 }
133 DirectoryServer.registerMonitorProvider(monitor);
134 }
135 catch (InitializationException ie)
136 {
137 logError(ie.getMessageObject());
138 continue;
139 }
140 }
141 }
142 }
143
144
145
146 /**
147 * {@inheritDoc}
148 */
149 public boolean isConfigurationAddAcceptable(
150 MonitorProviderCfg configuration,
151 List<Message> unacceptableReasons)
152 {
153 if (configuration.isEnabled())
154 {
155 // Get the name of the class and make sure we can instantiate it as a
156 // monitor provider.
157 String className = configuration.getJavaClass();
158 try
159 {
160 loadMonitor(className, null);
161 }
162 catch (InitializationException ie)
163 {
164 unacceptableReasons.add(ie.getMessageObject());
165 return false;
166 }
167 }
168
169 // If we've gotten here, then it's fine.
170 return true;
171 }
172
173
174
175 /**
176 * {@inheritDoc}
177 */
178 public ConfigChangeResult applyConfigurationAdd(
179 MonitorProviderCfg configuration)
180 {
181 ResultCode resultCode = ResultCode.SUCCESS;
182 boolean adminActionRequired = false;
183 ArrayList<Message> messages = new ArrayList<Message>();
184
185 configuration.addChangeListener(this);
186
187 if (! configuration.isEnabled())
188 {
189 return new ConfigChangeResult(resultCode, adminActionRequired, messages);
190 }
191
192 MonitorProvider<? extends MonitorProviderCfg> monitor = null;
193
194 // Get the name of the class and make sure we can instantiate it as a
195 // monitor provider.
196 String className = configuration.getJavaClass();
197 try
198 {
199 monitor = loadMonitor(className, configuration);
200 }
201 catch (InitializationException ie)
202 {
203 if (resultCode == ResultCode.SUCCESS)
204 {
205 resultCode = DirectoryServer.getServerErrorResultCode();
206 }
207
208 messages.add(ie.getMessageObject());
209 }
210
211 if (resultCode == ResultCode.SUCCESS)
212 {
213 monitors.put(configuration.dn(), monitor);
214 if (monitor.getUpdateInterval() > 0)
215 {
216 monitor.start();
217 }
218 DirectoryServer.registerMonitorProvider(monitor);
219 }
220
221 return new ConfigChangeResult(resultCode, adminActionRequired, messages);
222 }
223
224
225
226 /**
227 * {@inheritDoc}
228 */
229 public boolean isConfigurationDeleteAcceptable(
230 MonitorProviderCfg configuration,
231 List<Message> unacceptableReasons)
232 {
233 // It will always be acceptable to delete or disable a monitor provider.
234 return true;
235 }
236
237
238
239 /**
240 * {@inheritDoc}
241 */
242 public ConfigChangeResult applyConfigurationDelete(
243 MonitorProviderCfg configuration)
244 {
245 ResultCode resultCode = ResultCode.SUCCESS;
246 boolean adminActionRequired = false;
247 ArrayList<Message> messages = new ArrayList<Message>();
248
249 MonitorProvider monitor = monitors.remove(configuration.dn());
250 if (monitor != null)
251 {
252 String lowerName = toLowerCase(monitor.getMonitorInstanceName());
253 DirectoryServer.deregisterMonitorProvider(lowerName);
254 monitor.finalizeMonitorProvider();
255 }
256
257 return new ConfigChangeResult(resultCode, adminActionRequired, messages);
258 }
259
260
261
262 /**
263 * {@inheritDoc}
264 */
265 public boolean isConfigurationChangeAcceptable(
266 MonitorProviderCfg configuration,
267 List<Message> unacceptableReasons)
268 {
269 if (configuration.isEnabled())
270 {
271 // Get the name of the class and make sure we can instantiate it as a
272 // monitor provider.
273 String className = configuration.getJavaClass();
274 try
275 {
276 loadMonitor(className, null);
277 }
278 catch (InitializationException ie)
279 {
280 unacceptableReasons.add(ie.getMessageObject());
281 return false;
282 }
283 }
284
285 // If we've gotten here, then it's fine.
286 return true;
287 }
288
289
290
291 /**
292 * {@inheritDoc}
293 */
294 public ConfigChangeResult applyConfigurationChange(
295 MonitorProviderCfg configuration)
296 {
297 ResultCode resultCode = ResultCode.SUCCESS;
298 boolean adminActionRequired = false;
299 ArrayList<Message> messages = new ArrayList<Message>();
300
301
302 // Get the existing monitor provider if it's already enabled.
303 MonitorProvider existingMonitor = monitors.get(configuration.dn());
304
305
306 // If the new configuration has the monitor disabled, then disable it if it
307 // is enabled, or do nothing if it's already disabled.
308 if (! configuration.isEnabled())
309 {
310 if (existingMonitor != null)
311 {
312 String lowerName =
313 toLowerCase(existingMonitor.getMonitorInstanceName());
314 DirectoryServer.deregisterMonitorProvider(lowerName);
315
316 MonitorProvider monitor = monitors.remove(configuration.dn());
317 if (monitor != null)
318 {
319 monitor.finalizeMonitorProvider();
320 }
321 }
322
323 return new ConfigChangeResult(resultCode, adminActionRequired, messages);
324 }
325
326
327 // Get the class for the monitor provider. If the monitor is already
328 // enabled, then we shouldn't do anything with it although if the class has
329 // changed then we'll at least need to indicate that administrative action
330 // is required. If the monitor is disabled, then instantiate the class and
331 // initialize and register it as a monitor provider.
332 String className = configuration.getJavaClass();
333 if (existingMonitor != null)
334 {
335 if (! className.equals(existingMonitor.getClass().getName()))
336 {
337 adminActionRequired = true;
338 }
339
340 return new ConfigChangeResult(resultCode, adminActionRequired, messages);
341 }
342
343 MonitorProvider<? extends MonitorProviderCfg> monitor = null;
344 try
345 {
346 monitor = loadMonitor(className, configuration);
347 }
348 catch (InitializationException ie)
349 {
350 if (resultCode == ResultCode.SUCCESS)
351 {
352 resultCode = DirectoryServer.getServerErrorResultCode();
353 }
354
355 messages.add(ie.getMessageObject());
356 }
357
358 if (resultCode == ResultCode.SUCCESS)
359 {
360 monitors.put(configuration.dn(), monitor);
361 if (monitor.getUpdateInterval() > 0)
362 {
363 monitor.start();
364 }
365 DirectoryServer.registerMonitorProvider(monitor);
366 }
367
368 return new ConfigChangeResult(resultCode, adminActionRequired, messages);
369 }
370
371
372
373 /**
374 * Loads the specified class, instantiates it as a monitor provider, and
375 * optionally initializes that instance.
376 *
377 * @param className The fully-qualified name of the monitor provider
378 * class to load, instantiate, and initialize.
379 * @param configuration The configuration to use to initialize the monitor
380 * provider, or {@code null} if the monitor provider
381 * should not be initialized.
382 *
383 * @return The possibly initialized monitor provider.
384 *
385 * @throws InitializationException If a problem occurred while attempting to
386 * initialize the monitor provider.
387 */
388 private MonitorProvider<? extends MonitorProviderCfg>
389 loadMonitor(String className, MonitorProviderCfg configuration)
390 throws InitializationException
391 {
392 try
393 {
394 MonitorProviderCfgDefn definition =
395 MonitorProviderCfgDefn.getInstance();
396 ClassPropertyDefinition propertyDefinition =
397 definition.getJavaClassPropertyDefinition();
398 Class<? extends MonitorProvider> providerClass =
399 propertyDefinition.loadClass(className, MonitorProvider.class);
400 MonitorProvider monitor = providerClass.newInstance();
401
402 if (configuration != null)
403 {
404 Method method = monitor.getClass().getMethod(
405 "initializeMonitorProvider", configuration.configurationClass());
406 method.invoke(monitor, configuration);
407 }
408
409 return (MonitorProvider<? extends MonitorProviderCfg>) monitor;
410 }
411 catch (Exception e)
412 {
413 Message message = ERR_CONFIG_MONITOR_INITIALIZATION_FAILED.
414 get(className, String.valueOf(configuration.dn()),
415 stackTraceToSingleLineString(e));
416 throw new InitializationException(message, e);
417 }
418 }
419 }
420