001: /**********************************************************************
002: Copyright (c) 2006 Erik Bengtson and others. All rights reserved.
003: Licensed under the Apache License, Version 2.0 (the "License");
004: you may not use this file except in compliance with the License.
005: You may obtain a copy of the License at
006:
007: http://www.apache.org/licenses/LICENSE-2.0
008:
009: Unless required by applicable law or agreed to in writing, software
010: distributed under the License is distributed on an "AS IS" BASIS,
011: WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
012: See the License for the specific language governing permissions and
013: limitations under the License.
014:
015: Contributors:
016: 2007 Andy Jefferson - added prePersist
017: ...
018: **********************************************************************/package org.jpox.jdo;
019:
020: import java.util.ArrayList;
021: import java.util.Iterator;
022: import java.util.List;
023:
024: import javax.jdo.JDOUserCallbackException;
025: import javax.jdo.listener.AttachCallback;
026: import javax.jdo.listener.AttachLifecycleListener;
027: import javax.jdo.listener.ClearCallback;
028: import javax.jdo.listener.ClearLifecycleListener;
029: import javax.jdo.listener.CreateLifecycleListener;
030: import javax.jdo.listener.DeleteCallback;
031: import javax.jdo.listener.DeleteLifecycleListener;
032: import javax.jdo.listener.DetachCallback;
033: import javax.jdo.listener.DetachLifecycleListener;
034: import javax.jdo.listener.DirtyLifecycleListener;
035: import javax.jdo.listener.InstanceLifecycleEvent;
036: import javax.jdo.listener.InstanceLifecycleListener;
037: import javax.jdo.listener.LoadCallback;
038: import javax.jdo.listener.LoadLifecycleListener;
039: import javax.jdo.listener.StoreCallback;
040: import javax.jdo.listener.StoreLifecycleListener;
041: import javax.jdo.spi.PersistenceCapable;
042:
043: import org.jpox.ObjectManager;
044: import org.jpox.ObjectManagerHelper;
045: import org.jpox.StateManager;
046: import org.jpox.state.CallbackHandler;
047: import org.jpox.util.Localiser;
048:
049: /**
050: * CallbackHandler implementation for JDO.
051: *
052: * @version $Revision: 1.10 $
053: */
054: public class JDOCallbackHandler implements CallbackHandler {
055: /** Localiser for messages. */
056: protected static final Localiser LOCALISER = Localiser
057: .getInstance("org.jpox.Localisation");
058:
059: List listeners = new ArrayList(1);
060:
061: private List listenersWorkingCopy = null;
062:
063: /**
064: * Callback after the object has been created.
065: * @param pc The Object
066: */
067: public void postCreate(Object pc) {
068: Iterator iter = getListenersWorkingCopy().iterator();
069: while (iter.hasNext()) {
070: LifecycleListenerForClass listener = (LifecycleListenerForClass) iter
071: .next();
072: if (listener.forClass(pc.getClass())
073: && listener.getListener() instanceof CreateLifecycleListener) {
074: ((CreateLifecycleListener) listener.getListener())
075: .postCreate(new InstanceLifecycleEvent(pc,
076: InstanceLifecycleEvent.CREATE, null));
077: }
078: }
079: }
080:
081: /**
082: * Callback before the object is persisted (just before the lifecycle state change).
083: * @param pc The Object
084: */
085: public void prePersist(Object pc) {
086: // Not supported by JDO
087: }
088:
089: /**
090: * Callback before the object is stored.
091: * @param pc The Object
092: */
093: public void preStore(Object pc) {
094: Iterator iter = getListenersWorkingCopy().iterator();
095: while (iter.hasNext()) {
096: LifecycleListenerForClass listener = (LifecycleListenerForClass) iter
097: .next();
098: if (listener.forClass(pc.getClass())
099: && listener.getListener() instanceof StoreLifecycleListener) {
100: ObjectManager om = ObjectManagerHelper
101: .getObjectManager((PersistenceCapable) pc);
102: String[] fieldNames = null;
103: // PRE_STORE will return the fields being stored (JPOX extension)
104: StateManager sm = om.findStateManager(pc);
105: fieldNames = sm.getDirtyFieldNames();
106: if (fieldNames == null) {
107: // Must be persisting so just return all loaded fields
108: fieldNames = sm.getLoadedFieldNames();
109: }
110: ((StoreLifecycleListener) listener.getListener())
111: .preStore(new FieldInstanceLifecycleEvent(pc,
112: InstanceLifecycleEvent.STORE, null,
113: fieldNames));
114: }
115: }
116:
117: if (pc instanceof StoreCallback) {
118: try {
119: ((StoreCallback) pc).jdoPreStore();
120: } catch (Exception e) {
121: throw new JDOUserCallbackException(LOCALISER.msg(
122: "025001", "jdoPreStore"), e);
123: }
124: }
125: }
126:
127: /**
128: * Callback after the object is stored.
129: * @param pc The Object
130: */
131: public void postStore(Object pc) {
132: Iterator iter = getListenersWorkingCopy().iterator();
133: while (iter.hasNext()) {
134: LifecycleListenerForClass listener = (LifecycleListenerForClass) iter
135: .next();
136: if (listener.forClass(pc.getClass())
137: && listener.getListener() instanceof StoreLifecycleListener) {
138: ((StoreLifecycleListener) listener.getListener())
139: .postStore(new InstanceLifecycleEvent(pc,
140: InstanceLifecycleEvent.STORE, null));
141: }
142: }
143: }
144:
145: /**
146: * Callback before the fields of the object are cleared.
147: * @param pc The Object
148: */
149: public void preClear(Object pc) {
150: Iterator iter = getListenersWorkingCopy().iterator();
151: while (iter.hasNext()) {
152: LifecycleListenerForClass listener = (LifecycleListenerForClass) iter
153: .next();
154: if (listener.forClass(pc.getClass())
155: && listener.getListener() instanceof ClearLifecycleListener) {
156: ((ClearLifecycleListener) listener.getListener())
157: .preClear(new InstanceLifecycleEvent(pc,
158: InstanceLifecycleEvent.CLEAR, null));
159: }
160: }
161:
162: if (pc instanceof ClearCallback) {
163: try {
164: ((ClearCallback) pc).jdoPreClear();
165: } catch (Exception e) {
166: throw new JDOUserCallbackException(LOCALISER.msg(
167: "025001", "jdoPreClear"), e);
168: }
169: }
170: }
171:
172: /**
173: * Callback after the fields of the object are cleared.
174: * @param pc The Object
175: */
176: public void postClear(Object pc) {
177: Iterator iter = getListenersWorkingCopy().iterator();
178: while (iter.hasNext()) {
179: LifecycleListenerForClass listener = (LifecycleListenerForClass) iter
180: .next();
181: if (listener.forClass(pc.getClass())
182: && listener.getListener() instanceof ClearLifecycleListener) {
183: ((ClearLifecycleListener) listener.getListener())
184: .postClear(new InstanceLifecycleEvent(pc,
185: InstanceLifecycleEvent.CLEAR, null));
186: }
187: }
188: }
189:
190: /**
191: * Callback before the object is deleted.
192: * @param pc The Object
193: */
194: public void preDelete(Object pc) {
195: Iterator iter = getListenersWorkingCopy().iterator();
196: while (iter.hasNext()) {
197: LifecycleListenerForClass listener = (LifecycleListenerForClass) iter
198: .next();
199: if (listener.forClass(pc.getClass())
200: && listener.getListener() instanceof DeleteLifecycleListener) {
201: ((DeleteLifecycleListener) listener.getListener())
202: .preDelete(new InstanceLifecycleEvent(pc,
203: InstanceLifecycleEvent.DELETE, null));
204: }
205: }
206:
207: if (pc instanceof DeleteCallback) {
208: try {
209: ((DeleteCallback) pc).jdoPreDelete();
210: } catch (Exception e) {
211: throw new JDOUserCallbackException(LOCALISER.msg(
212: "025001", "jdoPreDelete"), e);
213: }
214: }
215: }
216:
217: /**
218: * Callback after the object is deleted.
219: * @param pc The Object
220: */
221: public void postDelete(Object pc) {
222: Iterator iter = getListenersWorkingCopy().iterator();
223: while (iter.hasNext()) {
224: LifecycleListenerForClass listener = (LifecycleListenerForClass) iter
225: .next();
226: if (listener.forClass(pc.getClass())
227: && listener.getListener() instanceof DeleteLifecycleListener) {
228: ((DeleteLifecycleListener) listener.getListener())
229: .postDelete(new InstanceLifecycleEvent(pc,
230: InstanceLifecycleEvent.DELETE, null));
231: }
232: }
233: }
234:
235: /**
236: * Callback before the object is made dirty.
237: * @param pc The Object
238: */
239: public void preDirty(Object pc) {
240: Iterator iter = getListenersWorkingCopy().iterator();
241: while (iter.hasNext()) {
242: LifecycleListenerForClass listener = (LifecycleListenerForClass) iter
243: .next();
244: if (listener.forClass(pc.getClass())
245: && listener.getListener() instanceof DirtyLifecycleListener) {
246: ((DirtyLifecycleListener) listener.getListener())
247: .preDirty(new InstanceLifecycleEvent(pc,
248: InstanceLifecycleEvent.DIRTY, null));
249: }
250: }
251: }
252:
253: /**
254: * Callback after the object is made dirty.
255: * @param pc The Object
256: */
257: public void postDirty(Object pc) {
258: Iterator iter = getListenersWorkingCopy().iterator();
259: while (iter.hasNext()) {
260: LifecycleListenerForClass listener = (LifecycleListenerForClass) iter
261: .next();
262: if (listener.forClass(pc.getClass())
263: && listener.getListener() instanceof DirtyLifecycleListener) {
264: ((DirtyLifecycleListener) listener.getListener())
265: .postDirty(new InstanceLifecycleEvent(pc,
266: InstanceLifecycleEvent.DIRTY, null));
267: }
268: }
269: }
270:
271: /**
272: * Callback after the fields of the object are loaded.
273: * @param pc The Object
274: */
275: public void postLoad(Object pc) {
276: if (pc instanceof LoadCallback) {
277: try {
278: ((LoadCallback) pc).jdoPostLoad();
279: } catch (Exception e) {
280: throw new JDOUserCallbackException(LOCALISER.msg(
281: "025001", "jdoPostLoad"), e);
282: }
283: }
284:
285: Iterator iter = getListenersWorkingCopy().iterator();
286: while (iter.hasNext()) {
287: LifecycleListenerForClass listener = (LifecycleListenerForClass) iter
288: .next();
289: if (listener.forClass(pc.getClass())
290: && listener.getListener() instanceof LoadLifecycleListener) {
291: ((LoadLifecycleListener) listener.getListener())
292: .postLoad(new InstanceLifecycleEvent(pc,
293: InstanceLifecycleEvent.LOAD, null));
294: }
295: }
296: }
297:
298: /**
299: * Callback after the fields of the object are refreshed.
300: * @param pc The Object
301: */
302: public void postRefresh(Object pc) {
303: // do nothing; JDO does not invoke postRefresh
304: }
305:
306: /**
307: * Callback before the object is detached.
308: * @param pc The Object
309: */
310: public void preDetach(Object pc) {
311: Iterator iter = getListenersWorkingCopy().iterator();
312: while (iter.hasNext()) {
313: LifecycleListenerForClass listener = (LifecycleListenerForClass) iter
314: .next();
315: if (listener.forClass(pc.getClass())
316: && listener.getListener() instanceof DetachLifecycleListener) {
317: ((DetachLifecycleListener) listener.getListener())
318: .preDetach(new InstanceLifecycleEvent(pc,
319: InstanceLifecycleEvent.DETACH, null));
320: }
321: }
322:
323: if (pc instanceof DetachCallback) {
324: try {
325: ((DetachCallback) pc).jdoPreDetach();
326: } catch (Exception e) {
327: throw new JDOUserCallbackException(LOCALISER.msg(
328: "025001", "jdoPreDetach"), e);
329: }
330: }
331: }
332:
333: /**
334: * Callback after the object is detached.
335: * @param pc The Object
336: * @param detachedPC The detached object
337: */
338: public void postDetach(Object pc, Object detachedPC) {
339: if (pc instanceof DetachCallback) {
340: try {
341: ((DetachCallback) detachedPC).jdoPostDetach(pc);
342: } catch (Exception e) {
343: throw new JDOUserCallbackException(LOCALISER.msg(
344: "025001", "jdoPostDetach"), e);
345: }
346: }
347:
348: Iterator iter = getListenersWorkingCopy().iterator();
349: while (iter.hasNext()) {
350: LifecycleListenerForClass listener = (LifecycleListenerForClass) iter
351: .next();
352: if (listener.forClass(pc.getClass())
353: && listener.getListener() instanceof DetachLifecycleListener) {
354: ((DetachLifecycleListener) listener.getListener())
355: .postDetach(new InstanceLifecycleEvent(
356: detachedPC,
357: InstanceLifecycleEvent.DETACH, pc));
358: }
359: }
360: }
361:
362: /**
363: * Callback before the object is attached.
364: * @param pc The Object
365: */
366: public void preAttach(Object pc) {
367: Iterator iter = getListenersWorkingCopy().iterator();
368: while (iter.hasNext()) {
369: LifecycleListenerForClass listener = (LifecycleListenerForClass) iter
370: .next();
371: if (listener.forClass(pc.getClass())
372: && listener.getListener() instanceof AttachLifecycleListener) {
373: ((AttachLifecycleListener) listener.getListener())
374: .preAttach(new InstanceLifecycleEvent(pc,
375: InstanceLifecycleEvent.ATTACH, null));
376: }
377: }
378:
379: if (pc instanceof AttachCallback) {
380: try {
381: ((AttachCallback) pc).jdoPreAttach();
382: } catch (Exception e) {
383: throw new JDOUserCallbackException(LOCALISER.msg(
384: "025001", "jdoPreAttach"), e);
385: }
386: }
387: }
388:
389: /**
390: * Callback after the object is attached.
391: * @param pc The attached Object
392: * @param detachedPC The detached object
393: */
394: public void postAttach(Object pc, Object detachedPC) {
395: if (detachedPC instanceof AttachCallback) {
396: try {
397: ((AttachCallback) pc).jdoPostAttach(detachedPC);
398: } catch (Exception e) {
399: throw new JDOUserCallbackException(LOCALISER.msg(
400: "025001", "jdoPostAttach"), e);
401: }
402: }
403:
404: Iterator iter = getListenersWorkingCopy().iterator();
405: while (iter.hasNext()) {
406: LifecycleListenerForClass listener = (LifecycleListenerForClass) iter
407: .next();
408: if (listener.forClass(pc.getClass())
409: && listener.getListener() instanceof AttachLifecycleListener) {
410: ((AttachLifecycleListener) listener.getListener())
411: .postAttach(new InstanceLifecycleEvent(pc,
412: InstanceLifecycleEvent.ATTACH,
413: detachedPC));
414: }
415: }
416: }
417:
418: /**
419: * Adds a new listener to this handler.
420: * @param listener the listener instance
421: * @param classes the persistent classes which events are fired for the listener
422: */
423: public void addListener(Object listener, Class[] classes) {
424: if (listener == null) {
425: return;
426: }
427: if (listeners == null) {
428: listeners = new ArrayList(1);
429: }
430:
431: listeners.add(new LifecycleListenerForClass(
432: (InstanceLifecycleListener) listener, classes));
433: listenersWorkingCopy = null;
434: }
435:
436: /**
437: * Remove a listener for this handler.
438: * @param listener the listener instance
439: */
440: public void removeListener(Object listener) {
441: if (listener != null && listeners != null) {
442: // Remove from the PMF
443: Iterator iter = listeners.iterator();
444: while (iter.hasNext()) {
445: LifecycleListenerForClass classListener = (LifecycleListenerForClass) iter
446: .next();
447: if (classListener.getListener() == listener) {
448: iter.remove();
449: }
450: }
451: }
452: listenersWorkingCopy = null;
453: }
454:
455: /**
456: * Clear any objects to release resources.
457: */
458: public void close() {
459: if (listeners != null) {
460: listeners.clear();
461: }
462: listenersWorkingCopy = null;
463: }
464:
465: /**
466: * Accessor for the working copy of the listeners (in case any are added/removed in the callbacks).
467: * @return The working copy
468: */
469: protected List getListenersWorkingCopy() {
470: if (listenersWorkingCopy == null) {
471: listenersWorkingCopy = new ArrayList(listeners);
472: }
473:
474: return listenersWorkingCopy;
475: }
476: }
|