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.jdo;
018:
019: import javax.jdo.PersistenceManagerFactory;
020: import javax.jdo.listener.DeleteLifecycleListener;
021: import javax.jdo.listener.InstanceLifecycleEvent;
022: import javax.jdo.listener.StoreLifecycleListener;
023:
024: import org.compass.core.CompassCallbackWithoutResult;
025: import org.compass.core.CompassException;
026: import org.compass.core.CompassSession;
027: import org.compass.core.mapping.CascadeMapping;
028: import org.compass.gps.CompassGpsException;
029: import org.compass.gps.PassiveMirrorGpsDevice;
030:
031: /**
032: * Adds real time monitoring on top of JDO 1 support (see
033: * {@link org.compass.gps.device.jdo.JdoGpsDevice}), using JDO 2
034: * lifecycle events.
035: *
036: * @author kimchy
037: */
038: public class Jdo2GpsDevice extends JdoGpsDevice implements
039: PassiveMirrorGpsDevice {
040:
041: private boolean mirrorDataChanges = true;
042:
043: private boolean ignoreMirrorExceptions;
044:
045: private JdoGpsInstanceLifecycleListener instanceLifecycleListener;
046:
047: public Jdo2GpsDevice() {
048: super ();
049: }
050:
051: public Jdo2GpsDevice(String name,
052: PersistenceManagerFactory persistenceManagerFactory) {
053: super (name, persistenceManagerFactory);
054: }
055:
056: public boolean isMirrorDataChanges() {
057: return mirrorDataChanges;
058: }
059:
060: public void setMirrorDataChanges(boolean mirrorDataChanges) {
061: this .mirrorDataChanges = mirrorDataChanges;
062: }
063:
064: /**
065: * Should exceptions be ignored during the mirroring operations (the JDO 2 event listeners).
066: * Defaults to <code>false</code>.
067: */
068: public boolean isIgnoreMirrorExceptions() {
069: return ignoreMirrorExceptions;
070: }
071:
072: /**
073: * Should exceptions be ignored during the mirroring operations (the JDO 2 event listeners).
074: * Defaults to <code>false</code>.
075: */
076: public void setIgnoreMirrorExceptions(boolean ignoreMirrorExceptions) {
077: this .ignoreMirrorExceptions = ignoreMirrorExceptions;
078: }
079:
080: protected void doStart() throws CompassGpsException {
081: super .doStart();
082: if (isMirrorDataChanges()) {
083: // TODO if there is a way to get the persistence classes, we can
084: // narrow it down with the OSEM classes and provide them instead of
085: // null
086: instanceLifecycleListener = new JdoGpsInstanceLifecycleListener();
087: persistenceManagerFactory.addInstanceLifecycleListener(
088: instanceLifecycleListener, null);
089: }
090: }
091:
092: protected void doStop() throws CompassGpsException {
093: if (isMirrorDataChanges()) {
094: persistenceManagerFactory
095: .removeInstanceLifecycleListener(instanceLifecycleListener);
096: }
097: }
098:
099: private class JdoGpsInstanceLifecycleListener implements
100: DeleteLifecycleListener, StoreLifecycleListener {
101:
102: public JdoGpsInstanceLifecycleListener() {
103: }
104:
105: public void preDelete(InstanceLifecycleEvent event) {
106: }
107:
108: public void preStore(InstanceLifecycleEvent event) {
109: }
110:
111: public void postDelete(InstanceLifecycleEvent event) {
112: if (!shouldMirrorDataChanges()
113: || isPerformingIndexOperation()) {
114: return;
115: }
116:
117: final Object entity = event.getSource();
118: if (!compassGps.hasMappingForEntityForMirror(entity
119: .getClass(), CascadeMapping.Cascade.DELETE)) {
120: return;
121: }
122:
123: try {
124: if (log.isDebugEnabled()) {
125: log
126: .debug(buildMessage("Deleting [" + entity
127: + "]"));
128: }
129: compassGps
130: .executeForMirror(new CompassCallbackWithoutResult() {
131: protected void doInCompassWithoutResult(
132: CompassSession session)
133: throws CompassException {
134: session.delete(entity);
135: }
136: });
137: } catch (Exception e) {
138: if (isIgnoreMirrorExceptions()) {
139: log.error(buildMessage("Failed while deleting ["
140: + entity + "]"), e);
141: } else {
142: throw new JdoGpsDeviceException(
143: buildMessage("Failed while deleting ["
144: + entity + "]"), e);
145: }
146: }
147: }
148:
149: public void postStore(InstanceLifecycleEvent event) {
150: if (!shouldMirrorDataChanges()
151: || isPerformingIndexOperation()) {
152: return;
153: }
154:
155: final Object entity = event.getSource();
156: if (!compassGps.hasMappingForEntityForMirror(entity
157: .getClass(), CascadeMapping.Cascade.SAVE)) {
158: return;
159: }
160:
161: try {
162: if (log.isDebugEnabled()) {
163: log
164: .debug(buildMessage("Updating [" + entity
165: + "]"));
166: }
167: compassGps
168: .executeForMirror(new CompassCallbackWithoutResult() {
169: protected void doInCompassWithoutResult(
170: CompassSession session)
171: throws CompassException {
172: session.save(entity);
173: }
174: });
175: } catch (Exception e) {
176: if (isIgnoreMirrorExceptions()) {
177: log.error(buildMessage("Failed while updating ["
178: + entity + "]"), e);
179: } else {
180: throw new JdoGpsDeviceException(
181: buildMessage("Failed while updating ["
182: + entity + "]"), e);
183: }
184: }
185: }
186: }
187: }
|