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 }