1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 import java.sql.Connection;
19 import java.sql.SQLException;
20
21 import org.apache.ojb.broker.OJBRuntimeException;
22 import org.apache.ojb.broker.PBKey;
23 import org.apache.ojb.broker.PersistenceBroker;
24 import org.apache.ojb.broker.PersistenceBrokerException;
25 import org.apache.ojb.broker.TransactionAbortedException;
26 import org.apache.ojb.broker.TransactionInProgressException;
27 import org.apache.ojb.broker.TransactionNotInProgressException;
28 import org.apache.ojb.broker.core.PersistenceBrokerImpl;
29 import org.apache.ojb.broker.metadata.JdbcConnectionDescriptor;
30 import org.apache.ojb.broker.metadata.MetadataManager;
31 import org.apache.ojb.broker.platforms.Platform;
32 import org.apache.ojb.broker.platforms.PlatformFactory;
33 import org.apache.ojb.broker.util.batch.BatchConnection;
34 import org.apache.ojb.broker.util.logging.Logger;
35 import org.apache.ojb.broker.util.logging.LoggerFactory;
36
37
38
39
40
41
42
43
44 public class ConnectionManagerImpl implements ConnectionManagerIF
45 {
46 private Logger log = LoggerFactory.getLogger(ConnectionManagerImpl.class);
47
48 private PersistenceBrokerImpl broker = null;
49 private ConnectionFactory connectionFactory;
50 private JdbcConnectionDescriptor jcd;
51 private Platform platform;
52 private Connection con = null;
53 private PBKey pbKey;
54 private boolean originalAutoCommitState;
55 private boolean isInLocalTransaction;
56 private boolean batchMode;
57 private BatchConnection batchCon = null;
58
59 public ConnectionManagerImpl(PersistenceBroker broker)
60 {
61
62 this.broker = (PersistenceBrokerImpl) broker;
63 this.pbKey = broker.getPBKey();
64 this.jcd = MetadataManager.getInstance().connectionRepository().getDescriptor(pbKey);
65 this.connectionFactory = ConnectionFactoryFactory.getInstance().createConnectionFactory();
66 this.platform = PlatformFactory.getPlatformFor(jcd);
67
68
69
70
71
72
73
74 setBatchMode(false);
75 }
76
77
78
79
80 public JdbcConnectionDescriptor getConnectionDescriptor()
81 {
82 return jcd;
83 }
84
85 public Platform getSupportedPlatform()
86 {
87 return this.platform;
88 }
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107 public Connection getConnection() throws LookupException
108 {
109
110
111
112
113
114
115 if(con != null && !isInLocalTransaction() && !isAlive(con))
116 {
117 releaseConnection();
118 }
119 if (con == null)
120 {
121 con = this.connectionFactory.lookupConnection(jcd);
122 if (con == null) throw new PersistenceBrokerException("Cannot get connection for " + jcd);
123 if (jcd.getUseAutoCommit() == JdbcConnectionDescriptor.AUTO_COMMIT_SET_TRUE_AND_TEMPORARY_FALSE)
124 {
125 try
126 {
127 this.originalAutoCommitState = con.getAutoCommit();
128 }
129 catch (SQLException e)
130 {
131 throw new PersistenceBrokerException("Cannot request autoCommit state on the connection", e);
132 }
133 }
134 if (log.isDebugEnabled()) log.debug("Request new connection from ConnectionFactory: " + con);
135 }
136
137 if (isBatchMode())
138 {
139 if (batchCon == null)
140 {
141 batchCon = new BatchConnection(con, broker);
142 }
143 return batchCon;
144 }
145 else
146 {
147 return con;
148 }
149 }
150
151
152
153
154 public void localBegin()
155 {
156 if (this.isInLocalTransaction)
157 {
158 throw new TransactionInProgressException("Connection is already in transaction");
159 }
160 Connection connection = null;
161 try
162 {
163 connection = this.getConnection();
164 }
165 catch (LookupException e)
166 {
167
168
169
170 throw new PersistenceBrokerException("Can't lookup a connection", e);
171 }
172 if (log.isDebugEnabled()) log.debug("localBegin was called for con " + connection);
173
174
175 if(!broker.isManaged())
176 {
177 if (jcd.getUseAutoCommit() == JdbcConnectionDescriptor.AUTO_COMMIT_SET_TRUE_AND_TEMPORARY_FALSE)
178 {
179 if (log.isDebugEnabled()) log.debug("Try to change autoCommit state to 'false'");
180 platform.changeAutoCommitState(jcd, connection, false);
181 }
182 }
183 else
184 {
185 if(log.isDebugEnabled()) log.debug(
186 "Found managed environment setting in PB, will skip Platform.changeAutoCommitState(...) call");
187 }
188 this.isInLocalTransaction = true;
189 }
190
191
192
193
194 public void localCommit()
195 {
196 if (log.isDebugEnabled()) log.debug("commit was called");
197 if (!this.isInLocalTransaction)
198 {
199 throw new TransactionNotInProgressException("Not in transaction, call begin() before commit()");
200 }
201 try
202 {
203 if(!broker.isManaged())
204 {
205 if (batchCon != null)
206 {
207 batchCon.commit();
208 }
209 else if (con != null)
210 {
211 con.commit();
212 }
213 }
214 else
215 {
216 if(log.isDebugEnabled()) log.debug(
217 "Found managed environment setting in PB, will skip Connection.commit() call");
218 }
219 }
220 catch (SQLException e)
221 {
222 log.error("Commit on underlying connection failed, try to rollback connection", e);
223 this.localRollback();
224 throw new TransactionAbortedException("Commit on connection failed", e);
225 }
226 finally
227 {
228 this.isInLocalTransaction = false;
229 restoreAutoCommitState();
230 this.releaseConnection();
231 }
232 }
233
234
235
236
237 public void localRollback()
238 {
239 log.info("Rollback was called, do rollback on current connection " + con);
240 if (!this.isInLocalTransaction)
241 {
242 throw new PersistenceBrokerException("Not in transaction, cannot abort");
243 }
244 try
245 {
246
247 this.isInLocalTransaction = false;
248 if(!broker.isManaged())
249 {
250 if (batchCon != null)
251 {
252 batchCon.rollback();
253 }
254 else if (con != null && !con.isClosed())
255 {
256 con.rollback();
257 }
258 }
259 else
260 {
261 if(log.isEnabledFor(Logger.INFO)) log.info(
262 "Found managed environment setting in PB, will ignore rollback call on connection, this should be done by JTA");
263 }
264 }
265 catch (SQLException e)
266 {
267 log.error("Rollback on the underlying connection failed", e);
268 }
269 finally
270 {
271 try
272 {
273 restoreAutoCommitState();
274 }
275 catch(OJBRuntimeException ignore)
276 {
277
278 }
279 releaseConnection();
280 }
281 }
282
283
284
285
286 protected void restoreAutoCommitState()
287 {
288 try
289 {
290 if(!broker.isManaged())
291 {
292 if (jcd.getUseAutoCommit() == JdbcConnectionDescriptor.AUTO_COMMIT_SET_TRUE_AND_TEMPORARY_FALSE
293 && originalAutoCommitState == true && con != null && !con.isClosed())
294 {
295 platform.changeAutoCommitState(jcd, con, true);
296 }
297 }
298 else
299 {
300 if(log.isDebugEnabled()) log.debug(
301 "Found managed environment setting in PB, will skip Platform.changeAutoCommitState(...) call");
302 }
303 }
304 catch (SQLException e)
305 {
306
307 throw new OJBRuntimeException("Restore of connection autocommit state failed", e);
308 }
309 }
310
311
312
313
314 public boolean isAlive(Connection conn)
315 {
316 try
317 {
318 return con != null ? !con.isClosed() : false;
319 }
320 catch (SQLException e)
321 {
322 log.error("IsAlive check failed, running connection was invalid!!", e);
323 return false;
324 }
325 }
326
327 public boolean isInLocalTransaction()
328 {
329 return this.isInLocalTransaction;
330 }
331
332
333
334
335
336 public void releaseConnection()
337 {
338 if (this.con == null)
339 {
340 return;
341 }
342 if(isInLocalTransaction())
343 {
344 log.error("Release connection: connection is in local transaction, missing 'localCommit' or" +
345 " 'localRollback' call - try to rollback the connection");
346 localRollback();
347 }
348 else
349 {
350 this.connectionFactory.releaseConnection(this.jcd, this.con);
351 this.con = null;
352 this.batchCon = null;
353 }
354 }
355
356
357
358
359
360 public ConnectionFactory getUnderlyingConnectionFactory()
361 {
362 return connectionFactory;
363 }
364
365
366
367
368
369
370
371
372
373 public void setBatchMode(boolean mode)
374 {
375
376
377
378
379
380
381
382 batchMode = mode && jcd.getBatchMode();
383 }
384
385
386
387
388 public boolean isBatchMode()
389 {
390 return batchMode && platform.supportsBatchOperations();
391 }
392
393
394
395
396 public void executeBatch() throws OJBBatchUpdateException
397 {
398 if (batchCon != null)
399 {
400 try
401 {
402 batchCon.executeBatch();
403 }
404 catch (Throwable th)
405 {
406 throw new OJBBatchUpdateException(th);
407 }
408 }
409 }
410
411
412
413
414
415 public void executeBatchIfNecessary() throws OJBBatchUpdateException
416 {
417 if (batchCon != null)
418 {
419 try
420 {
421 batchCon.executeBatchIfNecessary();
422 }
423 catch (Throwable th)
424 {
425 throw new OJBBatchUpdateException(th);
426 }
427 }
428 }
429
430
431
432
433 public void clearBatch()
434 {
435 if (batchCon != null)
436 {
437 batchCon.clearBatch();
438 }
439 }
440 }