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) {
069 return null;
070 }
071
072 RuleBasedTransactionAttribute ruleBasedTransactionAttribute =
073 new RuleBasedTransactionAttribute();
074
075 int isolationLevel = annotation.isolation().value();
076
077 if (isolationLevel == TransactionDefinition.ISOLATION_PORTAL) {
078 ruleBasedTransactionAttribute.setIsolationLevel(
079 PropsValues.TRANSACTION_ISOLATION_PORTAL);
080 }
081 else {
082 ruleBasedTransactionAttribute.setIsolationLevel(isolationLevel);
083 }
084
085 ruleBasedTransactionAttribute.setPropagationBehavior(
086 annotation.propagation().value());
087 ruleBasedTransactionAttribute.setReadOnly(annotation.readOnly());
088 ruleBasedTransactionAttribute.setTimeout(annotation.timeout());
089
090 List<RollbackRuleAttribute> rollBackAttributes =
091 new ArrayList<RollbackRuleAttribute>();
092
093 Class<?>[] rollbackFor = annotation.rollbackFor();
094
095 for (int i = 0; i < rollbackFor.length; i++) {
096 RollbackRuleAttribute rollbackRuleAttribute =
097 new RollbackRuleAttribute(rollbackFor[i]);
098
099 rollBackAttributes.add(rollbackRuleAttribute);
100 }
101
102 String[] rollbackForClassName = annotation.rollbackForClassName();
103
104 for (int i = 0; i < rollbackForClassName.length; i++) {
105 RollbackRuleAttribute rollbackRuleAttribute =
106 new RollbackRuleAttribute(rollbackForClassName[i]);
107
108 rollBackAttributes.add(rollbackRuleAttribute);
109 }
110
111 Class<?>[] noRollbackFor = annotation.noRollbackFor();
112
113 for (int i = 0; i < noRollbackFor.length; ++i) {
114 NoRollbackRuleAttribute noRollbackRuleAttribute =
115 new NoRollbackRuleAttribute(noRollbackFor[i]);
116
117 rollBackAttributes.add(noRollbackRuleAttribute);
118 }
119
120 String[] noRollbackForClassName = annotation.noRollbackForClassName();
121
122 for (int i = 0; i < noRollbackForClassName.length; ++i) {
123 NoRollbackRuleAttribute noRollbackRuleAttribute =
124 new NoRollbackRuleAttribute(noRollbackForClassName[i]);
125
126 rollBackAttributes.add(noRollbackRuleAttribute);
127 }
128
129 ruleBasedTransactionAttribute.getRollbackRules().addAll(
130 rollBackAttributes);
131
132 return ruleBasedTransactionAttribute;
133 }
134
135 private Transactional _deepSearchMethods(
136 Method method, Queue<Class<?>> candidateQueue) {
137
138 Transactional annotation = method.getAnnotation(Transactional.class);
139
140 if (annotation != null) {
141 return annotation;
142 }
143
144 if (candidateQueue.isEmpty()) {
145 return null;
146 }
147
148 Class<?> clazz = candidateQueue.poll();
149
150 if (method.getDeclaringClass() != clazz) {
151 try {
152 Method specificMethod = clazz.getDeclaredMethod(
153 method.getName(), method.getParameterTypes());
154
155 annotation = specificMethod.getAnnotation(Transactional.class);
156
157 if (annotation != null) {
158 return annotation;
159 }
160 }
161 catch (Exception e) {
162 }
163 }
164
165 annotation = clazz.getAnnotation(Transactional.class);
166
167 if (annotation == null) {
168 _queueSuperTypes(clazz, candidateQueue);
169
170 return _deepSearchMethods(method, candidateQueue);
171 }
172 else {
173 return annotation;
174 }
175 }
176
177 private Transactional _deepSearchTypes(Queue<Class<?>> candidateQueue) {
178 if (candidateQueue.isEmpty()) {
179 return null;
180 }
181
182 Class<?> clazz = candidateQueue.poll();
183
184 Transactional annotation = clazz.getAnnotation(Transactional.class);
185
186 if (annotation == null) {
187 _queueSuperTypes(clazz, candidateQueue);
188
189 return _deepSearchTypes(candidateQueue);
190 }
191 else {
192 return annotation;
193 }
194 }
195
196 private void _queueSuperTypes(
197 Class<?> clazz, Queue<Class<?>> candidateQueue) {
198
199 Class<?> supperClass = clazz.getSuperclass();
200
201 if ((supperClass != null) && (supperClass != Object.class)) {
202 candidateQueue.offer(supperClass);
203 }
204
205 Class<?>[] interfaces = clazz.getInterfaces();
206
207 for (Class<?> inter : interfaces) {
208 candidateQueue.offer(inter);
209 }
210 }
211
212 }