EMMA Coverage Report (generated Tue Feb 12 22:23:49 ICT 2008)
[all classes][net.sourceforge.hivetranse.transaction]

COVERAGE SUMMARY FOR SOURCE FILE [TransactionInterceptorFactory.java]

nameclass, %method, %block, %line, %
TransactionInterceptorFactory.java100% (2/2)100% (12/12)92%  (275/299)86%  (56/65)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class TransactionInterceptorFactory$Interceptor100% (1/1)100% (5/5)84%  (122/146)76%  (29/38)
invoke (Object, Method, Object []): Object 100% (1/1)62%  (36/58)50%  (8/16)
mustRollback (Throwable): boolean 100% (1/1)91%  (20/22)83%  (5/6)
TransactionInterceptorFactory$Interceptor (TransactionInterceptorFactory, Log... 100% (1/1)100% (30/30)100% (8/8)
exceptionCaught (Throwable): void 100% (1/1)100% (14/14)100% (3/3)
getDemarcation (Method): TransactionDemarcation 100% (1/1)100% (22/22)100% (5/5)
     
class TransactionInterceptorFactory100% (1/1)100% (7/7)100% (153/153)100% (27/27)
TransactionInterceptorFactory (Log, TransactionService, List): void 100% (1/1)100% (57/57)100% (13/13)
access$000 (TransactionSettingsContribution, MethodMatcher, ClassMatcher): void 100% (1/1)100% (5/5)100% (1/1)
access$100 (TransactionInterceptorFactory): TransactionService 100% (1/1)100% (3/3)100% (1/1)
access$200 (TransactionInterceptorFactory): MethodMatcher 100% (1/1)100% (3/3)100% (1/1)
access$300 (TransactionInterceptorFactory): ClassMatcher 100% (1/1)100% (3/3)100% (1/1)
createInterceptor (InterceptorStack, Module, List): void 100% (1/1)100% (38/38)100% (6/6)
setMatchers (TransactionSettingsContribution, MethodMatcher, ClassMatcher): void 100% (1/1)100% (44/44)100% (7/7)

1//  Copyright 2004-2007 Jean-Francois Poilpret
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14 
15package net.sourceforge.hivetranse.transaction;
16 
17import java.lang.reflect.InvocationHandler;
18import java.lang.reflect.InvocationTargetException;
19import java.lang.reflect.Method;
20import java.lang.reflect.Proxy;
21import java.util.List;
22 
23import org.apache.commons.logging.Log;
24 
25import org.apache.hivemind.ApplicationRuntimeException;
26import org.apache.hivemind.InterceptorStack;
27import org.apache.hivemind.ServiceInterceptorFactory;
28import org.apache.hivemind.internal.Module;
29import org.apache.hivemind.methodmatch.MethodMatcher;
30import org.apache.hivemind.service.MethodSignature;
31 
32import net.sourceforge.hiveutils.util.ClassMatcher;
33 
34/**
35 * This service creates service interceptors that manage transactions.
36 * <p>
37 * Each interceptor, depending on its configuration for the given service, will
38 * manage transaction creation/commit/rollback upon situations.
39 *
40 * @author        Jean-Francois Poilpret
41 */
42public class TransactionInterceptorFactory implements ServiceInterceptorFactory
43{
44        public TransactionInterceptorFactory(        Log                                        logger, 
45                                                                                        TransactionService        manager, 
46                                                                                        List                                defaults)
47        {
48                _manager = manager;
49                // Create default method matcher and exception matchers
50                _defaultMethodMatcher = new MethodMatcher();
51                _defaultExcMatcher = new ClassMatcher();
52                if (defaults != null && defaults.size() > 1)
53                {
54                        logger.error("<init> defaults.size > 1");
55                        throw new ApplicationRuntimeException("defaults.size must be zero or one");
56                }
57                
58                if (defaults != null && defaults.size() == 1)
59                {
60                        TransactionSettingsContribution settings = 
61                                                                        (TransactionSettingsContribution) defaults.get(0);
62                        setMatchers(settings, _defaultMethodMatcher, _defaultExcMatcher);
63                }
64                // Add default demarcation (in case defaults did not specify it)
65                _defaultMethodMatcher.put("*", TransactionDemarcation.Never);
66                // Add default demarcation (in case defaults did not specify it)
67                _defaultExcMatcher.put(Throwable.class, Boolean.TRUE);
68        }
69        
70        static private void        setMatchers(TransactionSettingsContribution        parameters,
71                                                                        MethodMatcher                                        methods,
72                                                                        ClassMatcher                                        exceptions)
73        {
74                TransactionContribution[] demarcations = parameters.getTransactionContributions();
75                for (int i = 0; i < demarcations.length; i++)
76                {
77                        methods.put(demarcations[i].getPattern(),
78                                                demarcations[i].getDemarcation());
79                }
80                RollbackExceptionContribution[] exceptionContribs = 
81                                                                                        parameters.getRollbackExceptionContributions();
82                for (int i = 0; i < exceptionContribs.length; i++)
83                {
84                        exceptions.put(        exceptionContribs[i].getException(),
85                                               Boolean.valueOf(exceptionContribs[i].getRollback()));
86                }
87        }
88        
89        public void        createInterceptor(        InterceptorStack        stack,
90                                                                        Module                                invokingMod,
91                                                                        List                                parameters)
92        {
93                Log logger = stack.getServiceLog();
94                TransactionSettingsContribution settings = null;
95                if (parameters != null && parameters.size() == 1)
96                {
97                        settings = (TransactionSettingsContribution) parameters.get(0);
98                }
99        stack.push(Proxy.newProxyInstance(
100                                                        invokingMod.getClassResolver().getClassLoader(),
101                                                        new Class[] {stack.getServiceInterface()},
102                                                        new Interceptor(logger, stack.peek(), settings)));
103        }
104        
105        private class Interceptor implements InvocationHandler
106        {
107                public Interceptor(        Log                                                                logger,
108                                                        Object                                                        target, 
109                                                        TransactionSettingsContribution        settings)
110                {
111                        _logger = logger;
112                        _target = target;
113                        // Create method matcher for finding demarcation to use for a method
114                        _methodMatcher = new MethodMatcher();
115                        // Create exception matcher for finding if an exception is a rollbacker
116                        _excMatcher = new ClassMatcher();
117                        if (settings != null)
118                        {
119                                setMatchers(settings, _methodMatcher, _excMatcher);
120                        }
121                }
122                
123                //CSOFF: IllegalThrowsCheck
124                //CSOFF: IllegalCatchCheck
125                public Object        invoke(Object proxy, Method method, Object[] args)
126                        throws Throwable
127                {
128                        // First of all, find demarcation for method
129                        TransactionDemarcation demarcation = getDemarcation(method);
130 
131                        _manager.begin(demarcation);
132                        try
133                        {
134                                return method.invoke(_target, args);
135                        }
136                        catch (IllegalAccessException e)
137                        {
138                                // Can never happen (normally!)
139                                _logger.fatal("Unexpected", e);
140                                exceptionCaught(e);
141                                throw e;
142                        }
143                        catch (InvocationTargetException e)
144                        {
145                                // Check if this exception must rollback the current transaction
146                                exceptionCaught(e.getTargetException());
147                                throw e.getTargetException();
148                        }
149                        catch (Throwable e)
150                        {
151                                // Can never happen (normally!)
152                                _logger.fatal("Unexpected", e);
153                                // Check if this exception must rollback the current transaction
154                                exceptionCaught(e);
155                                throw e;
156                        }
157                        finally
158                        {
159                                _manager.end();
160                        }
161                }
162                //CSON: IllegalCatchCheck
163                //CSON: IllegalThrowsCheck
164                
165                private TransactionDemarcation        getDemarcation(Method method)
166                {
167                        MethodSignature signature = new MethodSignature(method);
168                        TransactionDemarcation demarcation;
169                        demarcation = (TransactionDemarcation) _methodMatcher.get(signature);
170                        if (demarcation != null)
171                        {
172                                return demarcation;
173                        }
174                        return (TransactionDemarcation) _defaultMethodMatcher.get(signature);
175                }
176                
177                private void        exceptionCaught(Throwable e)
178                {
179                        if (        mustRollback(e)
180                                &&        (_manager.getCurrentTransaction() != null))
181                        {
182                                _manager.setRollbackOnly();
183                        }
184                }
185                
186                private boolean                mustRollback(Throwable e)
187                {
188                        Boolean rollback;
189                        rollback = (Boolean) _excMatcher.get(e);
190                        if (rollback == null)
191                        {
192                                rollback = (Boolean) _defaultExcMatcher.get(e);
193                        }
194                        if (rollback == null)
195                        {
196                                return true;
197                        }
198                        return rollback.booleanValue();
199                }
200                
201                private final Log                                _logger;
202                private final Object                        _target;
203                private final MethodMatcher                _methodMatcher;
204                private final ClassMatcher                _excMatcher;
205        }
206        
207        private final TransactionService        _manager;
208        private final MethodMatcher                        _defaultMethodMatcher;
209        private final ClassMatcher                        _defaultExcMatcher;
210}

[all classes][net.sourceforge.hivetranse.transaction]
EMMA 2.0.5312 (C) Vladimir Roubtsov