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 legal-notices/CDDLv1_0.txt 010 * or http://forgerock.org/license/CDDLv1.0.html. 011 * See the License for the specific language governing permissions 012 * and limitations under the License. 013 * 014 * When distributing Covered Code, include this CDDL HEADER in each 015 * file and include the License file at legal-notices/CDDLv1_0.txt. 016 * If applicable, add the following below this CDDL HEADER, with the 017 * fields enclosed by brackets "[]" replaced with your own identifying 018 * information: 019 * Portions Copyright [yyyy] [name of copyright owner] 020 * 021 * CDDL HEADER END 022 * 023 * 024 * Copyright 2009 Sun Microsystems, Inc. 025 * Portions Copyright 2012-2015 ForgeRock AS. 026 */ 027package org.opends.server.loggers; 028 029import java.util.HashMap; 030import java.util.List; 031import java.util.Map; 032import java.util.TreeMap; 033 034import org.forgerock.i18n.LocalizableMessage; 035import org.opends.server.admin.std.server.DebugLogPublisherCfg; 036 037/** 038 * This class defines the set of methods and structures that must be 039 * implemented for a Directory Server debug log publisher. 040 * 041 * @param <T> The type of debug log publisher configuration handled 042 * by this log publisher implementation. 043 */ 044@org.opends.server.types.PublicAPI( 045 stability=org.opends.server.types.StabilityLevel.VOLATILE, 046 mayInstantiate=false, 047 mayExtend=true, 048 mayInvoke=false) 049public abstract class DebugLogPublisher<T extends DebugLogPublisherCfg> 050 implements LogPublisher<T> 051{ 052 /** The default global settings key. */ 053 private static final String GLOBAL= "_global"; 054 055 /** The map of class names to their trace settings. */ 056 private Map<String,TraceSettings> classTraceSettings; 057 058 /** The map of class names to their method trace settings. */ 059 private Map<String,Map<String,TraceSettings>> methodTraceSettings; 060 061 062 063 /** 064 * Construct a default configuration where the global scope will 065 * only log at the ERROR level. 066 */ 067 protected DebugLogPublisher() 068 { 069 classTraceSettings = null; 070 methodTraceSettings = null; 071 072 //Set the global settings so that nothing is logged. 073 addTraceSettings(null, TraceSettings.DISABLED); 074 } 075 076 077 078 /** {@inheritDoc} */ 079 @Override 080 public boolean isConfigurationAcceptable(T configuration, 081 List<LocalizableMessage> unacceptableReasons) 082 { 083 // This default implementation does not perform any special 084 // validation. It should be overridden by debug log publisher 085 // implementations that wish to perform more detailed validation. 086 return true; 087 } 088 089 090 091 /** 092 * Gets the method trace levels for a specified class. 093 * 094 * @param className The fully-qualified name of the class for 095 * which to get the trace levels. 096 * 097 *@return An unmodifiable map of trace levels keyed by method name, 098 * or {@code null} if no method-level tracing is configured 099 * for the scope. 100 */ 101 final Map<String,TraceSettings> getMethodSettings( 102 String className) 103 { 104 if(methodTraceSettings == null) 105 { 106 return null; 107 } 108 else 109 { 110 return methodTraceSettings.get(className); 111 } 112 } 113 114 115 116 /** 117 * Get the trace settings for a specified class. 118 * 119 * @param className 120 * The fully-qualified name of the class for which to get the trace 121 * levels. 122 * @return The current trace settings for the class. 123 */ 124 final TraceSettings getClassSettings(String className) 125 { 126 TraceSettings settings = null; 127 if (classTraceSettings != null) 128 { 129 // Find most specific trace setting 130 // which covers this fully qualified class name 131 // Search up the hierarchy for a match. 132 String searchName = className; 133 settings = classTraceSettings.get(searchName); 134 while (settings == null && searchName != null) 135 { 136 int clipPoint = searchName.lastIndexOf('$'); 137 if (clipPoint == -1) 138 { 139 clipPoint = searchName.lastIndexOf('.'); 140 } 141 if (clipPoint != -1) 142 { 143 searchName = searchName.substring(0, clipPoint); 144 settings = classTraceSettings.get(searchName); 145 } 146 else 147 { 148 searchName = null; 149 } 150 } 151 // Try global settings 152 // only if no specific target is defined 153 if (settings == null && classTraceSettings.size()==1) { 154 settings = classTraceSettings.get(GLOBAL); 155 } 156 } 157 return settings == null ? TraceSettings.DISABLED : settings; 158 } 159 160 161 162 /** 163 * Adds a trace settings to the current set for a specified scope. 164 * If a scope is not specified, the settings will be set for the 165 * global scope. The global scope settings are used when no other 166 * scope matches. 167 * 168 * @param scope The scope for which to set the trace settings. 169 * This should be a fully-qualified class name, or 170 * {@code null} to set the trace settings for the 171 * global scope. 172 * @param settings The trace settings for the specified scope. 173 */ 174 public final void addTraceSettings(String scope, TraceSettings settings) 175 { 176 if (scope == null) { 177 setClassSettings(GLOBAL, settings); 178 } 179 else { 180 int methodPt= scope.lastIndexOf('#'); 181 if (methodPt != -1) { 182 String methodName= scope.substring(methodPt+1); 183 scope= scope.substring(0, methodPt); 184 setMethodSettings(scope, methodName, settings); 185 } 186 else { 187 setClassSettings(scope, settings); 188 } 189 } 190 } 191 192 /** 193 * Determine whether a trace setting is already defined for a particular 194 * scope. 195 * 196 * @param scope 197 * The scope for which to make the determination. This should be a 198 * fully-qualified class name. 199 * @return {@code true} if a trace settings is defined for the specified 200 * scope, {@code false} otherwise. 201 */ 202 final boolean hasTraceSettings(String scope) 203 { 204 int methodPt = scope.lastIndexOf('#'); 205 if (methodPt != -1) 206 { 207 String methodName = scope.substring(methodPt + 1); 208 scope = scope.substring(0, methodPt); 209 if (methodTraceSettings != null) 210 { 211 Map<String, TraceSettings> methodLevels = 212 methodTraceSettings.get(scope); 213 if (methodLevels != null) 214 { 215 return methodLevels.containsKey(methodName); 216 } 217 } 218 } 219 else if (classTraceSettings != null) 220 { 221 return classTraceSettings.containsKey(scope); 222 } 223 return false; 224 } 225 226 227 228 /** 229 * Remove a trace setting by scope. 230 * 231 * @param scope The scope for which to remove the trace setting. 232 * This should be a fully-qualified class name, or 233 * {@code null} to remove the trace setting for the 234 * global scope. 235 * 236 * @return The trace settings for the specified scope, or 237 * {@code null} if no trace setting is defined for that 238 * scope. 239 */ 240 final TraceSettings removeTraceSettings(String scope) 241 { 242 TraceSettings removedSettings = null; 243 if (scope == null) { 244 if(classTraceSettings != null) 245 { 246 removedSettings = classTraceSettings.remove(GLOBAL); 247 } 248 } 249 else { 250 int methodPt= scope.lastIndexOf('#'); 251 if (methodPt != -1) { 252 String methodName= scope.substring(methodPt+1); 253 scope= scope.substring(0, methodPt); 254 if(methodTraceSettings != null) 255 { 256 Map<String, TraceSettings> methodLevels = 257 methodTraceSettings.get(scope); 258 if(methodLevels != null) 259 { 260 removedSettings = methodLevels.remove(methodName); 261 if(methodLevels.isEmpty()) 262 { 263 methodTraceSettings.remove(scope); 264 } 265 } 266 } 267 } 268 else { 269 if(classTraceSettings != null) 270 { 271 removedSettings = classTraceSettings.remove(scope); 272 } 273 } 274 } 275 276 return removedSettings; 277 } 278 279 /** 280 * Set the trace settings for a class. 281 * 282 * @param className The class name. 283 * @param settings The trace settings for the class. 284 */ 285 private final synchronized void setClassSettings(String className, TraceSettings settings) 286 { 287 if (classTraceSettings == null) 288 { 289 classTraceSettings = new HashMap<>(); 290 } 291 classTraceSettings.put(className, settings); 292 } 293 294 295 296 /** 297 * Set the method settings for a particular method in a class. 298 * 299 * @param className The class name. 300 * @param methodName The method name. 301 * @param settings The trace settings for the method. 302 */ 303 private final synchronized void setMethodSettings(String className, 304 String methodName, TraceSettings settings) 305 { 306 if (methodTraceSettings == null) { 307 methodTraceSettings = new HashMap<>(); 308 } 309 Map<String, TraceSettings> methodLevels = methodTraceSettings.get(className); 310 if (methodLevels == null) 311 { 312 methodLevels = new TreeMap<>(); 313 methodTraceSettings.put(className, methodLevels); 314 } 315 methodLevels.put(methodName, settings); 316 } 317 318 319 320 /** 321 * Log an arbitrary event in a method. 322 * @param settings The current trace settings in effect. 323 * @param signature The method signature. 324 * @param sourceLocation The location of the method in the source. 325 * @param msg The message to be logged. 326 * @param stackTrace The stack trace at the time the message 327 * is logged or null if its not available. 328 */ 329 public abstract void trace(TraceSettings settings, String signature, 330 String sourceLocation, String msg, StackTraceElement[] stackTrace); 331 332 333 334 /** 335 * Log a caught exception in a method. 336 * @param settings The current trace settings in effect. 337 * @param signature The method signature. 338 * @param sourceLocation The location of the method in the source. 339 * @param msg The message to be logged. 340 * @param ex The exception that was caught. 341 * @param stackTrace The stack trace at the time the exception 342 * is caught or null if its not available. 343 */ 344 public abstract void traceException(TraceSettings settings, String signature, 345 String sourceLocation, String msg, Throwable ex, 346 StackTraceElement[] stackTrace); 347 348}