001/* 002 * The contents of this file are subject to the terms of the Common Development and 003 * Distribution License (the License). You may not use this file except in compliance with the 004 * License. 005 * 006 * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the 007 * specific language governing permission and limitations under the License. 008 * 009 * When distributing Covered Software, include this CDDL Header Notice in each file and include 010 * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL 011 * Header, with the fields enclosed by brackets [] replaced by your own identifying 012 * information: "Portions Copyright [year] [name of copyright owner]". 013 * 014 * Copyright 2006-2010 Sun Microsystems, Inc. 015 * Portions Copyright 2013-2016 ForgeRock AS. 016 */ 017package org.opends.server.core; 018 019import static org.opends.messages.ConfigMessages.*; 020import static org.opends.server.util.StaticUtils.*; 021 022import java.util.List; 023import java.util.concurrent.ConcurrentHashMap; 024 025import org.forgerock.i18n.LocalizableMessage; 026import org.forgerock.i18n.slf4j.LocalizedLogger; 027import org.forgerock.opendj.config.server.ConfigException; 028import org.forgerock.opendj.ldap.ResultCode; 029import org.forgerock.opendj.config.ClassPropertyDefinition; 030import org.forgerock.opendj.config.server.ConfigurationAddListener; 031import org.forgerock.opendj.config.server.ConfigurationChangeListener; 032import org.forgerock.opendj.config.server.ConfigurationDeleteListener; 033import org.forgerock.opendj.server.config.meta.MonitorProviderCfgDefn; 034import org.forgerock.opendj.server.config.server.MonitorProviderCfg; 035import org.forgerock.opendj.server.config.server.RootCfg; 036import org.opends.server.api.MonitorProvider; 037import org.forgerock.opendj.config.server.ConfigChangeResult; 038import org.forgerock.opendj.ldap.DN; 039import org.opends.server.types.InitializationException; 040 041/** 042 * This class defines a utility that will be used to manage the set of monitor 043 * providers defined in the Directory Server. It will initialize the monitor 044 * providers when the server starts, and then will manage any additions, 045 * removals, or modifications to any providers while the server is running. 046 */ 047public class MonitorConfigManager 048 implements ConfigurationChangeListener<MonitorProviderCfg>, 049 ConfigurationAddListener<MonitorProviderCfg>, 050 ConfigurationDeleteListener<MonitorProviderCfg> 051{ 052 private static final LocalizedLogger logger = LocalizedLogger.getLoggerForThisClass(); 053 054 /** A mapping between the DNs of the config entries and the associated monitor providers. */ 055 private final ConcurrentHashMap<DN,MonitorProvider<?>> monitors; 056 057 private final ServerContext serverContext; 058 059 /** 060 * Creates a new instance of this monitor provider config manager. 061 * 062 * @param serverContext 063 * The server context. 064 */ 065 public MonitorConfigManager(ServerContext serverContext) 066 { 067 this.serverContext = serverContext; 068 monitors = new ConcurrentHashMap<>(); 069 } 070 071 /** 072 * Initializes all monitor providers currently defined in the Directory Server 073 * configuration. This should only be called at Directory Server startup. 074 * 075 * @throws ConfigException If a configuration problem causes the monitor 076 * provider initialization process to fail. 077 * 078 * @throws InitializationException If a problem occurs while initializing 079 * the monitor providers that is not related 080 * to the server configuration. 081 */ 082 public void initializeMonitorProviders() 083 throws ConfigException, InitializationException 084 { 085 RootCfg rootConfiguration = serverContext.getRootConfig(); 086 rootConfiguration.addMonitorProviderAddListener(this); 087 rootConfiguration.addMonitorProviderDeleteListener(this); 088 089 //Initialize the existing monitor providers. 090 for (String name : rootConfiguration.listMonitorProviders()) 091 { 092 MonitorProviderCfg monitorConfig = 093 rootConfiguration.getMonitorProvider(name); 094 monitorConfig.addChangeListener(this); 095 096 if (monitorConfig.isEnabled()) 097 { 098 String className = monitorConfig.getJavaClass(); 099 try 100 { 101 MonitorProvider<? extends MonitorProviderCfg> monitor = 102 loadMonitor(className, monitorConfig); 103 monitors.put(monitorConfig.dn(), monitor); 104 DirectoryServer.registerMonitorProvider(monitor); 105 } 106 catch (InitializationException ie) 107 { 108 logger.error(ie.getMessageObject()); 109 continue; 110 } 111 } 112 } 113 } 114 115 @Override 116 public boolean isConfigurationAddAcceptable( 117 MonitorProviderCfg configuration, 118 List<LocalizableMessage> unacceptableReasons) 119 { 120 if (configuration.isEnabled()) 121 { 122 // Get the name of the class and make sure we can instantiate it as a 123 // monitor provider. 124 String className = configuration.getJavaClass(); 125 try 126 { 127 loadMonitor(className, null); 128 } 129 catch (InitializationException ie) 130 { 131 unacceptableReasons.add(ie.getMessageObject()); 132 return false; 133 } 134 } 135 136 // If we've gotten here, then it's fine. 137 return true; 138 } 139 140 @Override 141 public ConfigChangeResult applyConfigurationAdd( 142 MonitorProviderCfg configuration) 143 { 144 final ConfigChangeResult ccr = new ConfigChangeResult(); 145 146 configuration.addChangeListener(this); 147 148 if (! configuration.isEnabled()) 149 { 150 return ccr; 151 } 152 153 MonitorProvider<? extends MonitorProviderCfg> monitor = null; 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 monitor = loadMonitor(className, configuration); 161 } 162 catch (InitializationException ie) 163 { 164 ccr.setResultCodeIfSuccess(DirectoryServer.getServerErrorResultCode()); 165 ccr.addMessage(ie.getMessageObject()); 166 } 167 168 if (ccr.getResultCode() == ResultCode.SUCCESS) 169 { 170 monitors.put(configuration.dn(), monitor); 171 DirectoryServer.registerMonitorProvider(monitor); 172 } 173 174 return ccr; 175 } 176 177 @Override 178 public boolean isConfigurationDeleteAcceptable( 179 MonitorProviderCfg configuration, 180 List<LocalizableMessage> unacceptableReasons) 181 { 182 // It will always be acceptable to delete or disable a monitor provider. 183 return true; 184 } 185 186 @Override 187 public ConfigChangeResult applyConfigurationDelete( 188 MonitorProviderCfg configuration) 189 { 190 final ConfigChangeResult ccr = new ConfigChangeResult(); 191 192 MonitorProvider<?> monitor = monitors.remove(configuration.dn()); 193 if (monitor != null) 194 { 195 DirectoryServer.deregisterMonitorProvider(monitor); 196 monitor.finalizeMonitorProvider(); 197 } 198 199 return ccr; 200 } 201 202 @Override 203 public boolean isConfigurationChangeAcceptable( 204 MonitorProviderCfg configuration, 205 List<LocalizableMessage> unacceptableReasons) 206 { 207 if (configuration.isEnabled()) 208 { 209 // Get the name of the class and make sure we can instantiate it as a 210 // monitor provider. 211 String className = configuration.getJavaClass(); 212 try 213 { 214 loadMonitor(className, null); 215 } 216 catch (InitializationException ie) 217 { 218 unacceptableReasons.add(ie.getMessageObject()); 219 return false; 220 } 221 } 222 223 // If we've gotten here, then it's fine. 224 return true; 225 } 226 227 @Override 228 public ConfigChangeResult applyConfigurationChange( 229 MonitorProviderCfg configuration) 230 { 231 final ConfigChangeResult ccr = new ConfigChangeResult(); 232 233 // Get the existing monitor provider if it's already enabled. 234 MonitorProvider<?> existingMonitor = monitors.get(configuration.dn()); 235 236 // If the new configuration has the monitor disabled, then disable it if it 237 // is enabled, or do nothing if it's already disabled. 238 if (! configuration.isEnabled()) 239 { 240 if (existingMonitor != null) 241 { 242 DirectoryServer.deregisterMonitorProvider(existingMonitor); 243 MonitorProvider<?> monitor = monitors.remove(configuration.dn()); 244 if (monitor != null) 245 { 246 monitor.finalizeMonitorProvider(); 247 } 248 } 249 250 return ccr; 251 } 252 253 // Get the class for the monitor provider. If the monitor is already 254 // enabled, then we shouldn't do anything with it although if the class has 255 // changed then we'll at least need to indicate that administrative action 256 // is required. If the monitor is disabled, then instantiate the class and 257 // initialize and register it as a monitor provider. 258 String className = configuration.getJavaClass(); 259 if (existingMonitor != null) 260 { 261 if (! className.equals(existingMonitor.getClass().getName())) 262 { 263 ccr.setAdminActionRequired(true); 264 } 265 266 return ccr; 267 } 268 269 MonitorProvider<? extends MonitorProviderCfg> monitor = null; 270 try 271 { 272 monitor = loadMonitor(className, configuration); 273 } 274 catch (InitializationException ie) 275 { 276 ccr.setResultCodeIfSuccess(DirectoryServer.getServerErrorResultCode()); 277 ccr.addMessage(ie.getMessageObject()); 278 } 279 280 if (ccr.getResultCode() == ResultCode.SUCCESS) 281 { 282 monitors.put(configuration.dn(), monitor); 283 DirectoryServer.registerMonitorProvider(monitor); 284 } 285 286 return ccr; 287 } 288 289 /** 290 * Loads the specified class, instantiates it as a monitor provider, and 291 * optionally initializes that instance. 292 * 293 * @param className The fully-qualified name of the monitor provider 294 * class to load, instantiate, and initialize. 295 * @param configuration The configuration to use to initialize the monitor 296 * provider, or {@code null} if the monitor provider 297 * should not be initialized. 298 * 299 * @return The possibly initialized monitor provider. 300 * 301 * @throws InitializationException If a problem occurred while attempting to 302 * initialize the monitor provider. 303 */ 304 private <T extends MonitorProviderCfg> MonitorProvider<T> 305 loadMonitor(String className, T configuration) 306 throws InitializationException 307 { 308 try 309 { 310 MonitorProviderCfgDefn definition = MonitorProviderCfgDefn.getInstance(); 311 ClassPropertyDefinition propertyDefinition = 312 definition.getJavaClassPropertyDefinition(); 313 @SuppressWarnings("unchecked") 314 Class<? extends MonitorProvider<T>> providerClass = 315 (Class<? extends MonitorProvider<T>>) propertyDefinition 316 .loadClass(className, MonitorProvider.class); 317 MonitorProvider<T> monitor = providerClass.newInstance(); 318 319 if (configuration != null) 320 { 321 monitor.initializeMonitorProvider(configuration); 322 } 323 324 return monitor; 325 } 326 catch (Exception e) 327 { 328 LocalizableMessage message = ERR_CONFIG_MONITOR_INITIALIZATION_FAILED. 329 get(className, configuration.dn(), stackTraceToSingleLineString(e)); 330 throw new InitializationException(message, e); 331 } 332 } 333}