1 package org.apache.ojb.broker.transaction.tm;
2
3 /* Copyright 2004-2005 The Apache Software Foundation
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18 import javax.transaction.TransactionManager;
19
20 import org.apache.commons.lang.SystemUtils;
21 import org.apache.ojb.broker.core.NamingLocator;
22 import org.apache.ojb.broker.util.ClassHelper;
23 import org.apache.ojb.broker.util.logging.Logger;
24 import org.apache.ojb.broker.util.logging.LoggerFactory;
25
26 /**
27 * Abstract base class implementation of the {@link TransactionManagerFactory} interface, all
28 * derived classes have to implement method {@link #getLookupInfo()}.
29 *
30 * @author <a href="mailto:armin@codeAuLait.de">Armin Waibel</a>
31 * @version $Id: AbstractTransactionManagerFactory.java,v 1.1 2007-08-24 22:17:41 ewestfal Exp $
32 */
33
34 public abstract class AbstractTransactionManagerFactory implements TransactionManagerFactory
35 {
36 private static Logger log = LoggerFactory.getLogger(AbstractTransactionManagerFactory.class);
37
38 /**
39 * Returns "getTransactionManager";
40 */
41 public static String TM_DEFAULT_METHOD_NAME = "getTransactionManager";
42
43
44 private static TransactionManager tm = null;
45
46 /**
47 * Returns an array of possible JNDI lookup / class names for
48 * the {@link javax.transaction.TransactionManager} instance. An array was used
49 * because for different application server versions the
50 * JNDI/class name may change.
51 * <p/>
52 * Expect an [n][3] string array. Following arguments are available:
53 * <ul>
54 * <li>info[i][0] = short description of used TM, e.g. appServer name</li>
55 * <li>info[i][2] = JNDI name to lookup TM or the method name to retrieve TM instance</li>
56 * <li>info[i][3] = if 'null' an JNDI lookup was made with JNDI name set above, if not null
57 * the class name of the TM factory was assumed and the method name set above will be invoked</li>
58 * </ul>
59 * Example:
60 * <p>
61 * {{"JBoss", "java:/TransactionManager", null}};<br/>
62 * In JBoss we lookup the TM via JNDI, so we don't need a TM factory class.
63 * </p>
64 *
65 * <p>
66 * {{"Websphere 4", TM_DEFAULT_METHOD_NAME, "com.ibm.ejs.jts.jta.JTSXA"},<br/>
67 * {"Websphere 5", TM_DEFAULT_METHOD_NAME, "com.ibm.ejs.jts.jta.TransactionManagerFactory"},<br/>
68 * {"Websphere >5", TM_DEFAULT_METHOD_NAME, "com.ibm.ws.Transaction.TransactionManagerFactory"}};<br/>
69 * In Websphere we have to use a TM factory class and obtain the TM via a <em>getTransactionManager()</em>
70 * method call. The TM factory class is varied in different versions.
71 * </p>
72 */
73 public abstract String[][] getLookupInfo();
74
75 /**
76 * @see org.apache.ojb.broker.transaction.tm.TransactionManagerFactory
77 */
78 public synchronized TransactionManager getTransactionManager() throws TransactionManagerFactoryException
79 {
80 if (tm == null)
81 {
82 StringBuffer msg = new StringBuffer();
83 String[][] lookupInfo = getLookupInfo();
84 String EOL = SystemUtils.LINE_SEPARATOR;
85
86 for (int i = 0; i < lookupInfo.length; i++)
87 {
88 String description = lookupInfo[i][0];
89 String methodName = lookupInfo[i][1];
90 String className = lookupInfo[i][2];
91 try
92 {
93 if (className == null)
94 {
95 tm = jndiLookup(description, methodName);
96 }
97 else
98 {
99 tm = instantiateClass(description, className, methodName);
100 }
101 msg.append("Successfully requested TM for " + description + EOL);
102 }
103 catch (Exception e)
104 {
105 if (className == null)
106 msg.append("Error on TM request for " + description +
107 ", using jndi-lookup '" + methodName + "'" + EOL + e.getMessage() + EOL);
108 else
109 msg.append("Error on TM request for " + description + ", using method '" +
110 methodName + "' for class '" + className + "'" + EOL + e.getMessage() + EOL);
111 }
112 if (tm != null) break;
113 }
114 // if we don't get an TM instance throw exception
115 if (tm == null)
116 {
117 throw new TransactionManagerFactoryException("Can't lookup transaction manager:" + EOL + msg);
118 }
119 }
120 return tm;
121 }
122
123 protected TransactionManager jndiLookup(String description, String methodName)
124 {
125 log.info(description + ", lookup TransactionManager: '" + methodName + "'");
126 return (TransactionManager) NamingLocator.lookup(methodName);
127 }
128
129 protected TransactionManager instantiateClass(String description, String className, String methodName) throws Exception
130 {
131 log.info(description + ", invoke method '"
132 + methodName + "()' on class " + className);
133 Class tmClass = ClassHelper.getClass(className);
134 return (TransactionManager) tmClass.getMethod(methodName, null).invoke(null, null);
135 }
136 }