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.loggers.RotationPolicy; 031 import org.opends.server.admin.server.ConfigurationAddListener; 032 import org.opends.server.admin.server.ConfigurationDeleteListener; 033 import org.opends.server.admin.server.ServerManagementContext; 034 import org.opends.server.admin.server.ConfigurationChangeListener; 035 import org.opends.server.admin.std.server.LogRotationPolicyCfg; 036 import org.opends.server.admin.std.server.RootCfg; 037 import org.opends.server.admin.std.meta.LogRotationPolicyCfgDefn; 038 import org.opends.server.admin.ClassPropertyDefinition; 039 import org.opends.server.types.InitializationException; 040 import org.opends.server.types.ConfigChangeResult; 041 import org.opends.server.types.ResultCode; 042 import org.opends.server.types.DebugLogLevel; 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 rotation 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 LogRotationPolicyConfigManager implements 063 ConfigurationAddListener<LogRotationPolicyCfg>, 064 ConfigurationDeleteListener<LogRotationPolicyCfg>, 065 ConfigurationChangeListener<LogRotationPolicyCfg> 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 rotation 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 initializeLogRotationPolicyConfig() 085 throws ConfigException, InitializationException 086 { 087 ServerManagementContext context = ServerManagementContext.getInstance(); 088 RootCfg root = context.getRootConfiguration(); 089 090 root.addLogRotationPolicyAddListener(this); 091 root.addLogRotationPolicyDeleteListener(this); 092 093 for(String name : root.listLogRotationPolicies()) 094 { 095 LogRotationPolicyCfg config = root.getLogRotationPolicy(name); 096 097 RotationPolicy rotationPolicy = getRotationPolicy(config); 098 099 DirectoryServer.registerRotationPolicy(config.dn(), rotationPolicy); 100 } 101 } 102 103 /** 104 * {@inheritDoc} 105 */ 106 public boolean isConfigurationAddAcceptable( 107 LogRotationPolicyCfg configuration, 108 List<Message> unacceptableReasons) 109 { 110 return isJavaClassAcceptable(configuration, unacceptableReasons); 111 } 112 113 /** 114 * {@inheritDoc} 115 */ 116 public boolean isConfigurationDeleteAcceptable( 117 LogRotationPolicyCfg 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(LogRotationPolicyCfg 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 RotationPolicy rotationPolicy = getRotationPolicy(config); 137 138 DirectoryServer.registerRotationPolicy(config.dn(), rotationPolicy); 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_ROTATION_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 LogRotationPolicyCfg config) 167 { 168 // Default result code. 169 ResultCode resultCode = ResultCode.SUCCESS; 170 boolean adminActionRequired = false; 171 ArrayList<Message> messages = new ArrayList<Message>(); 172 173 RotationPolicy policy = DirectoryServer.getRotationPolicy(config.dn()); 174 if(policy != null) 175 { 176 DirectoryServer.deregisterRotationPolicy(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 LogRotationPolicyCfg configuration, 192 List<Message> unacceptableReasons) 193 { 194 return isJavaClassAcceptable(configuration, unacceptableReasons); 195 } 196 197 /** 198 * {@inheritDoc} 199 */ 200 public ConfigChangeResult applyConfigurationChange( 201 LogRotationPolicyCfg configuration) 202 { 203 // Default result code. 204 ResultCode resultCode = ResultCode.SUCCESS; 205 boolean adminActionRequired = false; 206 ArrayList<Message> messages = new ArrayList<Message>(); 207 208 RotationPolicy policy = 209 DirectoryServer.getRotationPolicy(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(LogRotationPolicyCfg config, 220 List<Message> unacceptableReasons) 221 { 222 String className = config.getJavaClass(); 223 LogRotationPolicyCfgDefn d = LogRotationPolicyCfgDefn.getInstance(); 224 ClassPropertyDefinition pd = 225 d.getJavaClassPropertyDefinition(); 226 // Load the class and cast it to a RotationPolicy. 227 Class<? extends RotationPolicy> theClass; 228 try { 229 theClass = pd.loadClass(className, RotationPolicy.class); 230 theClass.newInstance(); 231 } catch (Exception e) { 232 Message message = ERR_CONFIG_ROTATION_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("initializeLogRotationPolicy", config 244 .configurationClass()); 245 } catch (Exception e) { 246 Message message = ERR_CONFIG_ROTATION_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 RotationPolicy getRotationPolicy(LogRotationPolicyCfg config) 257 throws ConfigException { 258 String className = config.getJavaClass(); 259 LogRotationPolicyCfgDefn d = LogRotationPolicyCfgDefn.getInstance(); 260 ClassPropertyDefinition pd = 261 d.getJavaClassPropertyDefinition(); 262 // Load the class and cast it to a RotationPolicy. 263 Class<? extends RotationPolicy> theClass; 264 RotationPolicy rotationPolicy; 265 try { 266 theClass = pd.loadClass(className, RotationPolicy.class); 267 rotationPolicy = 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("initializeLogRotationPolicy", config 273 .configurationClass()); 274 method.invoke(rotationPolicy, 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_ROTATION_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_ROTATION_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 rotationPolicy; 291 } 292 }