1   /**
2    * Copyright (c) 2000-2010 Liferay, Inc. All rights reserved.
3    *
4    * This library is free software; you can redistribute it and/or modify it under
5    * the terms of the GNU Lesser General Public License as published by the Free
6    * Software Foundation; either version 2.1 of the License, or (at your option)
7    * any later version.
8    *
9    * This library is distributed in the hope that it will be useful, but WITHOUT
10   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11   * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
12   * details.
13   */
14  
15  package com.liferay.util.spring.transaction;
16  
17  import com.liferay.portal.kernel.bean.PortalBeanLocatorUtil;
18  import com.liferay.portal.kernel.log.Log;
19  import com.liferay.portal.kernel.log.LogFactoryUtil;
20  import com.liferay.portal.kernel.util.PortalClassLoaderUtil;
21  import com.liferay.portal.kernel.util.SimplePojoClp;
22  
23  import java.lang.reflect.Method;
24  
25  import java.util.HashMap;
26  import java.util.Map;
27  
28  import javax.annotation.PostConstruct;
29  
30  import org.springframework.transaction.PlatformTransactionManager;
31  import org.springframework.transaction.TransactionDefinition;
32  import org.springframework.transaction.TransactionException;
33  import org.springframework.transaction.TransactionStatus;
34  import org.springframework.transaction.TransactionSystemException;
35  import org.springframework.transaction.support.DefaultTransactionDefinition;
36  
37  /**
38   * <a href="TransactionManagerClp.java.html"><b><i>View Source</i></b></a>
39   *
40   * <p>
41   * A transaction manager class loader proxy delegating the method invocations to
42   * the transaction manager in the portal implementation. The transaction manager
43   * within the portal must be specified as a Spring bean having id
44   * <code>"liferayTransactionManager"</code>.
45   * </p>
46   *
47   * @author Micha Kiener
48   * @author Brian Wing Shun Chan
49   */
50  public class TransactionManagerClp implements PlatformTransactionManager {
51  
52      public void commit(TransactionStatus transactionStatus)
53          throws TransactionException {
54  
55          try {
56              Method method = _transactionManagerMethods.get("commit");
57  
58              method.invoke(
59                  _transactionManager,
60                  unwrapTransactionStatus(transactionStatus));
61          }
62          catch (Exception e) {
63              _log.error(e, e);
64  
65              throw new TransactionSystemException(e.getMessage());
66          }
67      }
68  
69      public TransactionStatus getTransaction(
70              TransactionDefinition transactionDefinition)
71          throws TransactionException {
72  
73          Object transactionStatus = null;
74  
75          try {
76              Method method = _transactionManagerMethods.get("getTransaction");
77  
78              transactionStatus = method.invoke(
79                  _transactionManager,
80                  createRemoteTransactionDefinition(transactionDefinition));
81          }
82          catch (Exception e) {
83              _log.error(e, e);
84  
85              throw new TransactionSystemException(e.getMessage());
86          }
87  
88          return new TransactionStatusClp(transactionStatus);
89      }
90  
91      @PostConstruct
92      public void init() throws ClassNotFoundException {
93          _transactionManager = PortalBeanLocatorUtil.locate(
94              "liferayTransactionManager");
95  
96          _transactionDefinitionClp = new SimplePojoClp<TransactionDefinition>(
97              DefaultTransactionDefinition.class,
98              PortalClassLoaderUtil.getClassLoader());
99  
100         initTransactionManagerMethods();
101     }
102 
103     public void rollback(TransactionStatus transactionStatus)
104         throws TransactionException {
105 
106         try {
107             Method method = _transactionManagerMethods.get("rollback");
108 
109             method.invoke(
110                 _transactionManager,
111                 unwrapTransactionStatus(transactionStatus));
112         }
113         catch (Exception e) {
114             _log.error(e, e);
115 
116             throw new TransactionSystemException(e.getMessage());
117         }
118     }
119 
120     protected Object createRemoteTransactionDefinition(
121             TransactionDefinition transactionDefinition)
122         throws IllegalAccessException, InstantiationException {
123 
124         return _transactionDefinitionClp.createRemoteObject(
125             transactionDefinition);
126     }
127 
128     protected void initTransactionManagerMethods() {
129         _transactionManagerMethods = new HashMap<String, Method>();
130 
131         Method[] methods = _transactionManager.getClass().getMethods();
132 
133         for (Method method : methods) {
134             _transactionManagerMethods.put(method.getName(), method);
135         }
136     }
137 
138     protected Object unwrapTransactionStatus(
139         TransactionStatus localTransactionStatus) {
140 
141         TransactionStatusClp transactionStatusClp =
142             (TransactionStatusClp)localTransactionStatus;
143 
144         return transactionStatusClp.getRemoteTransactionStatus();
145     }
146 
147     private static Log _log = LogFactoryUtil.getLog(
148         TransactionManagerClp.class);
149 
150     private SimplePojoClp<TransactionDefinition> _transactionDefinitionClp;
151     private Object _transactionManager;
152     private Map<String, Method> _transactionManagerMethods;
153 
154 }