org.wildfly.security.manager.StackInspector Maven / Gradle / Ivy
The newest version!
/*
* JBoss, Home of Professional Open Source.
* Copyright 2013 Red Hat, Inc., and individual contributors
* as indicated by the @author tags.
*
* 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 org.wildfly.security.manager;
import static java.lang.Math.max;
import static java.lang.Math.min;
import static java.lang.System.getSecurityManager;
import static java.util.Arrays.copyOfRange;
import static org.wildfly.security.manager.WildFlySecurityManagerPermission.getStackInspectorPermission;
/**
* A utility class which is useful for inspecting the call stack.
*
* @author David M. Lloyd
*/
public final class StackInspector {
private static final StackInspector INSTANCE = new StackInspector();
private StackInspector() {
}
/**
* Get the singleton {@code StackInspector} instance. The caller must have the {@code getStackInspector}
* {@link RuntimePermission}.
* If the security manager is enabled, requires {@code getStackInspector} {@link WildFlySecurityManagerPermission}.
*
* @return the singleton {@code StackInspector} instance
*/
public static StackInspector getInstance() {
final SecurityManager securityManager = getSecurityManager();
if (securityManager instanceof WildFlySecurityManager) {
securityManager.checkPermission(getStackInspectorPermission, INSTANCE.getCallerClass(1));
} else if (securityManager != null) {
securityManager.checkPermission(getStackInspectorPermission);
}
return INSTANCE;
}
/**
* Get the caller class. The {@code skipFrames} argument specifies how many spots to go back
* on the call stack; 0 indicates the immediate caller.
*
* @param skipFrames the number of frames to skip over before the immediate caller
* @return the caller class
*/
public Class> getCallerClass(int skipFrames) {
return WildFlySecurityManager.getCallerClass(max(0, skipFrames) + 1);
}
/**
* Get all or a portion of the call stack. The {@code numFrames} argument specifies how many frames should be
* returned.
*
* @param skipFrames the number of frames to skip; 0 will include the immediate caller at index 0
* @param numFrames the maximum number of frames to return
* @return the partial call stack
*/
public Class>[] getCallStack(int skipFrames, int numFrames) {
final Class>[] stack = WildFlySecurityManager.getCallStack();
final int from = max(0, skipFrames) + 2;
return copyOfRange(stack, from, min(from + numFrames, stack.length));
}
/**
* Get all or a portion of the call stack. The {@code numFrames} argument specifies how many frames should be
* returned.
*
* @param skipFrames the number of frames to skip; 0 will include the immediate caller at index 0
* @return the partial call stack
*/
public Class>[] getCallStack(int skipFrames) {
final Class>[] stack = WildFlySecurityManager.getCallStack();
final int from = max(0, skipFrames) + 2;
return copyOfRange(stack, from, stack.length);
}
/**
* Get the call stack.
*
* @return the call stack
*/
public Class>[] getCallStack() {
final Class>[] stack = WildFlySecurityManager.getCallStack();
return copyOfRange(stack, 2, stack.length);
}
/**
* Determine whether the call stack contains a given class. Useful for assertions.
*
* @param clazz the class to test
* @return {@code true} if the call stack contains the class
*/
public boolean callStackContains(Class> clazz) {
final Class>[] stack = WildFlySecurityManager.getCallStack();
for (int i = 2; i < stack.length; i ++) {
if (stack[i] == clazz) return true;
}
return false;
}
}