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.loggers.debug; 028 029 import org.aspectj.lang.annotation.*; 030 import org.aspectj.lang.JoinPoint; 031 032 import static 033 org.opends.server.loggers.debug.DebugLogger.DEFAULT_CONSTRUCTOR_LEVEL; 034 import static 035 org.opends.server.loggers.debug.DebugLogger.DEFAULT_ENTRY_EXIT_LEVEL; 036 import static 037 org.opends.server.loggers.debug.DebugLogger.DEFAULT_THROWN_LEVEL; 038 039 /** 040 * An aspect for source-code tracing at the method level. 041 * 042 * One DebugLogger aspect instance exists for each Java class using tracing. 043 * Tracer must be registered with the DebugLogger. 044 * 045 * Logging is always done at a level basis, with debug log messages 046 * exceeding the trace threshold being traced, others being discarded. 047 */ 048 @Aspect() 049 public class DebugAspect 050 { 051 /** 052 * Pointcut for matching static context events. 053 */ 054 @Pointcut("!this(Object)") 055 private void staticContext() 056 { 057 } 058 059 /** 060 * Pointcut for matching non static context events. 061 * @param obj The object being operated on. 062 */ 063 @Pointcut("this(obj)") 064 private void nonStaticContext(Object obj) 065 { 066 } 067 068 /** 069 * Pointcut for matching all toString() methods. 070 */ 071 @Pointcut("execution(* *..toString(..))") 072 private void toStringMethod() 073 { 074 } 075 076 /** 077 * Pointcut for matching all getMessage() methods. 078 */ 079 @Pointcut("execution(String org.opends.server." + 080 "messages.MessageHandler.getMessage(..))") 081 private void getMessageMethod() 082 { 083 } 084 085 /** 086 * Pointcut for matching the getDirectoryThreadGroup method. 087 */ 088 @Pointcut("execution(public static ThreadGroup org.opends.server." + 089 "core.DirectoryServer.getDirectoryThreadGroup(..))") 090 private void getThreadGroupMethod() 091 { 092 } 093 094 /** 095 * Pointcut for matching all getDebugProperties() methods. 096 * TODO: Make this less general. Find out if pointcut matches 097 * subclass methods. 098 */ 099 @Pointcut("execution(* *..getDebugProperties(..))") 100 private void getDebugPropertiesMethod() 101 { 102 } 103 104 /** 105 * Pointcut for matching all logging related classes. 106 */ 107 @Pointcut("within(org.opends.server.loggers.*+ || " + 108 "org.opends.server.loggers.debug..*+ || " + 109 "org.opends.server.types.DebugLogLevel+ || " + 110 "org.opends.server.types.DebugLogCategory+ || " + 111 "org.opends.server.api.DebugLogPublisher+ || " + 112 "org.opends.server.util.TimeThread+ ||" + 113 "org.opends.server.util.MultiOutputStream+)") 114 private void debugRelatedClasses() 115 { 116 } 117 118 /** 119 * Pointcut to exclude all pointcuts which should not be adviced by the 120 * debug logger. 121 */ 122 @Pointcut("toStringMethod() || getMessageMethod() || " + 123 "getDebugPropertiesMethod() || debugRelatedClasses() || " + 124 "getThreadGroupMethod()") 125 private void excluded() 126 { 127 } 128 129 /** 130 * Pointcut for matching the execution of all public methods. 131 */ 132 @Pointcut("execution(!@(DebugLogger.NoDebugTracing || " + 133 "DebugLogger.NoEntryDebugTracing) public * *(..)) && " + 134 "!excluded()") 135 void tracedEntryMethod() 136 { 137 } 138 139 /** 140 * Pointcut for matching the execution of all public methods. 141 */ 142 @Pointcut("execution(!@(DebugLogger.NoDebugTracing || " + 143 "DebugLogger.NoExitDebugTracing) public * *(..)) && " + 144 "!excluded()") 145 void tracedExitMethod() 146 { 147 } 148 149 /** 150 * Pointcut for matching the execution of all public methods. 151 */ 152 @Pointcut("execution(@DebugLogger.TraceThrown public * *(..)) && " + 153 "!excluded()") 154 void tracedThrownMethod() 155 { 156 } 157 158 /** 159 * Pointcut for matching the execution of all constructors. 160 */ 161 @Pointcut("execution(!@(DebugLogger.NoDebugTracing || " + 162 "DebugLogger.NoEntryDebugTracing) public new(..)) && !excluded()") 163 void tracedEntryConstructor() 164 { 165 } 166 167 /** 168 * Pointcut for matching the execution of all constructors. 169 */ 170 @Pointcut("execution(!@(DebugLogger.NoDebugTracing || " + 171 "DebugLogger.NoExitDebugTracing) public new(..)) && !excluded()") 172 void tracedExitConstructor() 173 { 174 } 175 176 /** 177 * Pointcut for matching only if there are publishers. 178 * 179 * @return if debug logging is enabled. 180 */ 181 @Pointcut("if()") 182 public static boolean shouldTrace() 183 { 184 return DebugLogger.enabled; 185 } 186 187 /** 188 * AspectJ Implementation. 189 * 190 * @param thisJoinPoint the JoinPoint reflection object. 191 */ 192 @Before("shouldTrace() && tracedEntryConstructor()") 193 public void traceConstructor(JoinPoint thisJoinPoint) 194 { 195 String signature = 196 thisJoinPoint.getSignature().getDeclaringTypeName(); 197 Object[] args = thisJoinPoint.getArgs(); 198 DebugTracer tracer = DebugLogger.getTracer(signature); 199 if(tracer != null) 200 { 201 tracer.debugConstructor( 202 DEFAULT_CONSTRUCTOR_LEVEL, args); 203 } 204 } 205 206 /** 207 * AspectJ Implementation. 208 * 209 * @param thisJoinPoint the JoinPoint reflection object. 210 * @param obj the object this method operations on. 211 */ 212 @Before("shouldTrace() && tracedEntryMethod() && nonStaticContext(obj)") 213 public void traceNonStaticMethodEntry(JoinPoint thisJoinPoint, Object obj) 214 { 215 String signature = 216 thisJoinPoint.getSignature().getDeclaringTypeName(); 217 Object[] args = thisJoinPoint.getArgs(); 218 Object callerInstance = thisJoinPoint.getThis(); 219 DebugTracer tracer = DebugLogger.getTracer(signature); 220 if(tracer != null) 221 { 222 tracer.debugMethodEntry( 223 DEFAULT_ENTRY_EXIT_LEVEL, callerInstance, args); 224 } 225 } 226 227 /** 228 * AspectJ Implementation. 229 * 230 * @param thisJoinPoint the JoinPoint reflection object. 231 */ 232 @Before("shouldTrace() && tracedEntryMethod() && staticContext()") 233 public void traceStaticMethodEntry(JoinPoint thisJoinPoint) 234 { 235 String signature = 236 thisJoinPoint.getSignature().getDeclaringTypeName(); 237 Object[] args = thisJoinPoint.getArgs(); 238 DebugTracer tracer = DebugLogger.getTracer(signature); 239 if(tracer != null) 240 { 241 tracer.debugStaticMethodEntry( 242 DEFAULT_ENTRY_EXIT_LEVEL, args); 243 } 244 } 245 246 /** 247 * AspectJ Implementation. 248 * 249 * @param thisJoinPointStaticPart the JoinPoint reflection object. 250 * @param ret the return value of the method. 251 */ 252 @AfterReturning(pointcut = "shouldTrace() && " + 253 "(tracedExitMethod() || tracedExitConstructor())", 254 returning = "ret") 255 public void traceReturn(JoinPoint.StaticPart thisJoinPointStaticPart, 256 Object ret) 257 { 258 String signature = 259 thisJoinPointStaticPart.getSignature().getDeclaringTypeName(); 260 DebugTracer tracer = DebugLogger.getTracer(signature); 261 if(tracer != null) 262 { 263 tracer.debugReturn( 264 DEFAULT_ENTRY_EXIT_LEVEL, ret); 265 } 266 } 267 268 /** 269 * AspectJ Implementation. 270 * 271 * @param thisJoinPointStaticPart the JoinPoint reflection object. 272 * @param ex the exception thrown. 273 */ 274 @SuppressAjWarnings({"adviceDidNotMatch"}) 275 @AfterThrowing(pointcut = "shouldTrace() && tracedThrownMethod()", 276 throwing = "ex") 277 public void traceThrown(JoinPoint.StaticPart thisJoinPointStaticPart, 278 Throwable ex) 279 { 280 String signature = 281 thisJoinPointStaticPart.getSignature().getDeclaringTypeName(); 282 DebugTracer tracer = DebugLogger.getTracer(signature); 283 if(tracer != null) 284 { 285 tracer.debugThrown( 286 DEFAULT_THROWN_LEVEL, ex); 287 } 288 } 289 }