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