package org.jboss.weld.bean.proxy;
import java.io.Serializable;
import java.lang.reflect.Method;
import org.jboss.weld.bean.proxy.InterceptionDecorationContext.Stack;
import org.jboss.weld.exceptions.UnsupportedOperationException;
import org.jboss.weld.interceptor.proxy.InterceptorMethodHandler;
import org.jboss.weld.util.reflection.Reflections;
/**
* A method handler that wraps the invocation of interceptors and decorators.
*
* @author Marius Bogoevici
*/
public class CombinedInterceptorAndDecoratorStackMethodHandler implements StackAwareMethodHandler, Serializable {
public static final CombinedInterceptorAndDecoratorStackMethodHandler NULL_INSTANCE = new CombinedInterceptorAndDecoratorStackMethodHandler() {
@Override
public void setInterceptorMethodHandler(InterceptorMethodHandler interceptorMethodHandler) {
throw new UnsupportedOperationException();
}
@Override
public void setOuterDecorator(Object outerDecorator) {
throw new UnsupportedOperationException();
}
@Override
public Object invoke(Object self, Method thisMethod, Method proceed, Object[] args) throws Throwable {
throw new UnsupportedOperationException();
}
};
private InterceptorMethodHandler interceptorMethodHandler;
private Object outerDecorator;
public void setInterceptorMethodHandler(InterceptorMethodHandler interceptorMethodHandler) {
this.interceptorMethodHandler = interceptorMethodHandler;
}
public void setOuterDecorator(Object outerDecorator) {
this.outerDecorator = outerDecorator;
}
@Override
public Object invoke(Object self, Method thisMethod, Method proceed, Object[] args) throws Throwable {
throw new UnsupportedOperationException();
}
@Override
public Object invoke(Stack stack, Object self, Method thisMethod, Method proceed, Object[] args) throws Throwable {
if (stack == null) {
/*
* This is a lifecycle callback invocation.
* 1) Lifecycle callback interception is never suppressed by IDC
* 2) Interception of methods called by lifecycle callbacks is suppressed
*/
stack = InterceptionDecorationContext.getStack();
return invoke(stack, self, thisMethod, proceed, args, true, stack.startIfNotOnTop(this));
} else {
/*
* This is an around-invoke interception
* Interceptors are invoked as long as the current IDC is not suppressed.
*/
boolean intercept = stack.startIfNotOnTop(this);
return invoke(stack, self, thisMethod, proceed, args, intercept, intercept);
}
}
public Object invoke(Stack stack, Object self, Method thisMethod, Method proceed, Object[] args, boolean intercept, boolean popStack) throws Throwable {
if (intercept) {
try {
if (interceptorMethodHandler != null) {
if (proceed != null) {
if (outerDecorator == null) {
// use WeldSubclass.method$$super() as proceed
return this.interceptorMethodHandler.invoke(stack, self, thisMethod, proceed, args);
} else {
return this.interceptorMethodHandler.invoke(stack, outerDecorator, thisMethod, thisMethod, args);
}
} else {
return this.interceptorMethodHandler.invoke(stack, self, thisMethod, null, args);
}
} else {
if (outerDecorator != null) {
SecurityActions.ensureAccessible(thisMethod);
return Reflections.invokeAndUnwrap(outerDecorator, thisMethod, args);
}
}
} finally {
if (popStack) {
stack.end();
}
}
}
SecurityActions.ensureAccessible(proceed);
return Reflections.invokeAndUnwrap(self, proceed, args);
}
public InterceptorMethodHandler getInterceptorMethodHandler() {
return interceptorMethodHandler;
}
public Object getOuterDecorator() {
return outerDecorator;
}
public boolean isDisabledHandler() {
return this == InterceptionDecorationContext.peekIfNotEmpty();
}
public boolean isDisabledHandler(Stack stack) {
return this == stack.peek();
}
}