~raginggoblin/infolog/infolog

« back to all changes in this revision

Viewing changes to InfologServer/lib/hibernate-distribution-3.3.2.GA/project/core/src/main/java/org/hibernate/jdbc/JDBCContext.java

  • Committer: Raging Goblin
  • Date: 2013-11-16 16:51:32 UTC
  • Revision ID: raging_goblin-20131116165132-weujnptzc88uy4ah
Mavenized the project, now using shared project InfologSync

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * Hibernate, Relational Persistence for Idiomatic Java
3
 
 *
4
 
 * Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
5
 
 * indicated by the @author tags or express copyright attribution
6
 
 * statements applied by the authors.  All third-party contributions are
7
 
 * distributed under license by Red Hat Middleware LLC.
8
 
 *
9
 
 * This copyrighted material is made available to anyone wishing to use, modify,
10
 
 * copy, or redistribute it subject to the terms and conditions of the GNU
11
 
 * Lesser General Public License, as published by the Free Software Foundation.
12
 
 *
13
 
 * This program is distributed in the hope that it will be useful,
14
 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15
 
 * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
16
 
 * for more details.
17
 
 *
18
 
 * You should have received a copy of the GNU Lesser General Public License
19
 
 * along with this distribution; if not, write to:
20
 
 * Free Software Foundation, Inc.
21
 
 * 51 Franklin Street, Fifth Floor
22
 
 * Boston, MA  02110-1301  USA
23
 
 *
24
 
 */
25
 
package org.hibernate.jdbc;
26
 
 
27
 
import java.io.Serializable;
28
 
import java.io.ObjectOutputStream;
29
 
import java.io.IOException;
30
 
import java.io.ObjectInputStream;
31
 
import java.sql.Connection;
32
 
import java.sql.SQLException;
33
 
 
34
 
import javax.transaction.TransactionManager;
35
 
 
36
 
import org.slf4j.Logger;
37
 
import org.slf4j.LoggerFactory;
38
 
import org.hibernate.ConnectionReleaseMode;
39
 
import org.hibernate.HibernateException;
40
 
import org.hibernate.Interceptor;
41
 
import org.hibernate.SessionException;
42
 
import org.hibernate.Transaction;
43
 
import org.hibernate.TransactionException;
44
 
import org.hibernate.util.JTAHelper;
45
 
import org.hibernate.engine.SessionFactoryImplementor;
46
 
import org.hibernate.exception.JDBCExceptionHelper;
47
 
import org.hibernate.transaction.CacheSynchronization;
48
 
import org.hibernate.transaction.TransactionFactory;
49
 
 
50
 
/**
51
 
 * Acts as the mediary between "entity-mode related" sessions in terms of
52
 
 * their interaction with the JDBC data store.
53
 
 *
54
 
 * @author Steve Ebersole
55
 
 */
56
 
public class JDBCContext implements Serializable, ConnectionManager.Callback {
57
 
 
58
 
        // TODO : make this the factory for "entity mode related" sessions;
59
 
        // also means making this the target of transaction-synch and the
60
 
        // thing that knows how to cascade things between related sessions
61
 
        //
62
 
        // At that point, perhaps this thing is a "SessionContext", and
63
 
        // ConnectionManager is a "JDBCContext"?  A "SessionContext" should
64
 
        // live in the impl package...
65
 
 
66
 
        private static final Logger log = LoggerFactory.getLogger( JDBCContext.class );
67
 
 
68
 
        public static interface Context extends TransactionFactory.Context {
69
 
                /**
70
 
                 * We cannot rely upon this method being called! It is only
71
 
                 * called if we are using Hibernate Transaction API.
72
 
                 */
73
 
                public void afterTransactionBegin(Transaction tx);
74
 
                public void beforeTransactionCompletion(Transaction tx);
75
 
                public void afterTransactionCompletion(boolean success, Transaction tx);
76
 
                public ConnectionReleaseMode getConnectionReleaseMode();
77
 
                public boolean isAutoCloseSessionEnabled();
78
 
        }
79
 
 
80
 
        private Context owner;
81
 
        private ConnectionManager connectionManager;
82
 
        private transient boolean isTransactionCallbackRegistered;
83
 
        private transient Transaction hibernateTransaction;
84
 
 
85
 
        public JDBCContext(Context owner, Connection connection, Interceptor interceptor) {
86
 
                this.owner = owner;
87
 
                this.connectionManager = new ConnectionManager(
88
 
                        owner.getFactory(),
89
 
                        this,
90
 
                        owner.getConnectionReleaseMode(),
91
 
                        connection,
92
 
                        interceptor
93
 
                        );
94
 
 
95
 
                final boolean registerSynchronization = owner.isAutoCloseSessionEnabled()
96
 
                        || owner.isFlushBeforeCompletionEnabled()
97
 
                        || owner.getConnectionReleaseMode() == ConnectionReleaseMode.AFTER_TRANSACTION;
98
 
                if ( registerSynchronization ) {
99
 
                        registerSynchronizationIfPossible();
100
 
                }
101
 
        }
102
 
 
103
 
        /**
104
 
         * Private constructor used exclusively for custom serialization...
105
 
         *
106
 
         */
107
 
        private JDBCContext() {
108
 
        }
109
 
 
110
 
        // ConnectionManager.Callback implementation ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
111
 
 
112
 
        public void connectionOpened() {
113
 
                if ( owner.getFactory().getStatistics().isStatisticsEnabled() ) {
114
 
                        owner.getFactory().getStatisticsImplementor().connect();
115
 
                }
116
 
        }
117
 
 
118
 
        public void connectionCleanedUp() {
119
 
                if ( !isTransactionCallbackRegistered ) {
120
 
                        afterTransactionCompletion( false, null );
121
 
                        // Note : success = false, because we don't know the outcome of the transaction
122
 
                }
123
 
        }
124
 
 
125
 
        public SessionFactoryImplementor getFactory() {
126
 
                return owner.getFactory();
127
 
        }
128
 
 
129
 
        public ConnectionManager getConnectionManager() {
130
 
                return connectionManager;
131
 
        }
132
 
 
133
 
        public Connection borrowConnection() {
134
 
                return connectionManager.borrowConnection();
135
 
        }
136
 
        
137
 
        public Connection connection() throws HibernateException {
138
 
                if ( owner.isClosed() ) {
139
 
                        throw new SessionException( "Session is closed" );
140
 
                }
141
 
 
142
 
                return connectionManager.getConnection();
143
 
        }
144
 
 
145
 
        public boolean registerCallbackIfNecessary() {
146
 
                if ( isTransactionCallbackRegistered ) {
147
 
                        return false;
148
 
                }
149
 
                else {
150
 
                        isTransactionCallbackRegistered = true;
151
 
                        return true;
152
 
                }
153
 
 
154
 
        }
155
 
 
156
 
        public boolean registerSynchronizationIfPossible() {
157
 
                if ( isTransactionCallbackRegistered ) {
158
 
                        // we already have a callback registered; either a local
159
 
                        // (org.hibernate.Transaction) transaction has accepted
160
 
                        // callback responsibilities, or we have previously
161
 
                        // registered a transaction synch.
162
 
                        return true;
163
 
                }
164
 
                boolean localCallbacksOnly = owner.getFactory().getSettings()
165
 
                                .getTransactionFactory()
166
 
                                .areCallbacksLocalToHibernateTransactions();
167
 
                if ( localCallbacksOnly ) {
168
 
                        // the configured transaction-factory says it only supports
169
 
                        // local callback mode, so no sense attempting to register a
170
 
                        // JTA Synchronization
171
 
                        return false;
172
 
                }
173
 
                TransactionManager tm = owner.getFactory().getTransactionManager();
174
 
                if ( tm == null ) {
175
 
                        // if there is no TM configured, we will not be able to access
176
 
                        // the javax.transaction.Transaction object in order to
177
 
                        // register a synch anyway.
178
 
                        return false;
179
 
                }
180
 
                else {
181
 
                        try {
182
 
                                if ( !isTransactionInProgress() ) {
183
 
                                        log.trace( "TransactionFactory reported no active transaction; Synchronization not registered" );
184
 
                                        return false;
185
 
                                }
186
 
                                else {
187
 
                                        javax.transaction.Transaction tx = tm.getTransaction();
188
 
                                        if ( JTAHelper.isMarkedForRollback( tx ) ) {
189
 
                                                // transactions marked for rollback-only cause some TM impls to throw exceptions
190
 
                                                log.debug( "Transaction is marked for rollback; skipping Synchronization registration" );
191
 
                                                return false;
192
 
                                        }
193
 
                                        else {
194
 
                                                if ( hibernateTransaction == null ) {
195
 
                                                        hibernateTransaction = owner.getFactory().getSettings().getTransactionFactory().createTransaction( this, owner );
196
 
                                                }
197
 
                                                tx.registerSynchronization( new CacheSynchronization(owner, this, tx, hibernateTransaction) );
198
 
                                                isTransactionCallbackRegistered = true;
199
 
                                                log.debug("successfully registered Synchronization");
200
 
                                                return true;
201
 
                                        }
202
 
                                }
203
 
                        }
204
 
                        catch( HibernateException e ) {
205
 
                                throw e;
206
 
                        }
207
 
                        catch (Exception e) {
208
 
                                throw new TransactionException( "could not register synchronization with JTA TransactionManager", e );
209
 
                        }
210
 
                }
211
 
        }
212
 
        
213
 
        public boolean isTransactionInProgress() {
214
 
                return owner.getFactory().getSettings().getTransactionFactory()
215
 
                                .isTransactionInProgress( this, owner, hibernateTransaction );
216
 
        }
217
 
 
218
 
        public Transaction getTransaction() throws HibernateException {
219
 
                if (hibernateTransaction==null) {
220
 
                        hibernateTransaction = owner.getFactory().getSettings()
221
 
                                        .getTransactionFactory()
222
 
                                        .createTransaction( this, owner );
223
 
                }
224
 
                return hibernateTransaction;
225
 
        }
226
 
        
227
 
        public void beforeTransactionCompletion(Transaction tx) {
228
 
                log.trace( "before transaction completion" );
229
 
                owner.beforeTransactionCompletion(tx);
230
 
        }
231
 
        
232
 
        /**
233
 
         * We cannot rely upon this method being called! It is only
234
 
         * called if we are using Hibernate Transaction API.
235
 
         */
236
 
        public void afterTransactionBegin(Transaction tx) {
237
 
                log.trace( "after transaction begin" );
238
 
                owner.afterTransactionBegin(tx);
239
 
        }
240
 
 
241
 
        public void afterTransactionCompletion(boolean success, Transaction tx) {
242
 
                log.trace( "after transaction completion" );
243
 
 
244
 
                if ( getFactory().getStatistics().isStatisticsEnabled() ) {
245
 
                        getFactory().getStatisticsImplementor().endTransaction(success);
246
 
                }
247
 
 
248
 
                connectionManager.afterTransaction();
249
 
 
250
 
                isTransactionCallbackRegistered = false;
251
 
                hibernateTransaction = null;
252
 
                owner.afterTransactionCompletion(success, tx);
253
 
        }
254
 
        
255
 
        /**
256
 
         * Called after executing a query outside the scope of
257
 
         * a Hibernate or JTA transaction
258
 
         */
259
 
        public void afterNontransactionalQuery(boolean success) {
260
 
                log.trace( "after autocommit" );
261
 
                try {
262
 
                        // check to see if the connection is in auto-commit 
263
 
                        // mode (no connection means aggressive connection
264
 
                        // release outside a JTA transaction context, so MUST
265
 
                        // be autocommit mode)
266
 
                        boolean isAutocommit = connectionManager.isAutoCommit();
267
 
 
268
 
                        connectionManager.afterTransaction();
269
 
                        
270
 
                        if ( isAutocommit ) {
271
 
                                owner.afterTransactionCompletion(success, null);
272
 
                        }
273
 
                }
274
 
                catch (SQLException sqle) {
275
 
                        throw JDBCExceptionHelper.convert( 
276
 
                                        owner.getFactory().getSQLExceptionConverter(),
277
 
                                        sqle,
278
 
                                        "could not inspect JDBC autocommit mode"
279
 
                                );
280
 
                }
281
 
        }
282
 
 
283
 
 
284
 
        // serialization ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
285
 
 
286
 
        private void writeObject(ObjectOutputStream oos) throws IOException {
287
 
                // isTransactionCallbackRegistered denotes whether any Hibernate
288
 
                // Transaction has registered as a callback against this
289
 
                // JDBCContext; only one such callback is allowed.  Directly
290
 
                // serializing this value causes problems with JDBCTransaction,
291
 
                // or really any Transaction impl where the callback is local
292
 
                // to the Transaction instance itself, since that Transaction
293
 
                // is not serialized along with the JDBCContext.  Thus we
294
 
                // handle that fact here explicitly...
295
 
                oos.defaultWriteObject();
296
 
                boolean deserHasCallbackRegistered = isTransactionCallbackRegistered
297
 
                                && ! owner.getFactory().getSettings().getTransactionFactory()
298
 
                                .areCallbacksLocalToHibernateTransactions();
299
 
                oos.writeBoolean( deserHasCallbackRegistered );
300
 
        }
301
 
 
302
 
        private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
303
 
                ois.defaultReadObject();
304
 
                isTransactionCallbackRegistered = ois.readBoolean();
305
 
        }
306
 
 
307
 
        /**
308
 
         * Custom serialization routine used during serialization of a
309
 
         * Session/PersistenceContext for increased performance.
310
 
         *
311
 
         * @param oos The stream to which we should write the serial data.
312
 
         * @throws IOException
313
 
         */
314
 
        public void serialize(ObjectOutputStream oos) throws IOException {
315
 
                connectionManager.serialize( oos );
316
 
        }
317
 
 
318
 
        /**
319
 
         * Custom deserialization routine used during deserialization of a
320
 
         * Session/PersistenceContext for increased performance.
321
 
         *
322
 
         * @param ois The stream from which to read the entry.
323
 
         * @throws IOException
324
 
         */
325
 
        public static JDBCContext deserialize(
326
 
                        ObjectInputStream ois,
327
 
                Context context,
328
 
                Interceptor interceptor) throws IOException {
329
 
                JDBCContext jdbcContext = new JDBCContext();
330
 
                jdbcContext.owner = context;
331
 
                jdbcContext.connectionManager = ConnectionManager.deserialize(
332
 
                                ois,
333
 
                                context.getFactory(),
334
 
                        interceptor,
335
 
                        context.getConnectionReleaseMode(),
336
 
                        jdbcContext
337
 
                );
338
 
                return jdbcContext;
339
 
        }
340
 
}