001: /*
002: * Copyright 2004-2006 the original author or authors.
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:
017: package org.compass.gps.device.hibernate;
018:
019: import java.io.Serializable;
020: import java.util.Iterator;
021: import java.util.concurrent.ConcurrentHashMap;
022:
023: import org.compass.core.Compass;
024: import org.compass.core.CompassSession;
025: import org.compass.core.CompassTransaction;
026: import org.compass.core.spi.InternalCompass;
027: import org.compass.core.transaction.TransactionFactory;
028: import org.compass.core.util.FieldInvoker;
029: import org.hibernate.CallbackException;
030: import org.hibernate.EntityMode;
031: import org.hibernate.Interceptor;
032: import org.hibernate.SessionFactory;
033: import org.hibernate.Transaction;
034: import org.hibernate.type.Type;
035:
036: /**
037: * <p>A Compass Hibernate interceptor to manage Compass transactions based on Hibernate
038: * Interceptor transaction lifecycle callbacks. Useful when working with Compass Local
039: * transactions and Hibernate JDBC transaction manager.
040: *
041: * <p>In order to use this interceptor call {@link #injectInterceptor(org.hibernate.SessionFactory, CompassTransactionInterceptor)}
042: * using the <code>SessionFactory</code> and an instance of this class.
043: *
044: * <p>For another option of integrating Compass transactions and Hibernate, please see
045: * {@link org.compass.core.transaction.JTASyncTransactionFactory}, {@link org.compass.core.transaction.XATransactionFactory}
046: * or {@link org.compass.gps.device.hibernate.HibernateSyncTransactionFactory}.
047: *
048: * @author kimchy
049: */
050: public class CompassTransactionInterceptor implements Interceptor {
051:
052: public static void injectInterceptor(SessionFactory sessionFactory,
053: CompassTransactionInterceptor interceptor) throws Exception {
054: FieldInvoker interceptorField = new FieldInvoker(sessionFactory
055: .getClass(), "interceptor").prepare();
056: Interceptor origInterceptor = (Interceptor) interceptorField
057: .get(sessionFactory);
058: interceptor.setInterceptor(origInterceptor);
059: interceptorField.set(sessionFactory, interceptor);
060: }
061:
062: private Interceptor interceptor;
063:
064: private InternalCompass compass;
065:
066: private TransactionFactory transactionFactory;
067:
068: private boolean commitBeforeTransactionCompletion = true;
069:
070: private ConcurrentHashMap activeTransactions = new ConcurrentHashMap();
071:
072: public CompassTransactionInterceptor(Compass compass) {
073: this (compass, true, null);
074: }
075:
076: public CompassTransactionInterceptor(Compass compass,
077: boolean commitBeforeTransactionCompletion,
078: Interceptor interceptor) {
079: this .commitBeforeTransactionCompletion = commitBeforeTransactionCompletion;
080: this .compass = (InternalCompass) compass;
081: this .interceptor = interceptor;
082: this .transactionFactory = this .compass.getTransactionFactory();
083: }
084:
085: void setInterceptor(Interceptor interceptor) {
086: this .interceptor = interceptor;
087: }
088:
089: public void afterTransactionBegin(Transaction transaction) {
090: if (interceptor != null) {
091: interceptor.afterTransactionBegin(transaction);
092: }
093: CompassSession session = transactionFactory
094: .getTransactionBoundSession();
095: // there is already a running transaction, do nothing
096: if (session != null) {
097: return;
098: }
099: if (activeTransactions.get(transaction) != null) {
100: return;
101: }
102: session = compass.openSession();
103: CompassTransaction tr = session.beginTransaction();
104: activeTransactions.put(transaction, tr);
105: }
106:
107: public void beforeTransactionCompletion(Transaction transaction) {
108: if (interceptor != null) {
109: interceptor.beforeTransactionCompletion(transaction);
110: }
111: if (!commitBeforeTransactionCompletion) {
112: return;
113: }
114: CompassTransaction tr = (CompassTransaction) activeTransactions
115: .remove(transaction);
116: if (tr == null) {
117: return;
118: }
119: CompassSession session = transactionFactory
120: .getTransactionBoundSession();
121: tr.commit();
122: session.close();
123: }
124:
125: public void afterTransactionCompletion(Transaction transaction) {
126: if (interceptor != null) {
127: interceptor.afterTransactionCompletion(transaction);
128: }
129: if (commitBeforeTransactionCompletion) {
130: return;
131: }
132: CompassTransaction tr = (CompassTransaction) activeTransactions
133: .remove(transaction);
134: if (tr == null) {
135: return;
136: }
137: CompassSession session = transactionFactory
138: .getTransactionBoundSession();
139: tr.commit();
140: session.close();
141: }
142:
143: public void onDelete(Object entity, Serializable id,
144: Object[] state, String[] propertyNames, Type[] types) {
145: if (interceptor != null) {
146: interceptor.onDelete(entity, id, state, propertyNames,
147: types);
148: }
149: }
150:
151: public boolean onFlushDirty(Object entity, Serializable id,
152: Object[] currentState, Object[] previousState,
153: String[] propertyNames, Type[] types) {
154: if (interceptor != null) {
155: return interceptor.onFlushDirty(entity, id, currentState,
156: previousState, propertyNames, types);
157: }
158: return false;
159: }
160:
161: public boolean onLoad(Object entity, Serializable id,
162: Object[] state, String[] propertyNames, Type[] types) {
163: if (interceptor != null) {
164: return interceptor.onLoad(entity, id, state, propertyNames,
165: types);
166: }
167: return false;
168: }
169:
170: public boolean onSave(Object entity, Serializable id,
171: Object[] state, String[] propertyNames, Type[] types) {
172: if (interceptor != null) {
173: return interceptor.onSave(entity, id, state, propertyNames,
174: types);
175: }
176: return false;
177: }
178:
179: public void postFlush(Iterator entities) {
180: if (interceptor != null) {
181: interceptor.postFlush(entities);
182: }
183: }
184:
185: public void preFlush(Iterator entities) {
186: if (interceptor != null) {
187: interceptor.preFlush(entities);
188: }
189: }
190:
191: public Boolean isTransient(Object entity) {
192: if (interceptor != null) {
193: return interceptor.isTransient(entity);
194: }
195: return null;
196: }
197:
198: public Object instantiate(String entityName, EntityMode entityMode,
199: Serializable id) {
200: if (interceptor != null) {
201: return interceptor.instantiate(entityName, entityMode, id);
202: }
203: return null;
204: }
205:
206: public int[] findDirty(Object entity, Serializable id,
207: Object[] currentState, Object[] previousState,
208: String[] propertyNames, Type[] types) {
209: if (interceptor != null) {
210: return interceptor.findDirty(entity, id, currentState,
211: previousState, propertyNames, types);
212: }
213: return null;
214: }
215:
216: public String getEntityName(Object object) {
217: if (interceptor != null) {
218: return interceptor.getEntityName(object);
219: }
220: return null;
221: }
222:
223: public Object getEntity(String entityName, Serializable id) {
224: if (interceptor != null) {
225: return interceptor.getEntity(entityName, id);
226: }
227: return null;
228: }
229:
230: public String onPrepareStatement(String sql) {
231: if (interceptor != null) {
232: return interceptor.onPrepareStatement(sql);
233: }
234: return sql;
235: }
236:
237: public void onCollectionRemove(Object collection, Serializable key)
238: throws CallbackException {
239: if (interceptor != null) {
240: interceptor.onCollectionRemove(collection, key);
241: }
242: }
243:
244: public void onCollectionRecreate(Object collection, Serializable key)
245: throws CallbackException {
246: if (interceptor != null) {
247: interceptor.onCollectionRecreate(collection, key);
248: }
249: }
250:
251: public void onCollectionUpdate(Object collection, Serializable key)
252: throws CallbackException {
253: if (interceptor != null) {
254: interceptor.onCollectionUpdate(collection, key);
255: }
256: }
257: }
|