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.jpa.embedded.toplink;
018:
019: import java.util.Properties;
020: import java.util.concurrent.ConcurrentHashMap;
021:
022: import oracle.toplink.essentials.sessions.Session;
023: import oracle.toplink.essentials.sessions.SessionEvent;
024: import oracle.toplink.essentials.sessions.SessionEventAdapter;
025: import oracle.toplink.essentials.sessions.UnitOfWork;
026: import org.apache.commons.logging.Log;
027: import org.apache.commons.logging.LogFactory;
028: import org.compass.core.Compass;
029: import org.compass.core.CompassSession;
030: import org.compass.core.CompassTransaction;
031: import org.compass.gps.device.jpa.embedded.JpaCompassGps;
032:
033: /**
034: * A TopLink SessionEventListener that uses the transaction callback methods
035: * to sync between them and Compass transaction mechanism.
036: *
037: * @author kimchy
038: */
039: public class CompassSessionEventListener extends SessionEventAdapter {
040:
041: private static final Log log = LogFactory
042: .getLog(CompassSessionEventListener.class);
043:
044: private Compass compass;
045:
046: private JpaCompassGps jpaCompassGps;
047:
048: private Properties indexSettings;
049:
050: private boolean commitBeforeCompletion;
051:
052: private boolean toplinkControlledTransaction;
053:
054: private ConcurrentHashMap<Session, CompassSessionHolder> sessionsHolders = new ConcurrentHashMap<Session, CompassSessionHolder>();
055:
056: public CompassSessionEventListener(Compass compass,
057: JpaCompassGps jpaCompassGps,
058: boolean commitBeforeCompletion,
059: boolean toplinkControlledTransaction,
060: Properties indexSettings) {
061: this .compass = compass;
062: this .jpaCompassGps = jpaCompassGps;
063: this .commitBeforeCompletion = commitBeforeCompletion;
064: this .toplinkControlledTransaction = toplinkControlledTransaction;
065: this .indexSettings = indexSettings;
066: }
067:
068: public Compass getCompass() {
069: return compass;
070: }
071:
072: public JpaCompassGps getJpaCompassGps() {
073: return jpaCompassGps;
074: }
075:
076: public Properties getIndexSettings() {
077: return indexSettings;
078: }
079:
080: public CompassSession getCurrentCompassSession(Session session) {
081: if (session.isUnitOfWork()) {
082: Session parentSession = ((UnitOfWork) session).getParent();
083: CompassSessionHolder sessionHolder = sessionsHolders
084: .get(parentSession);
085: if (sessionHolder != null) {
086: return sessionHolder.session;
087: } else {
088: return beginCompassSessionAndTx(parentSession).session;
089: }
090: } else {
091: CompassSessionHolder sessionHolder = sessionsHolders
092: .get(session);
093: if (sessionHolder != null) {
094: return sessionHolder.session;
095: } else {
096: return beginCompassSessionAndTx(session).session;
097: }
098: }
099: }
100:
101: public void postBeginTransaction(SessionEvent event) {
102: Session session = findSession(event);
103: beginCompassSessionAndTx(session);
104: }
105:
106: public void preCommitTransaction(SessionEvent event) {
107: if (commitBeforeCompletion) {
108: commit(findSession(event));
109: }
110: }
111:
112: public void postCommitTransaction(SessionEvent event) {
113: if (!commitBeforeCompletion) {
114: commit(findSession(event));
115: }
116: }
117:
118: public void postRollbackTransaction(SessionEvent event) {
119: rollback(findSession(event));
120: }
121:
122: private CompassSessionHolder beginCompassSessionAndTx(
123: Session session) {
124: CompassSession compassSession = compass.openSession();
125: CompassTransaction tr = compassSession.beginTransaction();
126: CompassSessionHolder sessionHolder = new CompassSessionHolder(
127: compassSession, tr);
128: sessionsHolders.put(session, sessionHolder);
129: return sessionHolder;
130: }
131:
132: private void commit(Session session) {
133: CompassSessionHolder holder = sessionsHolders.remove(session);
134: if (toplinkControlledTransaction) {
135: try {
136: holder.tr.commit();
137: } finally {
138: holder.session.close();
139: }
140: }
141: }
142:
143: private void rollback(Session session) {
144: CompassSessionHolder holder = sessionsHolders.remove(session);
145: if (holder == null) {
146: return;
147: }
148: if (toplinkControlledTransaction) {
149: try {
150: holder.tr.rollback();
151: } finally {
152: holder.session.close();
153: }
154: }
155: }
156:
157: private Session findSession(SessionEvent event) {
158: return event.getSession();
159: }
160:
161: protected void finalize() throws Throwable {
162: super .finalize();
163: //TODO: is there a better place to close this?
164: if (log.isInfoEnabled()) {
165: log.info("Compass embedded TopLink shutting down");
166: }
167: if (jpaCompassGps.isRunning()) {
168: jpaCompassGps.stop();
169: }
170: compass.close();
171: }
172:
173: private class CompassSessionHolder {
174:
175: CompassSession session;
176:
177: CompassTransaction tr;
178:
179: public CompassSessionHolder(CompassSession session,
180: CompassTransaction tr) {
181: this.session = session;
182: this.tr = tr;
183: }
184: }
185: }
|