1
14
15 package com.liferay.portal.spring.annotation;
16
17 import com.liferay.portal.kernel.annotation.TransactionDefinition;
18 import com.liferay.portal.kernel.annotation.Transactional;
19 import com.liferay.portal.util.PropsValues;
20
21 import java.io.Serializable;
22
23 import java.lang.reflect.AnnotatedElement;
24 import java.lang.reflect.Method;
25
26 import java.util.ArrayList;
27 import java.util.LinkedList;
28 import java.util.List;
29 import java.util.Queue;
30
31 import org.springframework.transaction.annotation.TransactionAnnotationParser;
32 import org.springframework.transaction.interceptor.NoRollbackRuleAttribute;
33 import org.springframework.transaction.interceptor.RollbackRuleAttribute;
34 import org.springframework.transaction.interceptor.RuleBasedTransactionAttribute;
35 import org.springframework.transaction.interceptor.TransactionAttribute;
36
37
44 public class PortalTransactionAnnotationParser
45 implements TransactionAnnotationParser, Serializable {
46
47 public TransactionAttribute parseTransactionAnnotation(
48 AnnotatedElement annotatedElement) {
49
50
53 Transactional annotation = null;
54
55 Queue<Class<?>> candidateQueue = new LinkedList<Class<?>>();
56
57 if (annotatedElement instanceof Method) {
58 Method method = (Method)annotatedElement;
59
60 candidateQueue.offer(method.getDeclaringClass());
61
62 annotation = _deepSearchMethods(method, candidateQueue);
63 }
64 else {
65 candidateQueue.offer((Class<?>)annotatedElement);
66
67 annotation = _deepSearchTypes(candidateQueue);
68 }
69
70 if (annotation == null) {
71 return null;
72 }
73
74 RuleBasedTransactionAttribute ruleBasedTransactionAttribute =
75 new RuleBasedTransactionAttribute();
76
77 int isolationLevel = annotation.isolation().value();
78
79 if (isolationLevel == TransactionDefinition.ISOLATION_PORTAL) {
80 ruleBasedTransactionAttribute.setIsolationLevel(
81 PropsValues.TRANSACTION_ISOLATION_PORTAL);
82 }
83 else {
84 ruleBasedTransactionAttribute.setIsolationLevel(isolationLevel);
85 }
86
87 ruleBasedTransactionAttribute.setPropagationBehavior(
88 annotation.propagation().value());
89 ruleBasedTransactionAttribute.setReadOnly(annotation.readOnly());
90 ruleBasedTransactionAttribute.setTimeout(annotation.timeout());
91
92 List<RollbackRuleAttribute> rollBackAttributes =
93 new ArrayList<RollbackRuleAttribute>();
94
95 Class<?>[] rollbackFor = annotation.rollbackFor();
96
97 for (int i = 0; i < rollbackFor.length; i++) {
98 RollbackRuleAttribute rollbackRuleAttribute =
99 new RollbackRuleAttribute(rollbackFor[i]);
100
101 rollBackAttributes.add(rollbackRuleAttribute);
102 }
103
104 String[] rollbackForClassName = annotation.rollbackForClassName();
105
106 for (int i = 0; i < rollbackForClassName.length; i++) {
107 RollbackRuleAttribute rollbackRuleAttribute =
108 new RollbackRuleAttribute(rollbackForClassName[i]);
109
110 rollBackAttributes.add(rollbackRuleAttribute);
111 }
112
113 Class<?>[] noRollbackFor = annotation.noRollbackFor();
114
115 for (int i = 0; i < noRollbackFor.length; ++i) {
116 NoRollbackRuleAttribute noRollbackRuleAttribute =
117 new NoRollbackRuleAttribute(noRollbackFor[i]);
118
119 rollBackAttributes.add(noRollbackRuleAttribute);
120 }
121
122 String[] noRollbackForClassName = annotation.noRollbackForClassName();
123
124 for (int i = 0; i < noRollbackForClassName.length; ++i) {
125 NoRollbackRuleAttribute noRollbackRuleAttribute =
126 new NoRollbackRuleAttribute(noRollbackForClassName[i]);
127
128 rollBackAttributes.add(noRollbackRuleAttribute);
129 }
130
131 ruleBasedTransactionAttribute.getRollbackRules().addAll(
132 rollBackAttributes);
133
134 return ruleBasedTransactionAttribute;
135 }
136
137 private Transactional _deepSearchMethods(
138 Method method, Queue<Class<?>> candidateQueue) {
139
140 Transactional annotation = method.getAnnotation(Transactional.class);
141
142 if (annotation != null) {
143 return annotation;
144 }
145
146 if (candidateQueue.isEmpty()) {
147 return null;
148 }
149
150 Class<?> clazz = candidateQueue.poll();
151
152 if (method.getDeclaringClass() != clazz) {
153 try {
154 Method specificMethod = clazz.getDeclaredMethod(
155 method.getName(), method.getParameterTypes());
156
157 annotation = specificMethod.getAnnotation(Transactional.class);
158
159 if (annotation != null) {
160 return annotation;
161 }
162 }
163 catch (Exception e) {
164 }
165 }
166
167 annotation = clazz.getAnnotation(Transactional.class);
168
169 if (annotation == null) {
170 _queueSuperTypes(clazz, candidateQueue);
171
172 return _deepSearchMethods(method, candidateQueue);
173 }
174 else {
175 return annotation;
176 }
177 }
178
179 private Transactional _deepSearchTypes(Queue<Class<?>> candidateQueue) {
180 if (candidateQueue.isEmpty()) {
181 return null;
182 }
183
184 Class<?> clazz = candidateQueue.poll();
185
186 Transactional annotation = clazz.getAnnotation(Transactional.class);
187
188 if (annotation == null) {
189 _queueSuperTypes(clazz, candidateQueue);
190
191 return _deepSearchTypes(candidateQueue);
192 }
193 else {
194 return annotation;
195 }
196 }
197
198 private void _queueSuperTypes(
199 Class<?> clazz, Queue<Class<?>> candidateQueue) {
200
201 Class<?> supperClass = clazz.getSuperclass();
202
203 if ((supperClass != null) && (supperClass != Object.class)) {
204 candidateQueue.offer(supperClass);
205 }
206
207 Class<?>[] interfaces = clazz.getInterfaces();
208
209 for (Class<?> inter : interfaces) {
210 candidateQueue.offer(inter);
211 }
212 }
213
214 }