/*
* JBoss, Home of Professional Open Source.
* Copyright 2013, Red Hat, Inc., and individual contributors
* as indicated by the @author tags. See the copyright.txt file in the
* distribution for a full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.jboss.narayana.compensations.internal;
import org.jboss.narayana.compensations.api.Compensatable;
import org.jboss.narayana.compensations.api.CompensationManager;
import javax.inject.Inject;
import javax.interceptor.InvocationContext;
import java.lang.annotation.Annotation;
/**
* @author <a href="mailto:gytis@redhat.com">Gytis Trikleris</a>
*/
public class CompensationInterceptorBase {
@Inject
CompensationManager compensationManager;
@Inject
javax.enterprise.inject.spi.BeanManager beanManager;
protected Object invokeInOurTx(InvocationContext ic) throws Exception {
BAController baController;
Compensatable compensatable = getCompensatable(ic);
if (compensatable.distributed()) {
baController = BAControllerFactory.getRemoteInstance();
} else {
baController = BAControllerFactory.getLocalInstance();
}
baController.beginBusinessActivity();
Object result = null;
boolean isException = false;
try {
result = ic.proceed();
} catch (Exception e) {
isException = true;
handleException(ic, e, true);
} finally {
baController.completeBusinessActivity(isException);
}
return result;
}
protected Object invokeInCallerTx(InvocationContext ic) throws Exception {
Object result = null;
try {
result = ic.proceed();
} catch (Exception e) {
handleException(ic, e, false);
}
return result;
}
protected Object invokeInNoTx(InvocationContext ic) throws Exception {
return ic.proceed();
}
private void handleException(final InvocationContext ic, final Exception exception, final boolean started) throws Exception {
final Compensatable compensatable = getCompensatable(ic);
if (isDontCancelOn(compensatable, exception)) {
throw exception;
}
if (isCancelOn(compensatable, exception) || exception instanceof RuntimeException) {
compensationManager.setCompensateOnly();
}
throw exception;
}
private boolean isDontCancelOn(final Compensatable compensatable, final Exception exception) {
for (Class dontCancelOnClass : compensatable.dontCancelOn()) {
if (dontCancelOnClass.isAssignableFrom(exception.getClass())) {
return true;
}
}
return false;
}
private boolean isCancelOn(final Compensatable compensatable, final Exception exception) {
for (Class cancelOnClass : compensatable.cancelOn()) {
if (cancelOnClass.isAssignableFrom(exception.getClass())) {
return true;
}
}
return false;
}
private Compensatable getCompensatable(InvocationContext ic) {
Compensatable compensatable = ic.getMethod().getAnnotation(Compensatable.class);
if (compensatable != null) {
return compensatable;
}
Class<?> targetClass = ic.getTarget().getClass();
compensatable = targetClass.getAnnotation(Compensatable.class);
if (compensatable != null) {
return compensatable;
}
for (Annotation annotation : ic.getMethod().getDeclaringClass().getAnnotations()) {
if (beanManager.isStereotype(annotation.annotationType())) {
for (Annotation stereotyped : beanManager.getStereotypeDefinition(annotation.annotationType())) {
if (stereotyped.annotationType().equals(Compensatable.class)) {
return (Compensatable) stereotyped;
}
}
}
}
throw new RuntimeException("Expected an @Compensatable annotation at class and/or method level");
}
}