001 /*
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements. See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership. The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License. You may obtain a copy of the License at
009 *
010 * http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing,
013 * software distributed under the License is distributed on an
014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015 * KIND, either express or implied. See the License for the
016 * specific language governing permissions and limitations
017 * under the License.
018 */
019 package org.apache.geronimo.tomcat.interceptor;
020
021 import javax.servlet.ServletRequest;
022 import javax.servlet.ServletResponse;
023 import javax.transaction.Status;
024 import javax.transaction.SystemException;
025 import javax.transaction.UserTransaction;
026
027 import org.apache.commons.logging.Log;
028 import org.apache.commons.logging.LogFactory;
029
030 public class UserTransactionBeforeAfter implements BeforeAfter {
031 private static Log log = LogFactory.getLog(UserTransactionBeforeAfter.class);
032
033 private final UserTransaction userTransaction;
034
035 private final BeforeAfter next;
036
037 private final int index;
038
039 public UserTransactionBeforeAfter(BeforeAfter next, int index, UserTransaction userTransaction) {
040 this.next = next;
041 this.index = index;
042 this.userTransaction = userTransaction;
043 }
044
045 public void after(Object[] context, ServletRequest httpRequest, ServletResponse httpResponse, int dispatch) {
046 if (next != null) {
047 next.after(context, httpRequest, httpResponse, dispatch);
048 }
049
050 boolean active = (Boolean)context[index];
051 if ((!active && isMarkedRollback()) || (dispatch == EDGE_SERVLET && isActive())) {
052 try {
053 userTransaction.rollback();
054 } catch (SystemException e) {
055 throw new RuntimeException("Error rolling back transaction left open by user program", e);
056 }
057 }
058
059 }
060
061 public void before(Object[] context, ServletRequest request, ServletResponse response, int dispatch) {
062 context[index] = isActive();
063 next.before(context, request, response, dispatch);
064 }
065
066 private boolean isActive() {
067 try {
068 return !(userTransaction.getStatus() == Status.STATUS_NO_TRANSACTION || userTransaction.getStatus() == Status.STATUS_COMMITTED);
069 } catch (SystemException e) {
070 log.error("Could not determine transaction status", e);
071 throw new RuntimeException("Could not determine transaction status", e);
072 }
073 }
074
075 private boolean isMarkedRollback() {
076 try {
077 return userTransaction.getStatus() == Status.STATUS_MARKED_ROLLBACK;
078 } catch (SystemException e) {
079 log.error("Could not determine transaction status", e);
080 throw new RuntimeException("Could not determine transaction status", e);
081 }
082 }
083 }