KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > oracle > toplink > essentials > internal > ejb > cmp3 > metadata > listeners > MetadataEntityListener


1 /*
2  * The contents of this file are subject to the terms
3  * of the Common Development and Distribution License
4  * (the "License"). You may not use this file except
5  * in compliance with the License.
6  *
7  * You can obtain a copy of the license at
8  * glassfish/bootstrap/legal/CDDLv1.0.txt or
9  * https://glassfish.dev.java.net/public/CDDLv1.0.html.
10  * See the License for the specific language governing
11  * permissions and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL
14  * HEADER in each file and include the License file at
15  * glassfish/bootstrap/legal/CDDLv1.0.txt. If applicable,
16  * add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your
18  * own identifying information: Portions Copyright [yyyy]
19  * [name of copyright owner]
20  */

21 // Copyright (c) 1998, 2006, Oracle. All rights reserved.
22
package oracle.toplink.essentials.internal.ejb.cmp3.metadata.listeners;
23
24 import java.lang.reflect.InvocationTargetException JavaDoc;
25 import java.lang.reflect.Method JavaDoc;
26 import java.lang.reflect.Modifier JavaDoc;
27
28 import java.security.AccessController JavaDoc;
29 import java.security.PrivilegedActionException JavaDoc;
30
31 import java.util.Hashtable JavaDoc;
32 import java.util.Vector JavaDoc;
33
34 import oracle.toplink.essentials.exceptions.ValidationException;
35
36 import oracle.toplink.essentials.descriptors.DescriptorEvent;
37 import oracle.toplink.essentials.descriptors.DescriptorEventAdapter;
38 import oracle.toplink.essentials.descriptors.DescriptorEventManager;
39
40 import oracle.toplink.essentials.internal.security.PrivilegedAccessHelper;
41 import oracle.toplink.essentials.internal.security.PrivilegedMethodInvoker;
42
43 /**
44  * A MetadataEntityListener and is placed on the owning entity's descriptor.
45  * Callback methods from an EntityListener require a signature on the method.
46  * Namely, they must have an Object parameter.
47  *
48  * @author Guy Pelletier
49  * @since TopLink 10.1.3/EJB 3.0 Preview
50  */

51 public class MetadataEntityListener extends DescriptorEventAdapter {
52     public final static String JavaDoc POST_BUILD = "postBuild";
53     public final static String JavaDoc POST_CLONE = "postClone";
54     public final static String JavaDoc POST_DELETE = "postDelete";
55     public final static String JavaDoc POST_INSERT = "postInsert";
56     public final static String JavaDoc POST_REFRESH = "postRefresh";
57     public final static String JavaDoc POST_UPDATE = "postUpdate";
58     public final static String JavaDoc PRE_PERSIST = "prePersist";
59     public final static String JavaDoc PRE_REMOVE = "preRemove";
60     public final static String JavaDoc PRE_UPDATE_WITH_CHANGES = "preUpdateWithChanges";
61     
62     private Object JavaDoc m_listener;
63     private Class JavaDoc m_entityClass;
64     private Hashtable JavaDoc<String JavaDoc, Method JavaDoc> m_methods;
65     private Hashtable JavaDoc<Integer JavaDoc, Boolean JavaDoc> m_overriddenEvents;
66     private static Hashtable JavaDoc<Integer JavaDoc, String JavaDoc> m_eventStrings;
67     
68     /**
69      * INTERNAL:
70      * The default constructor should not be used.
71      */

72     protected MetadataEntityListener() {
73         m_methods = new Hashtable JavaDoc<String JavaDoc, Method JavaDoc>();
74         
75         // Remember which events are overridden in subclasses.
76
m_overriddenEvents = new Hashtable JavaDoc<Integer JavaDoc, Boolean JavaDoc>();
77         
78         // For quick look up of equivalent event strings from event codes.
79
if (m_eventStrings == null) {
80             m_eventStrings = new Hashtable JavaDoc<Integer JavaDoc, String JavaDoc>();
81             m_eventStrings.put(new Integer JavaDoc(DescriptorEventManager.PostBuildEvent), POST_BUILD);
82             m_eventStrings.put(new Integer JavaDoc(DescriptorEventManager.PostCloneEvent), POST_CLONE);
83             m_eventStrings.put(new Integer JavaDoc(DescriptorEventManager.PostDeleteEvent), POST_DELETE);
84             m_eventStrings.put(new Integer JavaDoc(DescriptorEventManager.PostInsertEvent), POST_INSERT);
85             m_eventStrings.put(new Integer JavaDoc(DescriptorEventManager.PostRefreshEvent), POST_REFRESH);
86             m_eventStrings.put(new Integer JavaDoc(DescriptorEventManager.PostUpdateEvent), POST_UPDATE);
87             m_eventStrings.put(new Integer JavaDoc(DescriptorEventManager.PrePersistEvent), PRE_PERSIST);
88             m_eventStrings.put(new Integer JavaDoc(DescriptorEventManager.PreRemoveEvent), PRE_REMOVE);
89             m_eventStrings.put(new Integer JavaDoc(DescriptorEventManager.PreUpdateWithChangesEvent), PRE_UPDATE_WITH_CHANGES);
90         }
91     }
92
93     /**
94      * INTERNAL:
95      */

96     protected MetadataEntityListener(Class JavaDoc entityClass) {
97         this();
98         m_entityClass = entityClass;
99     }
100     
101     /**
102      * INTERNAL:
103      */

104     public MetadataEntityListener(Class JavaDoc listenerClass, Class JavaDoc entityClass) {
105         this(entityClass);
106         
107         try {
108             m_listener = listenerClass.newInstance();
109         } catch (Exception JavaDoc ex) {
110             ValidationException.errorInstantiatingEntityListener(listenerClass, ex);
111         }
112     }
113     
114     /**
115      * INTERNAL:
116      */

117     public void addEventMethod(String JavaDoc event, Method JavaDoc method) {
118         validateMethod(method);
119         
120         if (m_methods.containsKey(event)) {
121             throw ValidationException.multipleLifecycleCallbackMethodsForSameLifecycleEvent(getListenerClass(), method, getEventMethod(event));
122         } else {
123             m_methods.put(event, method);
124         }
125     }
126
127     /**
128      * INTERNAL:
129      */

130     public Class JavaDoc getEntityClass() {
131         return m_entityClass;
132     }
133     
134     /**
135      * INTERNAL:
136      */

137     protected Method JavaDoc getEventMethod(int eventCode) {
138         String JavaDoc eventString = m_eventStrings.get(eventCode);
139         
140         if (eventString != null) {
141             return getEventMethod(eventString);
142         } else {
143             return null;
144         }
145     }
146     
147     /**
148      * INTERNAL:
149      */

150     protected Method JavaDoc getEventMethod(String JavaDoc event) {
151         return m_methods.get(event);
152     }
153     
154     /**
155      * INTERNAL:
156      */

157     protected String JavaDoc getEventMethodName(String JavaDoc eventName) {
158         Method JavaDoc method = getEventMethod(eventName);
159         
160         if (method != null) {
161             return method.getName();
162         } else {
163             return null;
164         }
165     }
166     
167     /**
168      * INTERNAL:
169      */

170     public Class JavaDoc getListenerClass() {
171         return m_listener.getClass();
172     }
173     
174     /**
175      * INTERNAL:
176      */

177     public Hashtable JavaDoc getMethods() {
178         return m_methods;
179     }
180     
181     /**
182      * INTERNAL:
183      */

184     public String JavaDoc getPostBuildMethodName() {
185         return getEventMethodName(POST_BUILD);
186     }
187     
188     /**
189      * INTERNAL:
190      */

191     public String JavaDoc getPostCloneMethodName() {
192         return getEventMethodName(POST_CLONE);
193     }
194
195     /**
196      * INTERNAL:
197      */

198     public String JavaDoc getPostDeleteMethodName() {
199         return getEventMethodName(POST_DELETE);
200     }
201
202     /**
203      * INTERNAL:
204      */

205     public String JavaDoc getPostInsertMethodName() {
206         return getEventMethodName(POST_INSERT);
207     }
208
209     /**
210      * INTERNAL:
211      */

212     public String JavaDoc getPostRefreshMethodName() {
213         return getEventMethodName(POST_REFRESH);
214     }
215     
216     /**
217      * INTERNAL:
218      */

219     public String JavaDoc getPostUpdateMethodName() {
220         return getEventMethodName(POST_UPDATE);
221     }
222
223     /**
224      * INTERNAL:
225      */

226     public String JavaDoc getPrePersistMethodName() {
227         return getEventMethodName(PRE_PERSIST);
228     }
229     
230     /**
231      * INTERNAL:
232      */

233     public String JavaDoc getPreRemoveMethodName() {
234         return getEventMethodName(PRE_REMOVE);
235     }
236     
237     /**
238      * INTERNAL:
239      */

240     public String JavaDoc getPreUpdateWithChangesMethodName() {
241         return getEventMethodName(PRE_UPDATE_WITH_CHANGES);
242     }
243     
244     /**
245      * INTERNAL:
246      */

247     public boolean hasCallbackMethods() {
248         return m_methods.size() > 0;
249     }
250     
251     /**
252      * INTERNAL:
253      */

254     public boolean hasOverriddenEventMethod(Method JavaDoc eventMethod, int eventCode) {
255         return hasOverriddenEventMethod(getEventMethod(eventCode), eventMethod);
256     }
257     
258     /**
259      * INTERNAL:
260      */

261     protected boolean hasOverriddenEventMethod(Method JavaDoc eventMethod1, Method JavaDoc eventMethod2) {
262         return (eventMethod1 != null && eventMethod1.getName().equals(eventMethod2.getName()));
263     }
264     
265     /**
266      * INTERNAL:
267      */

268     public boolean hasOverriddenEventMethod(Method JavaDoc eventMethod, String JavaDoc eventCode) {
269         return hasOverriddenEventMethod(getEventMethod(eventCode), eventMethod);
270     }
271     
272     /**
273      * INTERNAL:
274      * Sub-classes should implement where necessary.
275      */

276     public void initializeCallbackMethods(ClassLoader JavaDoc classLoader) {}
277     
278     /**
279      * INTERNAL:
280      */

281     protected void invokeMethod(Method JavaDoc method, Object JavaDoc onObject, Object JavaDoc[] objectList, DescriptorEvent event) {
282         //if (method != null && ! isSessionPostBuildEvent(event)) {
283
if (method != null) {
284             try {
285                 if (PrivilegedAccessHelper.shouldUsePrivilegedAccess()){
286                     try {
287                         AccessController.doPrivileged(new PrivilegedMethodInvoker(method, onObject, objectList));
288                     } catch (PrivilegedActionException JavaDoc exception) {
289                         Exception JavaDoc throwableException = exception.getException();
290                         if (throwableException instanceof IllegalAccessException JavaDoc) {
291                             throw ValidationException.invalidCallbackMethod(onObject.getClass(), method.toString());
292                         } else {
293                             Throwable JavaDoc cause = throwableException.getCause();
294                             
295                             if (cause instanceof RuntimeException JavaDoc) {
296                                 throw (RuntimeException JavaDoc) cause;
297                             } else {
298                                 throw (Error JavaDoc) cause;
299                             } }
300                     }
301                 } else {
302                     PrivilegedAccessHelper.invokeMethod(method, onObject, objectList);
303                 }
304             } catch (IllegalAccessException JavaDoc exception) {
305                 // WIP throw a better exception string.
306
throw ValidationException.invalidCallbackMethod(onObject.getClass(), method.toString());
307             } catch (InvocationTargetException JavaDoc e) {
308                 Throwable JavaDoc cause = e.getCause();
309                 
310                 if (cause instanceof RuntimeException JavaDoc) {
311                     throw (RuntimeException JavaDoc) cause;
312                 } else {
313                     throw (Error JavaDoc) cause;
314                 }
315             }
316         }
317     }
318     
319     /**
320      * INTERNAL:
321      */

322     protected void invokeMethod(String JavaDoc event, DescriptorEvent descriptorEvent) {
323         Object JavaDoc[] objectList = { descriptorEvent.getSource() };
324         invokeMethod(getEventMethod(event), m_listener, objectList, descriptorEvent);
325     }
326     
327     /**
328      * INTERNAL:
329      */

330      public boolean isEntityClassListener() {
331         return false;
332     }
333
334     /**
335      * INTERNAL:
336      * Return true is listener has a lifecycle callback method that is
337      * overridden in a subclass.
338      */

339     public boolean isOverriddenEvent(DescriptorEvent event, Vector JavaDoc eventManagers) {
340         int eventCode = event.getEventCode();
341         if (! m_overriddenEvents.containsKey(eventCode)) {
342             m_overriddenEvents.put(eventCode, false); // default
343

344             Method JavaDoc eventMethod = getEventMethod(eventCode);
345         
346             if (eventMethod != null) {
347                 for (DescriptorEventManager eventManager : (Vector JavaDoc<DescriptorEventManager>) eventManagers) {
348                     MetadataEntityListener childListener = (MetadataEntityListener) eventManager.getEntityEventListener();
349                     
350                     // We can't override ourself ...
351
if (childListener == this) {
352                         break;
353                     } else {
354                         if (childListener.hasOverriddenEventMethod(eventMethod, eventCode)) {
355                             m_overriddenEvents.put(eventCode, true);
356                             break; // stop looking
357
}
358                     }
359                 }
360             }
361         }
362         
363         return m_overriddenEvents.get(eventCode);
364     }
365
366     /**
367      * INTERNAL:
368      */

369     protected boolean isSessionPostBuildEvent(DescriptorEvent event) {
370         if (((String JavaDoc) m_eventStrings.get(event)).equals(POST_BUILD)) {
371             return ! event.getSession().isUnitOfWork();
372         }
373         
374         return false;
375     }
376
377     /**
378      * INTERNAL:
379      * Checks if the user already set this call back method via XML. We
380      * need to check because the set methods on the superclass will throw
381      * an exception when multiple methods are added for the callback.
382      */

383     protected boolean noCallbackMethodAlreadySetFor(String JavaDoc event, Method JavaDoc method) {
384         Method JavaDoc cbMethod = (Method JavaDoc) getMethods().get(event);
385         
386         if (cbMethod == null) {
387             return true;
388         } else {
389             return ! cbMethod.getName().equals(method.getName());
390         }
391     }
392
393     /**
394      * INTERNAL:
395      */

396     public void postBuild(DescriptorEvent event) {
397         invokeMethod(POST_BUILD, event);
398     }
399     
400     /**
401      * INTERNAL:
402      */

403     public void postClone(DescriptorEvent event) {
404         invokeMethod(POST_CLONE, event);
405     }
406     
407     /**
408      * INTERNAL:
409      */

410     public void postDelete(DescriptorEvent event) {
411         invokeMethod(POST_DELETE, event);
412     }
413     
414     /**
415      * INTERNAL:
416      */

417     public void postInsert(DescriptorEvent event) {
418         invokeMethod(POST_INSERT, event);
419     }
420     
421     /**
422      * INTERNAL:
423      */

424     public void postRefresh(DescriptorEvent event) {
425         invokeMethod(POST_REFRESH, event);
426     }
427
428     /**
429      * INTERNAL:
430      */

431     public void postUpdate(DescriptorEvent event) {
432         invokeMethod(POST_UPDATE, event);
433     }
434
435     /**
436      * INTERNAL:
437      */

438     public void prePersist(DescriptorEvent event) {
439         invokeMethod(PRE_PERSIST, event);
440     }
441     
442     /**
443      * INTERNAL:
444      */

445     public void preRemove(DescriptorEvent event) {
446         invokeMethod(PRE_REMOVE, event);
447     }
448     
449     /**
450      * INTERNAL:
451      */

452     public void preUpdateWithChanges(DescriptorEvent event) {
453         invokeMethod(PRE_UPDATE_WITH_CHANGES, event);
454     }
455
456     /**
457      * INTERNAL:
458      */

459     public void setEntityClass(Class JavaDoc entityClass) {
460         m_entityClass = entityClass;
461     }
462     
463     /**
464      * INTERNAL:
465      */

466     public void setListener(Object JavaDoc listener) {
467         m_listener = listener;
468     }
469     
470     /**
471      * INTERNAL:
472      */

473     public void setPostBuildMethod(Method JavaDoc method) {
474         addEventMethod(POST_BUILD, method);
475     }
476     
477     /**
478      * INTERNAL:
479      */

480     public void setPostCloneMethod(Method JavaDoc method) {
481         addEventMethod(POST_CLONE, method);
482     }
483
484     /**
485      * INTERNAL:
486      */

487     public void setPostDeleteMethod(Method JavaDoc method) {
488         addEventMethod(POST_DELETE, method);
489     }
490
491     /**
492      * INTERNAL:
493      */

494     public void setPostInsertMethod(Method JavaDoc method) {
495         addEventMethod(POST_INSERT, method);
496     }
497
498     /**
499      * INTERNAL:
500      */

501     public void setPostRefreshMethod(Method JavaDoc method) {
502         addEventMethod(POST_REFRESH, method);
503     }
504     
505     /**
506      * INTERNAL:
507      */

508     public void setPostUpdateMethod(Method JavaDoc method) {
509         addEventMethod(POST_UPDATE, method);
510     }
511
512     /**
513      * INTERNAL:
514      */

515     public void setPrePersistMethod(Method JavaDoc method) {
516         addEventMethod(PRE_PERSIST, method);
517     }
518     
519     /**
520      * INTERNAL:
521      */

522     public void setPreRemoveMethod(Method JavaDoc method) {
523         addEventMethod(PRE_REMOVE, method);
524     }
525     
526     /**
527      * INTERNAL:
528      */

529     public void setPreUpdateWithChangesMethod(Method JavaDoc method) {
530         addEventMethod(PRE_UPDATE_WITH_CHANGES, method);
531     }
532     
533     /**
534      * INTERNAL:
535      */

536     protected void validateMethod(Method JavaDoc method) {
537         int numberOfParameters = method.getParameterTypes().length;
538         Class JavaDoc parameterClass = method.getParameterTypes()[0];
539            
540         if (numberOfParameters == 1 && parameterClass.isAssignableFrom(m_entityClass)) {
541             // So far so good, now check the method modifiers.
542
validateMethodModifiers(method);
543         } else {
544             throw ValidationException.invalidEntityListenerCallbackMethodArguments(m_entityClass, parameterClass, m_listener.getClass(), method.getName());
545         }
546     }
547     
548     /**
549      * INTERNAL:
550      */

551     protected void validateMethodModifiers(Method JavaDoc method) {
552         int modifiers = method.getModifiers();
553         
554         if (Modifier.isStatic(modifiers) || Modifier.isFinal(modifiers)) {
555             throw ValidationException.invalidCallbackMethodModifier(getListenerClass(), method.getName());
556         }
557     }
558 }
559
Popular Tags