001 /*
002 * Licensed under the Apache License, Version 2.0 (the "License");
003 * you may not use this file except in compliance with the License.
004 * You may obtain a copy of the License at
005 *
006 * http://www.apache.org/licenses/LICENSE-2.0
007 *
008 * Unless required by applicable law or agreed to in writing, software
009 * distributed under the License is distributed on an "AS IS" BASIS,
010 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
011 * See the License for the specific language governing permissions and
012 * limitations under the License.
013 */
014 package org.apache.commons.classscan.util;
015
016 public abstract class CallStack {
017
018 interface GetCallerStrategy {
019 Class<?> getCallerClass(int callStackDepth);
020 }
021
022 private static GetCallerStrategy strategy;
023
024 static class SunReflection implements GetCallerStrategy {
025 SunReflection() {
026 // cause load of sun.reflect.Reflection class
027 sun.reflect.Reflection.getCallerClass(0);
028 }
029
030 @Override
031 public Class<?> getCallerClass(int callStackDepth) {
032 return sun.reflect.Reflection.getCallerClass(callStackDepth);
033 }
034 }
035
036 static class SecurityManagerMethod extends SecurityManager implements GetCallerStrategy {
037 @Override
038 public Class<?> getCallerClass(int callStackDepth) {
039 return getClassContext()[callStackDepth];
040 }
041 }
042
043 static {
044 try {
045 strategy= new SunReflection();
046 }
047 catch(Throwable t) {
048 strategy= new SecurityManagerMethod();
049 }
050 }
051
052 /**
053 * Return the Class of the caller.
054 * @param callStackDepth The number of stack frames to skip.
055 * A value of 0 will return the calling Class of this method.
056 * A value of 1 will return the calling Class of the caller of this method.
057 * @return The Class at callStackDepth down the call stack
058 */
059 public static Class<?> getCallerClass(int callStackDepth) {
060 return strategy.getCallerClass(callStackDepth+3);
061 }
062
063 /**
064 * Return the ClassLoader of the caller.
065 * @param callStackDepth The number of stack frames to skip.
066 * A value of 0 will return the ClassLoader of the calling Class of this method.
067 * A value of 1 will return the ClassLoader of the calling Class of the caller of this method.
068 * @return The ClassLoader of the Class at callStackDepth down the call stack
069 */
070 public static ClassLoader getClassLoader(int callStackDepth) {
071 Class<?> rc= strategy.getCallerClass(callStackDepth+3);
072 return rc.getClassLoader();
073 }
074 }