001: /*
002: * Licensed under the X license (see http://www.x.org/terms.htm)
003: */
004: package org.ofbiz.minerva.pool.jdbc.xa.wrapper;
005:
006: import java.io.PrintWriter;
007: import java.sql.Connection;
008: import java.sql.Driver;
009: import java.sql.DriverManager;
010: import java.sql.SQLException;
011: import java.util.Properties;
012:
013: import javax.sql.XAConnection;
014: import javax.sql.XADataSource;
015:
016: import org.apache.log4j.Logger;
017:
018: /**
019: * Transactional DataSource wrapper for JDBC 1.0 drivers. This is very
020: * lightweight - it just passes requests through to an underlying driver, and
021: * wraps the results with an XAConnection. The XAConnection and corresponding
022: * XAResource are responsible for closing the connection when appropriate.
023: * Note that the underlying driver may perform pooling, but need not. This
024: * class does not add any pooling capabilities.
025: *
026: * @author Aaron Mulder (ammulder@alumni.princeton.edu)
027: */
028: public class XADataSourceImpl implements XADataSource {
029:
030: private String url;
031: private String user;
032: private String password;
033: private String driverName;
034: private Driver driver;
035: private Properties properties;
036: private int loginTimeout;
037: private PrintWriter logWriter;
038: private boolean saveStackTrace;
039: private static Logger log = Logger
040: .getLogger(XADataSourceImpl.class);
041:
042: /**
043: * Empty constructure for beans, reflection, etc.
044: */
045: public XADataSourceImpl() {
046: }
047:
048: /**
049: * Specifies the URL and properties to connect to the underlying driver.
050: * If the properties are null, they will not be used.
051: */
052: public XADataSourceImpl(String url, Properties properties) {
053: this .url = url;
054: this .properties = properties;
055: }
056:
057: /**
058: * Gets the JDBC URL used to open an underlying connection.
059: */
060: public String getURL() {
061: return url;
062: }
063:
064: /**
065: * Sets the JDBC URL used to open an underlying connection.
066: */
067: public void setURL(String url) {
068: this .url = url;
069: }
070:
071: /**
072: * Gets the JDBC user name used to open an underlying connection.
073: */
074: public String getUser() {
075: return user;
076: }
077:
078: /**
079: * Sets the JDBC user name used to open an underlying connection.
080: * This is optional - use it only if your underlying driver requires it.
081: */
082: public void setUser(String user) {
083: this .user = user;
084: }
085:
086: /**
087: * Gets the JDBC password used to open an underlying connection.
088: */
089: public String getPassword() {
090: return password;
091: }
092:
093: /**
094: * Sets the JDBC password used to open an underlying connection.
095: * This is optional - use it only if your underlying driver requires it.
096: */
097: public void setPassword(String password) {
098: this .password = password;
099: }
100:
101: public void setDriver(String driverName) {
102: this .driverName = driverName;
103: }
104:
105: /**
106: * Gets the JDBC properties used to open an underlying connection.
107: */
108: public Properties getProperties() {
109: return properties;
110: }
111:
112: /**
113: * Sets the JDBC properties used to open an underlying connection.
114: * This is optional - use it only if your underlying driver requires it.
115: */
116: public void setProperties(Properties properties) {
117: this .properties = properties;
118: }
119:
120: /**
121: * Have XAClientConnections save a stack trace on creation
122: * This is useful for debugging non-closed connections.
123: * It must be used with ReleaseOnCommit option
124: */
125: public boolean getSaveStackTrace() {
126: return saveStackTrace;
127: }
128:
129: public void setSaveStackTrace(boolean save) {
130: saveStackTrace = save;
131: }
132:
133: /**
134: * Gets the log writer used to record when XAConnections are opened.
135: */
136: public PrintWriter getLogWriter() throws SQLException {
137: return logWriter;
138: }
139:
140: /**
141: * Sets a log writer used to record when XAConnections are opened.
142: */
143: public void setLogWriter(PrintWriter writer) throws SQLException {
144: if (writer == null) {
145: logWriter = null;
146: }
147:
148: }
149:
150: /**
151: * This is not used by the current implementation, since the effect would
152: * differ depending on the underlying driver.
153: */
154: public int getLoginTimeout() throws SQLException {
155: return loginTimeout;
156: }
157:
158: /**
159: * This is not used by the current implementation, since the effect would
160: * differ depending on the underlying driver.
161: */
162: public void setLoginTimeout(int timeout) throws SQLException {
163: loginTimeout = timeout;
164: }
165:
166: private void loadDriver() throws SQLException {
167: if (driver == null) {
168: try {
169: driver = (Driver) Class.forName(driverName, true,
170: Thread.currentThread().getContextClassLoader())
171: .newInstance();
172: DriverManager.registerDriver(driver);
173: } catch (ClassNotFoundException e) {
174: log.warn("unable to load driver", e);
175: } catch (InstantiationException e) {
176: log.warn("unable to instantiate driver", e);
177: } catch (IllegalAccessException e) {
178: log.warn("illegal access exception", e);
179: }
180: }
181: }
182:
183: /**
184: * Gets an XAConnection. This first gets a java.sql.Connection from the
185: * underlying driver, and then wraps it in an XAConnection and XAResource.
186: * This uses the URL, user, password, and properties (or as many as you
187: * have specified) to make the connection.
188: */
189: public XAConnection getXAConnection() throws SQLException {
190:
191: loadDriver();
192:
193: Connection con;
194: if (user != null && user.length() > 0)
195: con = DriverManager.getConnection(url, user, password);
196: else if (properties != null)
197: con = DriverManager.getConnection(url, properties);
198: else
199: con = DriverManager.getConnection(url);
200:
201: try {
202: con.setAutoCommit(false);
203: } catch (SQLException e) {
204: log.warn("Unable to disable auto-commit on "
205: + con.getClass().getName());
206: }
207:
208: XAResourceImpl res = new XAResourceImpl(con);
209: XAConnectionImpl xacon = new XAConnectionImpl(con, res,
210: saveStackTrace);
211: res.setXAConnection(xacon);
212:
213: log.debug("created new Connection(" + con.getClass().getName()
214: + ") with XAResource " + res.getClass().getName()
215: + " and XAConnection " + xacon.getClass().getName()
216: + ".");
217:
218: return xacon;
219: }
220:
221: /**
222: * Gets an XAConnection. This first gets a java.sql.Connection from the
223: * underlying driver, and then wraps it in an XAConnection and XAResource.
224: * Note that we never change the default userid and password, but instead
225: * only set the userid and password for this one connection.
226: */
227: public XAConnection getXAConnection(String user, String password)
228: throws SQLException {
229:
230: loadDriver();
231: Connection con = DriverManager.getConnection(url, user,
232: password);
233:
234: try {
235: con.setAutoCommit(false);
236: } catch (SQLException e) {
237: if (logWriter != null)
238: logWriter
239: .println("XADataSource unable to disable auto-commit on "
240: + con.getClass().getName());
241: }
242:
243: XAResourceImpl res = new XAResourceImpl(con);
244: XAConnectionImpl xacon = new XAConnectionImpl(con, res,
245: saveStackTrace);
246: res.setXAConnection(xacon);
247:
248: xacon.setUser(user);
249: xacon.setPassword(password);
250:
251: log.debug(" created new Connection ("
252: + con.getClass().getName() + ") with XAResource "
253: + res.getClass().getName()
254: + " and XAConnection with userid and password "
255: + xacon.getClass().getName());
256:
257: return xacon;
258: }
259: }
|