KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > ivata > groupware > container > persistence > hibernate > HibernateInterceptor


1 /*
2  * Copyright (c) 2001 - 2005 ivata limited.
3  * All rights reserved.
4  * -----------------------------------------------------------------------------
5  * ivata groupware may be redistributed under the GNU General Public
6  * License as published by the Free Software Foundation;
7  * version 2 of the License.
8  *
9  * These programs are free software; you can redistribute them and/or
10  * modify them under the terms of the GNU General Public License
11  * as published by the Free Software Foundation; version 2 of the License.
12  *
13  * These programs are distributed in the hope that they will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
16  *
17  * See the GNU General Public License in the file LICENSE.txt for more
18  * details.
19  *
20  * If you would like a copy of the GNU General Public License write to
21  *
22  * Free Software Foundation, Inc.
23  * 59 Temple Place - Suite 330
24  * Boston, MA 02111-1307, USA.
25  *
26  *
27  * To arrange commercial support and licensing, contact ivata at
28  * http://www.ivata.com/contact.jsp
29  * -----------------------------------------------------------------------------
30  * $Log: HibernateInterceptor.java,v $
31  * Revision 1.4 2005/05/01 08:44:39 colinmacleod
32  * Fix for ID type reverted to Integer.
33  *
34  * Revision 1.3 2005/04/10 20:09:42 colinmacleod
35  * Added new themes.
36  * Changed id type to String.
37  * Changed i tag to em and b tag to strong.
38  * Improved PicoContainerFactory with NanoContainer scripts.
39  *
40  * Revision 1.2 2005/04/09 17:19:37 colinmacleod
41  * Changed copyright text to GPL v2 explicitly.
42  *
43  * Revision 1.1 2005/03/10 19:23:04 colinmacleod
44  * Moved to ivata groupware.
45  *
46  * Revision 1.1 2004/07/13 19:42:44 colinmacleod
47  * Moved project to POJOs from EJBs.
48  * Applied PicoContainer to services layer (replacing session EJBs).
49  * Applied Hibernate to persistence layer (replacing entity EJBs).
50  * -----------------------------------------------------------------------------
51  */

52 package com.ivata.groupware.container.persistence.hibernate;
53
54 import java.io.Serializable JavaDoc;
55 import java.lang.reflect.InvocationTargetException JavaDoc;
56 import java.util.HashMap JavaDoc;
57 import java.util.Iterator JavaDoc;
58 import java.util.List JavaDoc;
59 import java.util.Map JavaDoc;
60 import java.util.Set JavaDoc;
61 import java.util.Vector JavaDoc;
62
63 import net.sf.hibernate.CallbackException;
64 import net.sf.hibernate.HibernateException;
65 import net.sf.hibernate.Interceptor;
66 import net.sf.hibernate.SessionFactory;
67 import net.sf.hibernate.type.Type;
68
69 import org.apache.commons.beanutils.PropertyUtils;
70 import org.apache.log4j.Logger;
71 import org.picocontainer.MutablePicoContainer;
72 import org.picocontainer.PicoContainer;
73 import org.picocontainer.defaults.DefaultPicoContainer;
74
75 import com.ivata.groupware.container.PicoContainerFactory;
76 import com.ivata.groupware.container.persistence.listener.AddPersistenceListener;
77 import com.ivata.groupware.container.persistence.listener.AmendPersistenceListener;
78 import com.ivata.groupware.container.persistence.listener.RemovePersistenceListener;
79 import com.ivata.mask.persistence.PersistenceException;
80 import com.ivata.mask.util.SystemException;
81 import com.ivata.mask.valueobject.ValueObject;
82
83 /**
84  * @author Colin MacLeod
85  * <a HREF='mailto:colin.macleod@ivata.com'>colin.macleod@ivata.com</a>
86  * @since May 31, 2004
87  * @version $Revision: 1.4 $
88  */

89 public class HibernateInterceptor implements Interceptor, Serializable JavaDoc {
90     private static Map JavaDoc addListeners = new HashMap JavaDoc();
91     private static Map JavaDoc amendListeners = new HashMap JavaDoc();
92     private static Logger log = Logger.getLogger(HibernateInterceptor.class);
93     private static Map JavaDoc removeListeners = new HashMap JavaDoc();
94     /**
95      * Refer to {@link }.
96      *
97      * @param dOClass
98      * @param listener
99      * @see com.ivata.groupware.container.persistence.QueryPersistenceManager#addAddListener(java.lang.Class, com.ivata.groupware.container.persistence.listener.AddPersistenceListener)
100      */

101     public static synchronized void addAddListener(Class JavaDoc dOClass, AddPersistenceListener listener) {
102         if (log.isDebugEnabled()) {
103             log.debug("addAddListener: "
104                     + listener);
105         }
106         List JavaDoc addListenersThisClass = (List JavaDoc)addListeners.get(dOClass.getName());
107         if(addListenersThisClass == null) {
108             addListeners.put(dOClass.getName(),
109                     addListenersThisClass = new Vector JavaDoc());
110         }
111         addListenersThisClass.add(listener);
112     }
113
114
115     /**
116      * Refer to {@link }.
117      *
118      * @param dOClass
119      * @param listener
120      * @see com.ivata.groupware.container.persistence.QueryPersistenceManager#addAmendListener(java.lang.Class, com.ivata.groupware.container.persistence.listener.AddPersistenceListener)
121      */

122     public static synchronized void addAmendListener(Class JavaDoc dOClass, AmendPersistenceListener listener) {
123         if (log.isDebugEnabled()) {
124             log.debug("addAmendListener: "
125                     + listener);
126         }
127         List JavaDoc amendListenersThisClass = (List JavaDoc)amendListeners.get(dOClass.getName());
128         if(amendListenersThisClass == null) {
129             amendListeners.put(dOClass.getName(),
130                     amendListenersThisClass = new Vector JavaDoc());
131         }
132         amendListenersThisClass.add(listener);
133     }
134
135
136     /**
137      * Refer to {@link }.
138      *
139      * @param dOClass
140      * @param listener
141      * @see com.ivata.groupware.container.persistence.QueryPersistenceManager#addRemoveListener(java.lang.Class, com.ivata.groupware.container.persistence.listener.AddPersistenceListener)
142      */

143     public static synchronized void addRemoveListener(Class JavaDoc dOClass, RemovePersistenceListener listener) {
144         if (log.isDebugEnabled()) {
145             log.debug("addRemoveListener: "
146                     + listener);
147         }
148         List JavaDoc removeListenersThisClass = (List JavaDoc)removeListeners.get(dOClass.getName());
149         if(removeListenersThisClass == null) {
150             removeListeners.put(dOClass.getName(),
151                     removeListenersThisClass = new Vector JavaDoc());
152         }
153         removeListenersThisClass.add(listener);
154     }
155     HibernateManager hibernateManager;
156     HibernateSession hibernateSession;
157     SessionFactory sessionFactory;
158     public HibernateInterceptor(HibernateManager hibernateManager,
159             SessionFactory sessionFactory) {
160         this.hibernateManager = hibernateManager;
161         this.sessionFactory = sessionFactory;
162     }
163
164     /**
165      * @see net.sf.hibernate.Interceptor#findDirty(Object, java.io.Serializable, Object[], Object[], String[], net.sf.hibernate.type.Type[])
166      */

167     public int[] findDirty(final Object JavaDoc object,
168             final Serializable JavaDoc arg1,
169             final Object JavaDoc[] arg2,
170             final Object JavaDoc[] arg3,
171             final String JavaDoc[] arg4,
172             final Type[] arg5) {
173         if (log.isDebugEnabled()) {
174             log.debug("findDirty: "
175                     + object);
176         }
177         return null;
178     }
179
180     private String JavaDoc getIdProperty(final Class JavaDoc clazz) throws CallbackException {
181         try {
182             return sessionFactory.getClassMetadata(clazz)
183                                  .getIdentifierPropertyName();
184         } catch (HibernateException e) {
185             throw new CallbackException(
186                 "Error getting identifier property for class " + clazz, e);
187         }
188     }
189     /**
190      * Get a list of listener class names which are superclasses of the data
191      * object class provided.
192      *
193      * @param listeners all listeners of the type (add/amend/remove) to be got.
194      * @param dOClass the subclass to look for.
195      * @return a <code>List</code> of <code>String</code> instances
196      */

197     private List JavaDoc getListenerClasses(Map JavaDoc listeners, Class JavaDoc dOClass)
198             throws PersistenceException {
199         if (log.isDebugEnabled()) {
200             log.debug("getListenerClasses: getting for "
201                     + dOClass);
202         }
203         List JavaDoc listenerClasses = new Vector JavaDoc();
204         Set JavaDoc allClasses = listeners.keySet();
205         for (Iterator JavaDoc iterator = allClasses.iterator(); iterator.hasNext();) {
206             String JavaDoc className = (String JavaDoc) iterator.next();
207             Class JavaDoc listenerClass;
208             try {
209                 listenerClass = Class.forName(className);
210             } catch (ClassNotFoundException JavaDoc e) {
211                 throw new PersistenceException(e);
212             }
213             if (listenerClass.isAssignableFrom(dOClass)) {
214                 listenerClasses.add(className);
215             }
216         }
217         if (log.isDebugEnabled()) {
218             log.debug("getListenerClasses: found "
219                     + listenerClasses.size()
220                     + " classes.");
221         }
222         return listenerClasses;
223     }
224     public Object JavaDoc instantiate(final Class JavaDoc dOClass,
225             final Serializable JavaDoc key)
226             throws CallbackException {
227         if (log.isDebugEnabled()) {
228             log.debug("instantiate: looking for instance of "
229                     + dOClass);
230         }
231         PicoContainer globalContainer;
232         try {
233             globalContainer = PicoContainerFactory.getInstance()
234                 .getGlobalContainer();
235         } catch (SystemException e) {
236             throw new CallbackException(e);
237         }
238         MutablePicoContainer tempContainer = new DefaultPicoContainer(globalContainer);
239         tempContainer.registerComponentImplementation(dOClass);
240
241         Object JavaDoc instance = tempContainer.getComponentInstance(dOClass);
242         try {
243             Integer JavaDoc id = null;
244             if (key != null) {
245                 id = new Integer JavaDoc(key.toString());
246             }
247             PropertyUtils.setProperty(instance, getIdProperty(dOClass), id);
248         } catch (CallbackException e) {
249             log.error(e);
250             throw new CallbackException(
251                 "Error setting property for key '"
252                 + key
253                 +"'", e);
254         } catch (IllegalAccessException JavaDoc e) {
255             log.error(e);
256             throw new CallbackException(
257                 "Error setting property for key '"
258                 + key
259                 +"'", e);
260         } catch (InvocationTargetException JavaDoc e) {
261             log.error(e);
262             throw new CallbackException(
263                 "Error setting property for key '"
264                 + key
265                 +"'", e);
266         } catch (NoSuchMethodException JavaDoc e) {
267             log.error(e);
268             throw new CallbackException(
269                 "Error setting property for key '"
270                 + key
271                 +"'", e);
272         }
273
274         if (log.isDebugEnabled()) {
275             log.debug("instantiate: returning "
276                     + instance);
277         }
278         return instance;
279     }
280
281     /**
282      * @see net.sf.hibernate.Interceptor#isUnsaved(Object)
283      */

284     public Boolean JavaDoc isUnsaved(final Object JavaDoc object) {
285         // if it is a value object, whether or not it is saved depends on the
286
// state of the id field
287
if (object instanceof ValueObject) {
288             ValueObject valueObject = (ValueObject) object;
289             boolean isUnsaved = (valueObject.getIdString() == null);
290             if (log.isDebugEnabled()) {
291                 log.debug("isUnsaved: returning "
292                         + isUnsaved
293                         + ".");
294             }
295             return new Boolean JavaDoc(isUnsaved);
296         }
297         if (log.isDebugEnabled()) {
298             log.debug("isUnsaved: returning null.");
299         }
300         return null;
301     }
302
303     /**
304      * @see net.sf.hibernate.Interceptor#onDelete(Object, java.io.Serializable, Object[], String[], net.sf.hibernate.type.Type[])
305      */

306     public void onDelete(Object JavaDoc object, Serializable JavaDoc id, Object JavaDoc[] state,
307             String JavaDoc[] propertyNames, Type[] types) throws CallbackException {
308         if (log.isDebugEnabled()) {
309             log.debug("In onDelete: "
310                     + object.toString());
311         }
312         // only interested in our value objects!
313
if (!(object instanceof ValueObject)) {
314             if (log.isDebugEnabled()) {
315                 log.debug("In onDelete: object is not a value object.");
316             }
317             return;
318         }
319         ValueObject valueObject = (ValueObject)object;
320         Class JavaDoc valueObjectClass = valueObject.getClass();
321         String JavaDoc className = valueObjectClass.getName();
322         List JavaDoc listenerClasses;
323         try {
324             listenerClasses = getListenerClasses(removeListeners,
325                     valueObjectClass);
326         } catch (PersistenceException e) {
327             throw new CallbackException(e);
328         }
329         for (Iterator JavaDoc classNameIterator = listenerClasses.iterator();
330                 classNameIterator.hasNext();) {
331             String JavaDoc superclassName = (String JavaDoc) classNameIterator.next();
332             List JavaDoc listeners = (List JavaDoc) removeListeners.get(superclassName);
333             if (log.isDebugEnabled()) {
334                 log.debug("In onDelete: processing "
335                         + listeners.size()
336                         + " listener(s) of superclass "
337                         + superclassName);
338             }
339             for (Iterator JavaDoc listenerIterator = listeners.iterator();
340                     listenerIterator.hasNext();) {
341                 RemovePersistenceListener listener =
342                     (RemovePersistenceListener) listenerIterator.next();
343                 try {
344                     listener.onRemove(hibernateSession, valueObject);
345                 } catch (PersistenceException e) {
346                     throw new CallbackException(e);
347                 }
348             }
349         }
350         if (log.isDebugEnabled()) {
351             log.debug("Leaving onDelete.");
352         }
353     }
354
355     /**
356      * @see net.sf.hibernate.Interceptor#onFlushDirty(Object, java.io.Serializable, Object[], Object[], String[], net.sf.hibernate.type.Type[])
357      */

358     public boolean onFlushDirty(Object JavaDoc object, Serializable JavaDoc id,
359             Object JavaDoc[] currentState, Object JavaDoc[] previousState,
360             String JavaDoc[] propertyNames, Type[] types) throws CallbackException {
361         if (log.isDebugEnabled()) {
362             log.debug("In onFlushDirty: "
363                     + object.toString());
364         }
365         // only interested in our value objects!
366
if (!(object instanceof ValueObject)) {
367             if (log.isDebugEnabled()) {
368                 log.debug("Leaving onFlushDirty: object is not a value object.");
369             }
370             return false;
371         }
372         ValueObject valueObject = (ValueObject)object;
373         String JavaDoc className = valueObject.getClass().getName();
374         List JavaDoc listenerClasses;
375         try {
376             listenerClasses = getListenerClasses(amendListeners,
377                     valueObject.getClass());
378         } catch (PersistenceException e) {
379             throw new CallbackException(e);
380         }
381         if (listenerClasses.isEmpty()) {
382             if (log.isDebugEnabled()) {
383                 log.debug("Leaving onFlushDirty: no listeners found for class "
384                         + valueObject.getClass());
385             }
386             return false;
387         }
388         for (Iterator JavaDoc classNameIterator = listenerClasses.iterator();
389                 classNameIterator.hasNext();) {
390             String JavaDoc superclassName = (String JavaDoc) classNameIterator.next();
391             List JavaDoc listeners = (List JavaDoc) amendListeners.get(superclassName);
392             if (log.isDebugEnabled()) {
393                 log.debug("In onFlushDirty: processing "
394                         + listeners.size()
395                         + " listener(s) of superclass "
396                         + superclassName);
397             }
398             for (Iterator JavaDoc listenerIterator = listeners.iterator();
399                     listenerIterator.hasNext();) {
400                 AmendPersistenceListener listener =
401                     (AmendPersistenceListener) listenerIterator.next();
402                 try {
403                     listener.onAmend(hibernateSession, valueObject);
404                 } catch (PersistenceException e) {
405                     throw new CallbackException(e);
406                 }
407                 // no idea why this is necessary! why not let me modify the
408
// object and let Hibernate worry about the state?!
409
// FIXME: not working - throws ClassCastException on property
410
// type if collection
411
// updateState("onFlushDirty", valueObject, currentState,
412
// propertyNames);
413
}
414         }
415         if (log.isDebugEnabled()) {
416             log.debug("Leaving onFlushDirty: returning true.");
417         }
418         return true;
419     }
420
421     /**
422      * @see net.sf.hibernate.Interceptor#onLoad(Object, java.io.Serializable, Object[], String[], net.sf.hibernate.type.Type[])
423      */

424     public boolean onLoad(final Object JavaDoc arg0,
425             final Serializable JavaDoc arg1,
426             final Object JavaDoc[] arg2,
427             final String JavaDoc[] arg3,
428             final Type[] arg4) throws CallbackException {
429         if (log.isDebugEnabled()) {
430             log.debug("onLoad: returning false.");
431         }
432         return false;
433     }
434
435
436     /**
437      * @see net.sf.hibernate.Interceptor#onSave(Object, java.io.Serializable, Object[], String[], net.sf.hibernate.type.Type[])
438      */

439     public boolean onSave(Object JavaDoc object, Serializable JavaDoc id, Object JavaDoc[] state,
440             String JavaDoc[] propertyNames, Type[] types) throws CallbackException {
441         if (log.isDebugEnabled()) {
442             log.debug("In onSave: "
443                     + object.toString());
444         }
445         // only interested in our value objects!
446
if (!(object instanceof ValueObject)) {
447             if (log.isDebugEnabled()) {
448                 log.debug("Leaving onSave: object is not a value object.");
449             }
450             return false;
451         }
452         ValueObject valueObject = (ValueObject)object;
453         String JavaDoc className = valueObject.getClass().getName();
454         List JavaDoc listenerClasses;
455         try {
456             listenerClasses = getListenerClasses(addListeners,
457                     valueObject.getClass());
458         } catch (PersistenceException e) {
459             throw new CallbackException(e);
460         }
461         if (listenerClasses.isEmpty()) {
462             if (log.isDebugEnabled()) {
463                 log.debug("Leaving onSave: no listeners found for class "
464                         + valueObject.getClass());
465             }
466             return false;
467         }
468         for (Iterator JavaDoc classNameIterator = listenerClasses.iterator();
469                 classNameIterator.hasNext();) {
470             String JavaDoc superclassName = (String JavaDoc) classNameIterator.next();
471             List JavaDoc listeners = (List JavaDoc) addListeners.get(superclassName);
472             if (log.isDebugEnabled()) {
473                 log.debug("In onSave: processing "
474                         + listeners.size()
475                         + " listener(s) of superclass "
476                         + superclassName);
477             }
478             for (Iterator JavaDoc listenerIterator = listeners.iterator();
479                     listenerIterator.hasNext();) {
480                 AddPersistenceListener listener =
481                     (AddPersistenceListener) listenerIterator.next();
482                 try {
483                     listener.onAdd(hibernateSession, valueObject);
484                 } catch (PersistenceException e) {
485                     throw new CallbackException(e);
486                 }
487                 // no idea why this is necessary! why not let me modify the
488
// object and let Hibernate worry about the state?!
489
updateState("onSave", valueObject, state, propertyNames);
490             }
491         }
492
493         if (log.isDebugEnabled()) {
494             log.debug("Leaving onSave: returning true.");
495         }
496         return true;
497     }
498     /**
499      * @see net.sf.hibernate.Interceptor#postFlush(java.util.Iterator)
500      */

501     public void postFlush(final Iterator JavaDoc arg0) throws CallbackException {
502         if (log.isDebugEnabled()) {
503             log.debug("postFlush - doing nothing");
504         }
505     }
506
507     /**
508      * @see net.sf.hibernate.Interceptor#preFlush(java.util.Iterator)
509      */

510     public void preFlush(final Iterator JavaDoc arg0) throws CallbackException {
511         if (log.isDebugEnabled()) {
512             log.debug("preFlush - doing nothing");
513         }
514     }
515     /**
516      * Chicken/egg situation - can't put this in the constructor.
517      * @param hibernateSession
518      */

519     public void setHibernateSession(HibernateSession hibernateSession) {
520         if (log.isDebugEnabled()) {
521             log.debug("setHibernateSession: "
522                     + hibernateSession);
523         }
524         this.hibernateSession = hibernateSession;
525     }
526
527     private void updateState(String JavaDoc methodName, ValueObject valueObject,
528             Object JavaDoc[] state, String JavaDoc[] propertyNames)
529             throws CallbackException {
530         for (int i = 0; i < propertyNames.length; i++) {
531             String JavaDoc propertyName = propertyNames[i];
532             try {
533                 Object JavaDoc value = PropertyUtils.getProperty(valueObject,
534                         propertyName);
535                 if (log.isDebugEnabled()) {
536                     log.debug(methodName
537                             + ": property '" + propertyName
538                             + "' was '"
539                             + state[i]
540                             + "', now '"
541                             + value
542                             + "'");
543                 }
544                 state[i] = value;
545             } catch (IllegalAccessException JavaDoc e1) {
546                 throw new CallbackException(e1);
547             } catch (InvocationTargetException JavaDoc e1) {
548                 throw new CallbackException(e1);
549             } catch (NoSuchMethodException JavaDoc e1) {
550                 throw new CallbackException(e1);
551             }
552         }
553
554     }
555 }
556
Popular Tags