001: /*
002:
003: Derby - Class org.apache.derby.jdbc.EmbedXAConnection
004:
005: Licensed to the Apache Software Foundation (ASF) under one or more
006: contributor license agreements. See the NOTICE file distributed with
007: this work for additional information regarding copyright ownership.
008: The ASF licenses this file to You under the Apache License, Version 2.0
009: (the "License"); you may not use this file except in compliance with
010: the License. You may obtain a copy of the License at
011:
012: http://www.apache.org/licenses/LICENSE-2.0
013:
014: Unless required by applicable law or agreed to in writing, software
015: distributed under the License is distributed on an "AS IS" BASIS,
016: WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
017: See the License for the specific language governing permissions and
018: limitations under the License.
019:
020: */
021:
022: package org.apache.derby.jdbc;
023:
024: import org.apache.derby.impl.jdbc.Util;
025: import org.apache.derby.iapi.jdbc.EngineConnection;
026: import org.apache.derby.iapi.jdbc.ResourceAdapter;
027:
028: import org.apache.derby.iapi.reference.SQLState;
029: import org.apache.derby.iapi.reference.JDBC30Translation;
030:
031: import java.sql.Connection;
032: import java.sql.SQLException;
033: import java.sql.Statement;
034: import java.sql.PreparedStatement;
035: import java.sql.CallableStatement;
036: import javax.transaction.xa.XAResource;
037:
038: /** -- jdbc 2.0. extension -- */
039: import javax.sql.XAConnection;
040:
041: /**
042: */
043: class EmbedXAConnection extends EmbedPooledConnection implements
044: XAConnection
045:
046: {
047:
048: private EmbedXAResource xaRes;
049:
050: EmbedXAConnection(EmbeddedDataSource ds, ResourceAdapter ra,
051: String u, String p, boolean requestPassword)
052: throws SQLException {
053: super (ds, u, p, requestPassword);
054: xaRes = new EmbedXAResource(this , ra);
055: }
056:
057: /*
058: ** XAConnection methods
059: */
060:
061: public final synchronized XAResource getXAResource()
062: throws SQLException {
063: checkActive();
064: return xaRes;
065: }
066:
067: /*
068: ** BrokeredConnectionControl api
069: */
070: /**
071: Allow control over setting auto commit mode.
072: */
073: public void checkAutoCommit(boolean autoCommit) throws SQLException {
074: if (autoCommit && (xaRes.getCurrentXid() != null))
075: throw Util
076: .generateCsSQLException(SQLState.CANNOT_AUTOCOMMIT_XA);
077:
078: super .checkAutoCommit(autoCommit);
079: }
080:
081: /**
082: Are held cursors allowed. If the connection is attached to
083: a global transaction then downgrade the result set holdabilty
084: to CLOSE_CURSORS_AT_COMMIT if downgrade is true, otherwise
085: throw an exception.
086: If the connection is in a local transaction then the
087: passed in holdabilty is returned.
088: */
089: public int checkHoldCursors(int holdability, boolean downgrade)
090: throws SQLException {
091: if (holdability == JDBC30Translation.HOLD_CURSORS_OVER_COMMIT) {
092: if (xaRes.getCurrentXid() != null) {
093: if (!downgrade)
094: throw Util
095: .generateCsSQLException(SQLState.CANNOT_HOLD_CURSOR_XA);
096:
097: holdability = JDBC30Translation.CLOSE_CURSORS_AT_COMMIT;
098: }
099: }
100:
101: return super .checkHoldCursors(holdability, downgrade);
102: }
103:
104: /**
105: Allow control over creating a Savepoint (JDBC 3.0)
106: */
107: public void checkSavepoint() throws SQLException {
108:
109: if (xaRes.getCurrentXid() != null)
110: throw Util
111: .generateCsSQLException(SQLState.CANNOT_ROLLBACK_XA);
112:
113: super .checkSavepoint();
114: }
115:
116: /**
117: Allow control over calling rollback.
118: */
119: public void checkRollback() throws SQLException {
120:
121: if (xaRes.getCurrentXid() != null)
122: throw Util
123: .generateCsSQLException(SQLState.CANNOT_ROLLBACK_XA);
124:
125: super .checkRollback();
126: }
127:
128: /**
129: Allow control over calling commit.
130: */
131: public void checkCommit() throws SQLException {
132:
133: if (xaRes.getCurrentXid() != null)
134: throw Util
135: .generateCsSQLException(SQLState.CANNOT_COMMIT_XA);
136:
137: super .checkCommit();
138: }
139:
140: public Connection getConnection() throws SQLException {
141: Connection handle;
142:
143: // Is this just a local transaction?
144: if (xaRes.getCurrentXid() == null) {
145: handle = super .getConnection();
146: } else {
147:
148: if (currentConnectionHandle != null) {
149: // this can only happen if someone called start(Xid),
150: // getConnection, getConnection (and we are now the 2nd
151: // getConnection call).
152: // Cannot yank a global connection away like, I don't think...
153: throw Util
154: .generateCsSQLException(SQLState.CANNOT_CLOSE_ACTIVE_XA_CONNECTION);
155: }
156:
157: handle = getNewCurrentConnectionHandle();
158: }
159:
160: currentConnectionHandle.syncState();
161:
162: return handle;
163: }
164:
165: /**
166: Wrap and control a Statement
167: */
168: public Statement wrapStatement(Statement s) throws SQLException {
169: XAStatementControl sc = new XAStatementControl(this , s);
170: return sc.applicationStatement;
171: }
172:
173: /**
174: Wrap and control a PreparedStatement
175: */
176: public PreparedStatement wrapStatement(PreparedStatement ps,
177: String sql, Object generatedKeys) throws SQLException {
178: ps = super .wrapStatement(ps, sql, generatedKeys);
179: XAStatementControl sc = new XAStatementControl(this , ps, sql,
180: generatedKeys);
181: return (PreparedStatement) sc.applicationStatement;
182: }
183:
184: /**
185: Wrap and control a PreparedStatement
186: */
187: public CallableStatement wrapStatement(CallableStatement cs,
188: String sql) throws SQLException {
189: cs = super .wrapStatement(cs, sql);
190: XAStatementControl sc = new XAStatementControl(this , cs, sql);
191: return (CallableStatement) sc.applicationStatement;
192: }
193:
194: /**
195: Override getRealConnection to create a a local connection
196: when we are not associated with an XA transaction.
197:
198: This can occur if the application has a Connection object (conn)
199: and the following sequence occurs.
200:
201: conn = xac.getConnection();
202: xac.start(xid, ...)
203:
204: // do work with conn
205:
206: xac.end(xid, ...);
207:
208: // do local work with conn
209: // need to create new connection here.
210: */
211: public EngineConnection getRealConnection() throws SQLException {
212: EngineConnection rc = super .getRealConnection();
213: if (rc != null)
214: return rc;
215:
216: openRealConnection();
217:
218: // a new Connection, set its state according to the application's Connection handle
219: currentConnectionHandle.setState(true);
220:
221: return realConnection;
222: }
223: }
|