/* * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package instrumentj.impl; import instrumentj.CallStack; import java.io.PrintStream; import java.util.ArrayDeque; import java.util.Deque; import java.util.Iterator; /** * @author Stephen Evanchik (evanchsa@gmail.com) * */ public class CallStackHelper implements CallStack { private static final class CallStackEntryImpl implements Entry { private boolean exiting; private final String methodDescription; private final String methodName; public CallStackEntryImpl(final String methodName, final String methodDescription) { this.methodName = methodName; this.methodDescription = methodDescription; } @Override public boolean equals(Object obj) { if (this == obj) { return true; } if (obj == null) { return false; } if (!(obj instanceof CallStackEntryImpl)) { return false; } final CallStackEntryImpl other = (CallStackEntryImpl) obj; if (methodDescription == null) { if (other.methodDescription != null) { return false; } } else if (!methodDescription.equals(other.methodDescription)) { return false; } if (methodName == null) { if (other.methodName != null) { return false; } } else if (!methodName.equals(other.methodName)) { return false; } return true; } @Override public String getMethodDescription() { return methodDescription; } @Override public String getMethodName() { return methodName; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((methodDescription == null) ? 0 : methodDescription.hashCode()); result = prime * result + ((methodName == null) ? 0 : methodName.hashCode()); return result; } @Override public boolean isExiting() { return exiting; } @Override public void markExiting() { exiting = true; } @Override public String toString() { return methodName + methodDescription; } } private static final ThreadLocal<Deque<Entry>> CALL_STACK = new ThreadLocal<Deque<Entry>>() { @Override protected java.util.Deque<Entry> initialValue() { return new ArrayDeque<Entry>(); }; }; @Override public boolean findFirstParent(final String methodName) { final Iterator<Entry> stackElement = CALL_STACK.get().descendingIterator(); while (stackElement.hasNext()) { if (methodName.equals(stackElement.next().getMethodName()) && stackElement.hasNext()) { return true; } } return false; } @Override public boolean findParent(final String methodName) { for (final Entry stackElement : CALL_STACK.get()) { if (methodName.equals(stackElement.getMethodName())) { return true; } } return false; } @Override public Entry peek() { return CALL_STACK.get().peek(); } @Override public void pop() { CALL_STACK.get().pop(); } @Override public void printStackTrace(PrintStream out) { out.println("Thread: " + Thread.currentThread().getName()); for (final Entry stackElement : CALL_STACK.get()) { out.println("\t" + stackElement); } } @Override public void push(String methodName, String methodDescription) { CALL_STACK.get().push(new CallStackEntryImpl(methodName, methodDescription)); } }