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