001    /**
002     * Copyright (c) 2000-2010 Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
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    /**
038     * @author         Michael Young
039     * @author         Shuyang Zhou
040     * @deprecated
041     */
042    public class PortalTransactionAnnotationParser
043            implements TransactionAnnotationParser, Serializable {
044    
045            public TransactionAttribute parseTransactionAnnotation(
046                    AnnotatedElement annotatedElement) {
047    
048                    //Transactional annotation = annotatedElement.getAnnotation(
049                    //        Transactional.class);
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    }