001 /* 002 * Copyright 2002-2005 the original author or authors. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017 package org.jencks.interceptor; 018 019 import org.apache.commons.logging.Log; 020 import org.apache.commons.logging.LogFactory; 021 import org.apache.geronimo.transaction.DefaultInstanceContext; 022 import org.apache.geronimo.transaction.InstanceContext; 023 import org.apache.geronimo.transaction.TrackedConnectionAssociator; 024 025 import javax.resource.ResourceException; 026 import javax.servlet.Filter; 027 import javax.servlet.FilterChain; 028 import javax.servlet.FilterConfig; 029 import javax.servlet.ServletException; 030 import javax.servlet.ServletRequest; 031 import javax.servlet.ServletResponse; 032 import java.io.IOException; 033 import java.util.HashSet; 034 import java.util.Set; 035 036 /** 037 * This servlet filter is used to enter in a transactional context 038 * automtically at every servlet call and exit of it when the response 039 * is sent back to the client. 040 * <p/> 041 * This class must be used with a mechanism (for example, Acegi) to 042 * use injection on filters. 043 * <p/> 044 * The following is an example of use: 045 * <p/> 046 * <web-app id="WebApp"> 047 * ... 048 * <filter> 049 * <filter-name>Geronimo Transaction Context Filter</filter-name> 050 * <filter-class> 051 * org.springframework.web.filter.DelegatingFilterProxy</filter-class> 052 * <init-param> 053 * <param-name>targetBeanName</param-name> 054 * <param-value> 055 * org.springframework.jca.interceptor.TransactionContexFilter 056 * </param-value> 057 * </init-param> 058 * </filter> 059 * <p/> 060 * <filter-mapping> 061 * <filter-name>Geronimo Transaction Context Filter</filter-name> 062 * <url-pattern>/*</url-pattern> 063 * </filter-mapping> 064 * ... 065 * </web-app> 066 * 067 * @author Thierry Templier 068 * @see TrackedConnectionAssociator#enter(InstanceContext) 069 * @see TrackedConnectionAssociator#exit(InstanceContext) 070 * @see InstanceContext 071 * @see DefaultInstanceContext 072 */ 073 public class TransactionContexFilter implements Filter { 074 075 private TrackedConnectionAssociator associator; 076 077 protected transient Log logger = LogFactory.getLog(getClass()); 078 079 public void init(FilterConfig config) throws ServletException { 080 } 081 082 /** 083 * This is the central method of the filter which allows the 084 * request to enter in a transactionnal context and exit when 085 * the request is sent back to the client. 086 * 087 * @see #enterContext(Set, Set) 088 * @see #exitContext(InstanceContext) 089 */ 090 public void doFilter(ServletRequest request, ServletResponse response, 091 FilterChain chain) throws IOException, ServletException { 092 // Enter in the transactionnal context 093 Set unshareableResources = new HashSet(); 094 Set applicationManagedSecurityResources = new HashSet(); 095 InstanceContext oldContext = 096 enterContext(unshareableResources, applicationManagedSecurityResources); 097 098 // Proceed with chain 099 chain.doFilter(request, response); 100 101 // Exit the transactionnal context 102 exitContext(oldContext); 103 } 104 105 /** 106 * This method enters in a new context and returns it 107 * in order to exit of it when the request is sent back to 108 * the client. 109 */ 110 private InstanceContext enterContext(Set unshareableResources, 111 Set applicationManagedSecurityResources) { 112 try { 113 InstanceContext oldContext = 114 associator.enter(new DefaultInstanceContext( 115 unshareableResources, applicationManagedSecurityResources)); 116 if (logger.isDebugEnabled()) { 117 logger.info("Geronimo transaction context set."); 118 } 119 return oldContext; 120 } 121 catch (ResourceException ex) { 122 } 123 return null; 124 } 125 126 /** 127 * This method exits of the specified context. This context is 128 * created when entering a new one. 129 * 130 * @see #enterContext(Set, Set) 131 */ 132 private void exitContext(InstanceContext oldContext) { 133 try { 134 associator.exit(oldContext); 135 if (logger.isDebugEnabled()) { 136 logger.info("Geronimo transaction context unset."); 137 } 138 } 139 catch (ResourceException ex) { 140 } 141 } 142 143 public void destroy() { 144 } 145 146 /** 147 * Set the TrackedConnectionAssociator instance to allow the bean 148 * to enter and exit a transactional context. 149 */ 150 public void setAssociator(TrackedConnectionAssociator associator) { 151 this.associator = associator; 152 } 153 154 }