1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one 3 * or more contributor license agreements. See the NOTICE file 4 * distributed with this work for additional information 5 * regarding copyright ownership. The ASF licenses this file 6 * to you under the Apache License, Version 2.0 (the 7 * "License"); you may not use this file except in compliance 8 * with the License. You may obtain a copy of the License at 9 * 10 * http://www.apache.org/licenses/LICENSE-2.0 11 * 12 * Unless required by applicable law or agreed to in writing, 13 * software distributed under the License is distributed on an 14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 * KIND, either express or implied. See the License for the 16 * specific language governing permissions and limitations 17 * under the License. 18 */ 19 package org.apache.geronimo.tomcat.interceptor; 20 21 import javax.servlet.ServletRequest; 22 import javax.servlet.ServletResponse; 23 import javax.transaction.Status; 24 import javax.transaction.SystemException; 25 import javax.transaction.UserTransaction; 26 27 import org.slf4j.Logger; 28 import org.slf4j.LoggerFactory; 29 30 public class UserTransactionBeforeAfter implements BeforeAfter { 31 private static final Logger log = LoggerFactory.getLogger(UserTransactionBeforeAfter.class); 32 33 private final UserTransaction userTransaction; 34 35 private final BeforeAfter next; 36 37 private final int index; 38 39 public UserTransactionBeforeAfter(BeforeAfter next, int index, UserTransaction userTransaction) { 40 this.next = next; 41 this.index = index; 42 this.userTransaction = userTransaction; 43 } 44 45 public void after(Object[] context, ServletRequest httpRequest, ServletResponse httpResponse, int dispatch) { 46 if (next != null) { 47 next.after(context, httpRequest, httpResponse, dispatch); 48 } 49 50 boolean active = (Boolean)context[index]; 51 if ((!active && isMarkedRollback()) || (dispatch == EDGE_SERVLET && isActive())) { 52 try { 53 userTransaction.rollback(); 54 } catch (SystemException e) { 55 throw new RuntimeException("Error rolling back transaction left open by user program", e); 56 } 57 } 58 59 } 60 61 public void before(Object[] context, ServletRequest request, ServletResponse response, int dispatch) { 62 context[index] = isActive(); 63 next.before(context, request, response, dispatch); 64 } 65 66 private boolean isActive() { 67 try { 68 return !(userTransaction.getStatus() == Status.STATUS_NO_TRANSACTION || userTransaction.getStatus() == Status.STATUS_COMMITTED); 69 } catch (SystemException e) { 70 log.error("Could not determine transaction status", e); 71 throw new RuntimeException("Could not determine transaction status", e); 72 } 73 } 74 75 private boolean isMarkedRollback() { 76 try { 77 return userTransaction.getStatus() == Status.STATUS_MARKED_ROLLBACK; 78 } catch (SystemException e) { 79 log.error("Could not determine transaction status", e); 80 throw new RuntimeException("Could not determine transaction status", e); 81 } 82 } 83 }