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    }