001: package org.apache.ojb.broker.transaction.tm;
002:
003: /* Copyright 2004-2005 The Apache Software Foundation
004: *
005: * Licensed under the Apache License, Version 2.0 (the "License");
006: * you may not use this file except in compliance with the License.
007: * You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017:
018: import javax.transaction.TransactionManager;
019:
020: import org.apache.commons.lang.SystemUtils;
021: import org.apache.ojb.broker.core.NamingLocator;
022: import org.apache.ojb.broker.util.ClassHelper;
023: import org.apache.ojb.broker.util.logging.Logger;
024: import org.apache.ojb.broker.util.logging.LoggerFactory;
025:
026: /**
027: * Abstract base class implementation of the {@link TransactionManagerFactory} interface, all
028: * derived classes have to implement method {@link #getLookupInfo()}.
029: *
030: * @author <a href="mailto:armin@codeAuLait.de">Armin Waibel</a>
031: * @version $Id: AbstractTransactionManagerFactory.java,v 1.2.2.2 2005/12/21 22:27:48 tomdz Exp $
032: */
033:
034: public abstract class AbstractTransactionManagerFactory implements
035: TransactionManagerFactory {
036: private static Logger log = LoggerFactory
037: .getLogger(AbstractTransactionManagerFactory.class);
038:
039: /**
040: * Returns "getTransactionManager";
041: */
042: public static String TM_DEFAULT_METHOD_NAME = "getTransactionManager";
043:
044: private static TransactionManager tm = null;
045:
046: /**
047: * Returns an array of possible JNDI lookup / class names for
048: * the {@link javax.transaction.TransactionManager} instance. An array was used
049: * because for different application server versions the
050: * JNDI/class name may change.
051: * <p/>
052: * Expect an [n][3] string array. Following arguments are available:
053: * <ul>
054: * <li>info[i][0] = short description of used TM, e.g. appServer name</li>
055: * <li>info[i][2] = JNDI name to lookup TM or the method name to retrieve TM instance</li>
056: * <li>info[i][3] = if 'null' an JNDI lookup was made with JNDI name set above, if not null
057: * the class name of the TM factory was assumed and the method name set above will be invoked</li>
058: * </ul>
059: * Example:
060: * <p>
061: * {{"JBoss", "java:/TransactionManager", null}};<br/>
062: * In JBoss we lookup the TM via JNDI, so we don't need a TM factory class.
063: * </p>
064: *
065: * <p>
066: * {{"Websphere 4", TM_DEFAULT_METHOD_NAME, "com.ibm.ejs.jts.jta.JTSXA"},<br/>
067: * {"Websphere 5", TM_DEFAULT_METHOD_NAME, "com.ibm.ejs.jts.jta.TransactionManagerFactory"},<br/>
068: * {"Websphere >5", TM_DEFAULT_METHOD_NAME, "com.ibm.ws.Transaction.TransactionManagerFactory"}};<br/>
069: * In Websphere we have to use a TM factory class and obtain the TM via a <em>getTransactionManager()</em>
070: * method call. The TM factory class is varied in different versions.
071: * </p>
072: */
073: public abstract String[][] getLookupInfo();
074:
075: /**
076: * @see org.apache.ojb.broker.transaction.tm.TransactionManagerFactory
077: */
078: public synchronized TransactionManager getTransactionManager()
079: throws TransactionManagerFactoryException {
080: if (tm == null) {
081: StringBuffer msg = new StringBuffer();
082: String[][] lookupInfo = getLookupInfo();
083: String EOL = SystemUtils.LINE_SEPARATOR;
084:
085: for (int i = 0; i < lookupInfo.length; i++) {
086: String description = lookupInfo[i][0];
087: String methodName = lookupInfo[i][1];
088: String className = lookupInfo[i][2];
089: try {
090: if (className == null) {
091: tm = jndiLookup(description, methodName);
092: } else {
093: tm = instantiateClass(description, className,
094: methodName);
095: }
096: msg.append("Successfully requested TM for "
097: + description + EOL);
098: } catch (Exception e) {
099: if (className == null)
100: msg.append("Error on TM request for "
101: + description + ", using jndi-lookup '"
102: + methodName + "'" + EOL
103: + e.getMessage() + EOL);
104: else
105: msg.append("Error on TM request for "
106: + description + ", using method '"
107: + methodName + "' for class '"
108: + className + "'" + EOL
109: + e.getMessage() + EOL);
110: }
111: if (tm != null)
112: break;
113: }
114: // if we don't get an TM instance throw exception
115: if (tm == null) {
116: throw new TransactionManagerFactoryException(
117: "Can't lookup transaction manager:" + EOL + msg);
118: }
119: }
120: return tm;
121: }
122:
123: protected TransactionManager jndiLookup(String description,
124: String methodName) {
125: log.info(description + ", lookup TransactionManager: '"
126: + methodName + "'");
127: return (TransactionManager) NamingLocator.lookup(methodName);
128: }
129:
130: protected TransactionManager instantiateClass(String description,
131: String className, String methodName) throws Exception {
132: log.info(description + ", invoke method '" + methodName
133: + "()' on class " + className);
134: Class tmClass = ClassHelper.getClass(className);
135: return (TransactionManager) tmClass.getMethod(methodName, null)
136: .invoke(null, null);
137: }
138: }
|