001: /*
002: * Copyright 2004 Clinton Begin
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016: package com.ibatis.sqlmap.engine.scope;
017:
018: import com.ibatis.sqlmap.client.SqlMapClient;
019: import com.ibatis.sqlmap.client.SqlMapException;
020: import com.ibatis.sqlmap.client.SqlMapExecutor;
021: import com.ibatis.sqlmap.client.SqlMapTransactionManager;
022: import com.ibatis.sqlmap.engine.transaction.Transaction;
023: import com.ibatis.sqlmap.engine.transaction.TransactionState;
024: import com.ibatis.sqlmap.engine.impl.SqlMapExecutorDelegate;
025:
026: import java.sql.PreparedStatement;
027: import java.sql.SQLException;
028: import java.util.HashMap;
029: import java.util.Map;
030: import java.util.Iterator;
031:
032: /**
033: * A Session based implementation of the Scope interface
034: */
035: public class SessionScope extends BaseScope {
036: private static long nextId;
037: private long id;
038: // Used by Any
039: private SqlMapClient sqlMapClient;
040: private SqlMapExecutor sqlMapExecutor;
041: private SqlMapTransactionManager sqlMapTxMgr;
042: private int requestStackDepth;
043: // Used by TransactionManager
044: private Transaction transaction;
045: private TransactionState transactionState;
046: // Used by SqlMapExecutorDelegate.setUserProvidedTransaction()
047: private TransactionState savedTransactionState;
048: // Used by StandardSqlMapClient and GeneralStatement
049: private boolean inBatch;
050: // Used by SqlExecutor
051: private Object batch;
052: private boolean commitRequired;
053: private Map preparedStatements;
054:
055: /**
056: * Default constructor
057: */
058: public SessionScope() {
059: preparedStatements = new HashMap();
060: reset();
061: }
062:
063: /**
064: * Get the SqlMapClient for the session
065: *
066: * @return - the SqlMapClient
067: */
068: public SqlMapClient getSqlMapClient() {
069: return sqlMapClient;
070: }
071:
072: /**
073: * Set the SqlMapClient for the session
074: *
075: * @param sqlMapClient - the SqlMapClient
076: */
077: public void setSqlMapClient(SqlMapClient sqlMapClient) {
078: this .sqlMapClient = sqlMapClient;
079: }
080:
081: /**
082: * Get the SQL executor for the session
083: *
084: * @return - the SQL executor
085: */
086: public SqlMapExecutor getSqlMapExecutor() {
087: return sqlMapExecutor;
088: }
089:
090: /**
091: * Get the SQL executor for the session
092: *
093: * @param sqlMapExecutor - the SQL executor
094: */
095: public void setSqlMapExecutor(SqlMapExecutor sqlMapExecutor) {
096: this .sqlMapExecutor = sqlMapExecutor;
097: }
098:
099: /**
100: * Get the transaction manager
101: *
102: * @return - the transaction manager
103: */
104: public SqlMapTransactionManager getSqlMapTxMgr() {
105: return sqlMapTxMgr;
106: }
107:
108: /**
109: * Set the transaction manager
110: *
111: * @param sqlMapTxMgr - the transaction manager
112: */
113: public void setSqlMapTxMgr(SqlMapTransactionManager sqlMapTxMgr) {
114: this .sqlMapTxMgr = sqlMapTxMgr;
115: }
116:
117: /**
118: * Tells us if we are in batch mode or not
119: *
120: * @return - true if we are working with a batch
121: */
122: public boolean isInBatch() {
123: return inBatch;
124: }
125:
126: /**
127: * Turn batch mode on or off
128: *
129: * @param inBatch - the switch
130: */
131: public void setInBatch(boolean inBatch) {
132: this .inBatch = inBatch;
133: }
134:
135: /**
136: * Getter for the session transaction
137: *
138: * @return - the transaction
139: */
140: public Transaction getTransaction() {
141: return transaction;
142: }
143:
144: /**
145: * Setter for the session transaction
146: *
147: * @param transaction - the transaction
148: */
149: public void setTransaction(Transaction transaction) {
150: this .transaction = transaction;
151: }
152:
153: /**
154: * Getter for the transaction state of the session
155: *
156: * @return - the state
157: */
158: public TransactionState getTransactionState() {
159: return transactionState;
160: }
161:
162: /**
163: * Setter for the transaction state of the session
164: *
165: * @param transactionState - the new transaction state
166: */
167: public void setTransactionState(TransactionState transactionState) {
168: this .transactionState = transactionState;
169: }
170:
171: /**
172: * Getter for the batch of the session
173: *
174: * @return - the batch
175: */
176: public Object getBatch() {
177: return batch;
178: }
179:
180: /**
181: * Stter for the batch of the session
182: *
183: * @param batch the new batch
184: */
185: public void setBatch(Object batch) {
186: this .batch = batch;
187: }
188:
189: /**
190: * Get the request stack depth
191: *
192: * @return - the stack depth
193: */
194: public int getRequestStackDepth() {
195: return requestStackDepth;
196: }
197:
198: /**
199: * Increment the stack depth by one.
200: */
201: public void incrementRequestStackDepth() {
202: requestStackDepth++;
203: }
204:
205: /**
206: * Decrement the stack depth by one.
207: */
208: public void decrementRequestStackDepth() {
209: requestStackDepth--;
210: }
211:
212: /**
213: * Getter to tell if a commit is required for the session
214: *
215: * @return - true if a commit is required
216: */
217: public boolean isCommitRequired() {
218: return commitRequired;
219: }
220:
221: /**
222: * Setter to tell the session that a commit is required for the session
223: *
224: * @param commitRequired - the flag
225: */
226: public void setCommitRequired(boolean commitRequired) {
227: this .commitRequired = commitRequired;
228: }
229:
230: public boolean hasPreparedStatementFor(String sql) {
231: return preparedStatements.containsKey(sql);
232: }
233:
234: public boolean hasPreparedStatement(PreparedStatement ps) {
235: return preparedStatements.containsValue(ps);
236: }
237:
238: public PreparedStatement getPreparedStatement(String sql)
239: throws SQLException {
240: if (!hasPreparedStatementFor(sql))
241: throw new SqlMapException(
242: "Could not get prepared statement. This is likely a bug.");
243: PreparedStatement ps = (PreparedStatement) preparedStatements
244: .get(sql);
245: return ps;
246: }
247:
248: public void putPreparedStatement(SqlMapExecutorDelegate delegate,
249: String sql, PreparedStatement ps) {
250: if (delegate.isStatementCacheEnabled()) {
251: if (!isInBatch()) {
252: if (hasPreparedStatementFor(sql))
253: throw new SqlMapException(
254: "Duplicate prepared statement found. This is likely a bug.");
255: preparedStatements.put(sql, ps);
256: }
257: }
258: }
259:
260: public void closePreparedStatements() {
261: Iterator keys = preparedStatements.keySet().iterator();
262: while (keys.hasNext()) {
263: PreparedStatement ps = (PreparedStatement) preparedStatements
264: .get(keys.next());
265: try {
266: ps.close();
267: } catch (Exception e) {
268: // ignore -- we don't care if this fails at this point.
269: }
270: }
271: preparedStatements.clear();
272: }
273:
274: public void reset() {
275: super .reset();
276: this .batch = null;
277: sqlMapExecutor = null;
278: sqlMapTxMgr = null;
279: inBatch = false;
280: transaction = null;
281: transactionState = null;
282: batch = null;
283: requestStackDepth = 0;
284: id = getNextId();
285: closePreparedStatements();
286: preparedStatements.clear();
287: }
288:
289: public boolean equals(Object parameterObject) {
290: if (this == parameterObject)
291: return true;
292: if (!(parameterObject instanceof SessionScope))
293: return false;
294: final SessionScope sessionScope = (SessionScope) parameterObject;
295: if (id != sessionScope.id)
296: return false;
297: return true;
298: }
299:
300: public int hashCode() {
301: return (int) (id ^ (id >>> 32));
302: }
303:
304: /**
305: * Method to get a unique ID
306: *
307: * @return - the new ID
308: */
309: public synchronized static long getNextId() {
310: return nextId++;
311: }
312:
313: /**
314: * Saves the current transaction state
315: */
316: public void saveTransactionState() {
317: savedTransactionState = transactionState;
318: }
319:
320: /**
321: * Restores the previously saved transaction state
322: */
323: public void recallTransactionState() {
324: transactionState = savedTransactionState;
325: }
326:
327: }
|