1   /**
2    * Copyright (c) 2000-2010 Liferay, Inc. All rights reserved.
3    *
4    * The contents of this file are subject to the terms of the Liferay Enterprise
5    * Subscription License ("License"). You may not use this file except in
6    * compliance with the License. You can obtain a copy of the License by
7    * contacting Liferay, Inc. See the License for the specific language governing
8    * permissions and limitations under the License, including but not limited to
9    * distribution rights of the Software.
10   *
11   *
12   *
13   */
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  /**
38   * <a href="PortalTransactionAnnotationParser.java.html"><b><i>View Source</i>
39   * </b></a>
40   *
41   * @author     Michael Young
42   * @author     Shuyang Zhou
43   * @deprecated
44   */
45  public class PortalTransactionAnnotationParser
46      implements TransactionAnnotationParser, Serializable {
47  
48      public TransactionAttribute parseTransactionAnnotation(
49          AnnotatedElement annotatedElement) {
50  
51          //Transactional annotation = annotatedElement.getAnnotation(
52          //  Transactional.class);
53  
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 }