KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > sun > enterprise > util > InjectionManagerImpl


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 in
5  * compliance with the License.
6  *
7  * You can obtain a copy of the license at
8  * https://glassfish.dev.java.net/public/CDDLv1.0.html or
9  * glassfish/bootstrap/legal/CDDLv1.0.txt.
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 Notice in each file and include the License file
15  * at glassfish/bootstrap/legal/CDDLv1.0.txt.
16  * If applicable, add the following below the CDDL Header,
17  * with the fields enclosed by brackets [] replaced by
18  * you own identifying information:
19  * "Portions Copyrighted [year] [name of copyright owner]"
20  *
21  * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
22  */

23 package com.sun.enterprise.util;
24
25 import java.util.List JavaDoc;
26 import java.util.LinkedList JavaDoc;
27 import java.lang.reflect.Field JavaDoc;
28 import java.lang.reflect.Method JavaDoc;
29 import java.lang.reflect.Modifier JavaDoc;
30 import java.lang.reflect.InvocationTargetException JavaDoc;
31 import java.util.logging.*;
32
33 import com.sun.enterprise.InvocationManager;
34 import com.sun.enterprise.Switch;
35 import com.sun.enterprise.InjectionManager;
36 import com.sun.enterprise.InjectionException;
37 import com.sun.enterprise.ComponentInvocation;
38 import javax.naming.InitialContext JavaDoc;
39 import javax.naming.NamingException JavaDoc;
40
41 import com.sun.enterprise.deployment.JndiNameEnvironment;
42 import com.sun.enterprise.deployment.InjectionCapable;
43 import com.sun.enterprise.deployment.InjectionInfo;
44 import com.sun.enterprise.deployment.InjectionTarget;
45 import com.sun.logging.*;
46
47 /**
48  * Implementation of InjectionManager.
49  *
50  * @author Kenneth Saks
51  */

52 public class InjectionManagerImpl implements InjectionManager {
53
54     static Logger _logger=LogDomains.getLogger(LogDomains.UTIL_LOGGER);
55
56     static private LocalStringManagerImpl localStrings =
57         new LocalStringManagerImpl(InjectionManagerImpl.class);
58
59     private Switch theSwitch;
60     private InvocationManager invocationMgr;
61     private InitialContext JavaDoc namingCtx;
62
63     public InjectionManagerImpl() {
64
65         theSwitch = Switch.getSwitch();
66         invocationMgr = theSwitch.getInvocationManager();
67         
68         try {
69             namingCtx = new InitialContext JavaDoc();
70         } catch(NamingException JavaDoc ne) {
71             throw new RuntimeException JavaDoc(ne);
72         }
73
74     }
75
76     public void injectInstance(Object JavaDoc instance)
77         throws InjectionException {
78
79         ComponentInvocation inv = invocationMgr.getCurrentInvocation();
80         
81         if( inv != null ) {
82
83             JndiNameEnvironment componentEnv = (JndiNameEnvironment)
84                 theSwitch.getDescriptorFor(inv.getContainerContext());
85
86             if( componentEnv != null ) {
87                 inject(instance.getClass(), instance, componentEnv, true);
88             } else {
89                 throw new InjectionException("No descriptor registered for " +
90                                              " current invocation : " + inv);
91             }
92
93         } else {
94             throw new InjectionException("null invocation context");
95         }
96
97     }
98
99     public void injectInstance(Object JavaDoc instance,
100                                JndiNameEnvironment componentEnv)
101         throws InjectionException
102     {
103
104         inject(instance.getClass(), instance, componentEnv, true);
105
106     }
107
108     public void injectInstance(Object JavaDoc instance,
109                                JndiNameEnvironment componentEnv,
110                                boolean invokePostConstruct)
111         throws InjectionException
112     {
113
114         inject(instance.getClass(), instance, componentEnv,
115                invokePostConstruct);
116
117     }
118
119     public void injectClass(Class JavaDoc clazz,
120                             JndiNameEnvironment componentEnv)
121         throws InjectionException
122     {
123         injectClass(clazz, componentEnv, true);
124     }
125
126     public void injectClass(Class JavaDoc clazz,
127                             JndiNameEnvironment componentEnv,
128                             boolean invokePostConstruct)
129         throws InjectionException
130     {
131         inject(clazz, null, componentEnv, invokePostConstruct);
132     }
133
134     public void invokeInstancePreDestroy(Object JavaDoc instance,
135                                          JndiNameEnvironment componentEnv)
136         throws InjectionException
137     {
138         invokePreDestroy(instance.getClass(), instance, componentEnv);
139     }
140
141     public void invokeInstancePreDestroy(Object JavaDoc instance)
142         throws InjectionException {
143
144         ComponentInvocation inv = invocationMgr.getCurrentInvocation();
145         
146         if( inv != null ) {
147
148             JndiNameEnvironment componentEnv = (JndiNameEnvironment)
149                 theSwitch.getDescriptorFor(inv.getContainerContext());
150
151             if( componentEnv != null ) {
152                 invokePreDestroy(instance.getClass(), instance, componentEnv);
153             } else {
154                 throw new InjectionException("No descriptor registered for " +
155                                              " current invocation : " + inv);
156             }
157
158         } else {
159             throw new InjectionException("null invocation context");
160         }
161     }
162
163     public void invokeClassPreDestroy(Class JavaDoc clazz,
164                                       JndiNameEnvironment componentEnv)
165         throws InjectionException
166     {
167         invokePreDestroy(clazz, null, componentEnv);
168     }
169
170     /**
171      * @param instance Target instance for injection, or null if injection
172      * is class-based. Any error encountered during any
173      * portion of injection is propagated immediately.
174      */

175     private void inject(final Class JavaDoc clazz, final Object JavaDoc instance,
176                         JndiNameEnvironment envDescriptor,
177                         boolean invokePostConstruct)
178         throws InjectionException
179     {
180         
181         LinkedList JavaDoc<Method JavaDoc> postConstructMethods = new LinkedList JavaDoc<Method JavaDoc>();
182             
183         Class JavaDoc nextClass = clazz;
184
185         // Process each class in the inheritance hierarchy, starting with
186
// the most derived class and ignoring java.lang.Object.
187
while((nextClass != Object JavaDoc.class) && (nextClass != null)) {
188
189             InjectionInfo injInfo =
190                 envDescriptor.getInjectionInfoByClass(nextClass.getName());
191
192             if( injInfo.getInjectionResources().size() > 0 ) {
193                 _inject(nextClass, instance, injInfo.getInjectionResources());
194             }
195
196             if( invokePostConstruct ) {
197                 
198                 if( injInfo.getPostConstructMethodName() != null ) {
199                     
200                     Method JavaDoc postConstructMethod = getPostConstructMethod
201                         (injInfo, nextClass);
202                     
203                     // Delay calling post construct methods until all
204
// dependency injection within the hierarchy has been
205
// completed. Then, invoke the methods starting from
206
// the least-derived class downward.
207
postConstructMethods.addFirst(postConstructMethod);
208                 }
209             }
210
211             nextClass = nextClass.getSuperclass();
212         }
213
214
215         for(Method JavaDoc postConstructMethod : postConstructMethods) {
216
217             invokeLifecycleMethod(postConstructMethod, instance);
218
219         }
220
221     }
222
223     /**
224      * @param instance Target instance for preDestroy, or null if
225      * class-based.
226      */

227     private void invokePreDestroy(final Class JavaDoc clazz, final Object JavaDoc instance,
228                                   JndiNameEnvironment envDescriptor)
229         throws InjectionException
230     {
231         
232         LinkedList JavaDoc<Method JavaDoc> preDestroyMethods = new LinkedList JavaDoc<Method JavaDoc>();
233             
234         Class JavaDoc nextClass = clazz;
235
236         // Process each class in the inheritance hierarchy, starting with
237
// the most derived class and ignoring java.lang.Object.
238
while((nextClass != Object JavaDoc.class) && (nextClass != null)) {
239
240             InjectionInfo injInfo =
241                 envDescriptor.getInjectionInfoByClass(nextClass.getName());
242
243             if( injInfo.getPreDestroyMethodName() != null ) {
244                 
245                 Method JavaDoc preDestroyMethod = getPreDestroyMethod
246                     (injInfo, nextClass);
247                 
248                 // Invoke the preDestroy methods starting from
249
// the least-derived class downward.
250
preDestroyMethods.addFirst(preDestroyMethod);
251             }
252
253             nextClass = nextClass.getSuperclass();
254         }
255
256         for(Method JavaDoc preDestroyMethod : preDestroyMethods) {
257
258             invokeLifecycleMethod(preDestroyMethod, instance);
259
260         }
261
262     }
263
264
265     private void _inject(final Class JavaDoc clazz, final Object JavaDoc instance,
266                         List JavaDoc<InjectionCapable> injectableResources)
267         throws InjectionException
268     {
269
270     for (InjectionCapable next : injectableResources ) {
271
272             try {
273
274                 final Object JavaDoc value = namingCtx.lookup("java:comp/env/" +
275                                                next.getComponentEnvName());
276
277                 // there still could be 2 injection on the same class, better
278
// do a loop here
279
for (InjectionTarget target : next.getInjectionTargets()) {
280                     
281                     // if target class is not the class we are injecting
282
// we can just jump to the next target
283
if (!clazz.getName().equals(target.getClassName()))
284                         continue;
285                     
286                     if( target.isFieldInjectable() ) {
287                         
288                         final Field JavaDoc f = getField(target, clazz);
289                         
290                         if( Modifier.isStatic(f.getModifiers()) &&
291                             (instance != null) ) {
292                             throw new InjectionException
293                                 ("Illegal use of static field " + f +
294                                  " on class that only supports instance-based"
295                                  + " injection");
296                         }
297
298                         if( (instance == null) &&
299                             !Modifier.isStatic(f.getModifiers()) ) {
300                             throw new InjectionException
301                                 ("Injected field " + f +
302                                  " on Application Client class " + clazz +
303                                  " must be declared static");
304                         }
305
306
307                         if(_logger.isLoggable(Level.FINE)) {
308                             _logger.fine("Injecting dependency with logical name "
309                                     + next.getComponentEnvName() +
310                                     " into field " + f + " on class " +
311                                     clazz);
312                         }
313                         
314                         // Wrap actual value insertion in doPrivileged to
315
// allow for private/protected field access.
316
java.security.AccessController.doPrivileged(
317                                 new java.security.PrivilegedExceptionAction JavaDoc() {
318                             public java.lang.Object JavaDoc run() throws Exception JavaDoc {
319                                 if( !f.isAccessible() ) {
320                                     f.setAccessible(true);
321                                 }
322                                 f.set(instance, value);
323                                 return null;
324                             }
325                         });
326                     } else if( target.isMethodInjectable() ) {
327                         
328                         final Method JavaDoc m = getMethod(next, target, clazz);
329
330                         if( Modifier.isStatic(m.getModifiers()) &&
331                             (instance != null) ) {
332                             throw new InjectionException
333                                 ("Illegal use of static method " + m +
334                                  " on class that only supports instance-based"
335                                  + " injection");
336                         }
337
338                         if( (instance == null) &&
339                             !Modifier.isStatic(m.getModifiers()) ) {
340                             throw new InjectionException
341                                 ("Injected method " + m +
342                                  " on Application Client class " + clazz +
343                                  " must be declared static");
344                         }
345                         
346                         if(_logger.isLoggable(Level.FINE)) {
347                             _logger.fine("Injecting dependency with logical name "
348                                     + next.getComponentEnvName() +
349                                     " into method " + m + " on class " +
350                                     clazz);
351                         }
352                         
353                         // Wrap actual value insertion in doPrivileged to
354
// allow for private/protected field access.
355
java.security.AccessController.doPrivileged(
356                                 new java.security.PrivilegedExceptionAction JavaDoc() {
357                             public java.lang.Object JavaDoc run() throws Exception JavaDoc {
358                                 if( !m.isAccessible() ) {
359                                     m.setAccessible(true);
360                                 }
361                                 m.invoke(instance, new Object JavaDoc[] { value });
362                                 return null;
363                             }
364                         });
365                         
366                     }
367                 }
368             } catch(Throwable JavaDoc t) {
369
370                 String JavaDoc msg = "Exception attempting to inject "
371                     + next + " into " + clazz;
372                 _logger.log(Level.FINE, msg, t);
373                 InjectionException ie = new InjectionException(msg);
374                 Throwable JavaDoc cause = (t instanceof InvocationTargetException JavaDoc) ?
375                     ((InvocationTargetException JavaDoc)t).getCause() : t;
376                 ie.initCause( cause );
377                 throw ie;
378
379             }
380         }
381     }
382
383     private void invokeLifecycleMethod(final Method JavaDoc lifecycleMethod,
384                                        final Object JavaDoc instance)
385         throws InjectionException {
386
387         try {
388
389             if(_logger.isLoggable(Level.FINE)) {
390                 _logger.fine("Calling lifeccle method " +
391                              lifecycleMethod + " on class " +
392                              lifecycleMethod.getDeclaringClass());
393             }
394
395             // Wrap actual value insertion in doPrivileged to
396
// allow for private/protected field access.
397
java.security.AccessController.doPrivileged(
398                 new java.security.PrivilegedExceptionAction JavaDoc() {
399                     public java.lang.Object JavaDoc run() throws Exception JavaDoc {
400                         if( !lifecycleMethod.isAccessible() ) {
401                             lifecycleMethod.setAccessible(true);
402                         }
403                         lifecycleMethod.invoke(instance);
404                         return null;
405                     }
406                 });
407         } catch( Throwable JavaDoc t) {
408
409                 String JavaDoc msg = "Exception attempting invoke lifecycle "
410                     + " method " + lifecycleMethod;
411                 _logger.log(Level.FINE, msg, t);
412                 InjectionException ie = new InjectionException(msg);
413                 Throwable JavaDoc cause = (t instanceof InvocationTargetException JavaDoc) ?
414                     ((InvocationTargetException JavaDoc)t).getCause() : t;
415                 ie.initCause( cause );
416                 throw ie;
417
418         }
419         
420         return;
421
422     }
423
424     private Field JavaDoc getField(InjectionTarget target,
425                            Class JavaDoc resourceClass) throws Exception JavaDoc {
426
427         Field JavaDoc f = target.getField();
428
429         if( f == null ) {
430             try {
431                 // Check for the given field within the resourceClass only.
432
// This does not include super-classes of this class.
433
f = resourceClass.getDeclaredField
434                         (target.getFieldName());
435             } catch(java.lang.NoSuchFieldException JavaDoc nsfe) {}
436             if( f != null ) {
437                 target.setField(f);
438             }
439         }
440
441         if( f == null ) {
442             throw new Exception JavaDoc("InjectionManager exception. Field " +
443                                 target.getFieldName() +
444                                 " not found in Class " + resourceClass);
445         }
446
447         return f;
448     }
449
450     private Method JavaDoc getMethod(InjectionCapable resource, InjectionTarget target,
451                              Class JavaDoc resourceClass) throws Exception JavaDoc {
452
453         Method JavaDoc m = target.getMethod();
454
455         if( m == null ) {
456             // Check for the method within the resourceClass only.
457
// This does not include super-classses.
458
for(Method JavaDoc next : resourceClass.getDeclaredMethods()) {
459                 // Overloading is not supported for setter injection
460
// methods, so matching on method-name is sufficient.
461
if(next.getName().equals(target.getMethodName())) {
462                     m = next;
463                     target.setMethod(m);
464                     break;
465                 }
466             }
467         }
468
469         if( m == null ) {
470             throw new Exception JavaDoc("InjectionManager exception. Method " +
471                                 "void " + target.getMethodName() +
472                                 "(" + resource.getInjectResourceType() + ")" +
473                                 " not found in Class " + resourceClass);
474         }
475
476         return m;
477     }
478
479
480     private Method JavaDoc getPostConstructMethod(InjectionInfo injInfo,
481                                           Class JavaDoc resourceClass)
482         throws InjectionException {
483
484         Method JavaDoc m = injInfo.getPostConstructMethod();
485
486         if( m == null ) {
487             String JavaDoc postConstructMethodName =
488                 injInfo.getPostConstructMethodName();
489
490             // Check for the method within the resourceClass only.
491
// This does not include super-classses.
492
for(Method JavaDoc next : resourceClass.getDeclaredMethods()) {
493                 // InjectionManager only handles injection into PostConstruct
494
// methods with no arguments.
495
if( next.getName().equals(postConstructMethodName) &&
496                     (next.getParameterTypes().length == 0) ) {
497                     m = next;
498                     injInfo.setPostConstructMethod(m);
499                     break;
500                 }
501             }
502         }
503
504         if( m == null ) {
505             throw new InjectionException
506                 ("InjectionManager exception. PostConstruct method " +
507                  injInfo.getPostConstructMethodName() +
508                  " could not be found in class " +
509                  injInfo.getClassName());
510         }
511
512         return m;
513     }
514
515     private Method JavaDoc getPreDestroyMethod(InjectionInfo injInfo,
516                                        Class JavaDoc resourceClass)
517         throws InjectionException {
518
519         Method JavaDoc m = injInfo.getPreDestroyMethod();
520
521         if( m == null ) {
522             String JavaDoc preDestroyMethodName = injInfo.getPreDestroyMethodName();
523
524             // Check for the method within the resourceClass only.
525
// This does not include super-classses.
526
for(Method JavaDoc next : resourceClass.getDeclaredMethods()) {
527                 // InjectionManager only handles injection into PreDestroy
528
// methods with no arguments.
529
if( next.getName().equals(preDestroyMethodName) &&
530                     (next.getParameterTypes().length == 0) ) {
531                     m = next;
532                     injInfo.setPreDestroyMethod(m);
533                     break;
534                 }
535             }
536         }
537
538         if( m == null ) {
539             throw new InjectionException
540                 ("InjectionManager exception. PreDestroy method " +
541                  injInfo.getPreDestroyMethodName() +
542                  " could not be found in class " +
543                  injInfo.getClassName());
544         }
545
546         return m;
547     }
548
549 }
550
Popular Tags