View Javadoc

1   /*
2    * This file is part of AceLogger.
3    * 
4    * AceLogger is free software: you can redistribute it and/or modify it under the terms of the GNU
5    * Lesser General Public License as published by the Free Software Foundation, either version 3 of
6    * the License, or (at your option) any later version.
7    * 
8    * AceLogger is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
9    * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
10   * Lesser General Public License for more details.
11   * 
12   * You should have received a copy of the GNU Lesser General Public License along with AceLogger.
13   * If not, see <http://www.gnu.org/licenses/lgpl-3.0.html>.
14   */
15  package net.sourceforge.acelogger.location.resolver;
16  
17  import net.sourceforge.acelogger.BaseLogger;
18  
19  /**
20   * An implementation of CodeFrameResolver that regresses a fixed number of calls.
21   * 
22   * @author Zardi (https://sourceforge.net/users/daniel_zardi)
23   * @version 1.0.0
24   * @since 1.0.0
25   */
26  public class InternalCodeFrameResolver extends BaseCodeFrameResolver {
27  
28  	/**
29  	 * The depth of this class in the logging structure.
30  	 */
31  	private static final int METHOD_DEPTH = 2;
32  
33  	/**
34  	 * The number of calls to 'look back'.
35  	 */
36  	private final int frameShift;
37  
38  	/**
39  	 * Constructs a new InternalCodeFrameResolver for the supplied frame shift.
40  	 * 
41  	 * @param frameShift
42  	 *            The number of calls that should be retroceded.
43  	 * @since 1.0.0
44  	 */
45  	public InternalCodeFrameResolver(int frameShift) {
46  		this.frameShift = frameShift + METHOD_DEPTH;
47  	}
48  
49  	/** {@inheritDoc} */
50  	public StackTraceElement getCodeFrame(Thread currentThread) {
51  		StackTraceElement[] stackTrace = currentThread.getStackTrace();
52  		int userCodeCallIndex = 0;
53  		for (int i = 0; i < stackTrace.length; i++) {
54  			String frameClassName = stackTrace[i].getClassName();
55  			if (!frameClassName.startsWith("java.util.concurrent")
56  					&& !frameClassName.startsWith("java.lang.Thread")) {
57  				userCodeCallIndex = i;
58  				if (i + frameShift < stackTrace.length) {
59  					userCodeCallIndex += frameShift;
60  				}
61  				break;
62  			}
63  		}
64  		StackTraceElement userCodeFrame = stackTrace[userCodeCallIndex];
65  		/*
66  		 * FIXME: Is this right? If the call was made without the cause parameter, then the method
67  		 * depth is 1 high
68  		 */
69  		if (userCodeFrame.getClassName().equals(BaseLogger.class.getCanonicalName())
70  				&& userCodeCallIndex + 1 < stackTrace.length) {
71  			userCodeCallIndex++;
72  			userCodeFrame = stackTrace[userCodeCallIndex];
73  		}
74  		return userCodeFrame;
75  	}
76  
77  }