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 }