001
014
015 package com.liferay.portal.spring.annotation;
016
017 import com.liferay.portal.kernel.annotation.TransactionDefinition;
018 import com.liferay.portal.kernel.annotation.Transactional;
019 import com.liferay.portal.util.PropsValues;
020
021 import java.io.Serializable;
022
023 import java.lang.reflect.AnnotatedElement;
024 import java.lang.reflect.Method;
025
026 import java.util.ArrayList;
027 import java.util.LinkedList;
028 import java.util.List;
029 import java.util.Queue;
030
031 import org.springframework.transaction.annotation.TransactionAnnotationParser;
032 import org.springframework.transaction.interceptor.NoRollbackRuleAttribute;
033 import org.springframework.transaction.interceptor.RollbackRuleAttribute;
034 import org.springframework.transaction.interceptor.RuleBasedTransactionAttribute;
035 import org.springframework.transaction.interceptor.TransactionAttribute;
036
037
042 public class PortalTransactionAnnotationParser
043 implements TransactionAnnotationParser, Serializable {
044
045 public TransactionAttribute parseTransactionAnnotation(
046 AnnotatedElement annotatedElement) {
047
048
049
050
051 Transactional annotation = null;
052
053 Queue<Class<?>> candidateQueue = new LinkedList<Class<?>>();
054
055 if (annotatedElement instanceof Method) {
056 Method method = (Method)annotatedElement;
057
058 candidateQueue.offer(method.getDeclaringClass());
059
060 annotation = _deepSearchMethods(method, candidateQueue);
061 }
062 else {
063 candidateQueue.offer((Class<?>)annotatedElement);
064
065 annotation = _deepSearchTypes(candidateQueue);
066 }
067
068 if (annotation == null || !annotation.enabled()) {
069 return null;
070 }
071
072 RuleBasedTransactionAttribute ruleBasedTransactionAttribute =
073 new RuleBasedTransactionAttribute();
074
075 int isolationLevel = annotation.isolation().value();
076
077 if (isolationLevel == TransactionDefinition.ISOLATION_COUNTER) {
078 ruleBasedTransactionAttribute.setIsolationLevel(
079 PropsValues.TRANSACTION_ISOLATION_COUNTER);
080 }
081 else if (isolationLevel == TransactionDefinition.ISOLATION_PORTAL) {
082 ruleBasedTransactionAttribute.setIsolationLevel(
083 PropsValues.TRANSACTION_ISOLATION_PORTAL);
084 }
085 else {
086 ruleBasedTransactionAttribute.setIsolationLevel(isolationLevel);
087 }
088
089 ruleBasedTransactionAttribute.setPropagationBehavior(
090 annotation.propagation().value());
091 ruleBasedTransactionAttribute.setReadOnly(annotation.readOnly());
092 ruleBasedTransactionAttribute.setTimeout(annotation.timeout());
093
094 List<RollbackRuleAttribute> rollBackAttributes =
095 new ArrayList<RollbackRuleAttribute>();
096
097 Class<?>[] rollbackFor = annotation.rollbackFor();
098
099 for (int i = 0; i < rollbackFor.length; i++) {
100 RollbackRuleAttribute rollbackRuleAttribute =
101 new RollbackRuleAttribute(rollbackFor[i]);
102
103 rollBackAttributes.add(rollbackRuleAttribute);
104 }
105
106 String[] rollbackForClassName = annotation.rollbackForClassName();
107
108 for (int i = 0; i < rollbackForClassName.length; i++) {
109 RollbackRuleAttribute rollbackRuleAttribute =
110 new RollbackRuleAttribute(rollbackForClassName[i]);
111
112 rollBackAttributes.add(rollbackRuleAttribute);
113 }
114
115 Class<?>[] noRollbackFor = annotation.noRollbackFor();
116
117 for (int i = 0; i < noRollbackFor.length; ++i) {
118 NoRollbackRuleAttribute noRollbackRuleAttribute =
119 new NoRollbackRuleAttribute(noRollbackFor[i]);
120
121 rollBackAttributes.add(noRollbackRuleAttribute);
122 }
123
124 String[] noRollbackForClassName = annotation.noRollbackForClassName();
125
126 for (int i = 0; i < noRollbackForClassName.length; ++i) {
127 NoRollbackRuleAttribute noRollbackRuleAttribute =
128 new NoRollbackRuleAttribute(noRollbackForClassName[i]);
129
130 rollBackAttributes.add(noRollbackRuleAttribute);
131 }
132
133 ruleBasedTransactionAttribute.getRollbackRules().addAll(
134 rollBackAttributes);
135
136 return ruleBasedTransactionAttribute;
137 }
138
139 private Transactional _deepSearchMethods(
140 Method method, Queue<Class<?>> candidateQueue) {
141
142 Transactional annotation = method.getAnnotation(Transactional.class);
143
144 if (annotation != null) {
145 return annotation;
146 }
147
148 if (candidateQueue.isEmpty()) {
149 return null;
150 }
151
152 Class<?> clazz = candidateQueue.poll();
153
154 if (method.getDeclaringClass() != clazz) {
155 try {
156 Method specificMethod = clazz.getDeclaredMethod(
157 method.getName(), method.getParameterTypes());
158
159 annotation = specificMethod.getAnnotation(Transactional.class);
160
161 if (annotation != null) {
162 return annotation;
163 }
164 }
165 catch (Exception e) {
166 }
167 }
168
169 annotation = clazz.getAnnotation(Transactional.class);
170
171 if (annotation == null) {
172 _queueSuperTypes(clazz, candidateQueue);
173
174 return _deepSearchMethods(method, candidateQueue);
175 }
176 else {
177 return annotation;
178 }
179 }
180
181 private Transactional _deepSearchTypes(Queue<Class<?>> candidateQueue) {
182 if (candidateQueue.isEmpty()) {
183 return null;
184 }
185
186 Class<?> clazz = candidateQueue.poll();
187
188 Transactional annotation = clazz.getAnnotation(Transactional.class);
189
190 if (annotation == null) {
191 _queueSuperTypes(clazz, candidateQueue);
192
193 return _deepSearchTypes(candidateQueue);
194 }
195 else {
196 return annotation;
197 }
198 }
199
200 private void _queueSuperTypes(
201 Class<?> clazz, Queue<Class<?>> candidateQueue) {
202
203 Class<?> supperClass = clazz.getSuperclass();
204
205 if ((supperClass != null) && (supperClass != Object.class)) {
206 candidateQueue.offer(supperClass);
207 }
208
209 Class<?>[] interfaces = clazz.getInterfaces();
210
211 for (Class<?> inter : interfaces) {
212 candidateQueue.offer(inter);
213 }
214 }
215
216 }