1
2
3
4
5
6
7
8
9
10
11
12
13
14 package org.eclipse.jetty.plus.webapp;
15
16 import java.util.Iterator;
17
18 import javax.naming.Context;
19 import javax.naming.InitialContext;
20 import javax.naming.NameNotFoundException;
21
22 import org.eclipse.jetty.jndi.NamingUtil;
23 import org.eclipse.jetty.plus.annotation.Injection;
24 import org.eclipse.jetty.plus.annotation.InjectionCollection;
25 import org.eclipse.jetty.plus.annotation.LifeCycleCallback;
26 import org.eclipse.jetty.plus.annotation.LifeCycleCallbackCollection;
27 import org.eclipse.jetty.plus.annotation.PostConstructCallback;
28 import org.eclipse.jetty.plus.annotation.PreDestroyCallback;
29 import org.eclipse.jetty.plus.annotation.RunAsCollection;
30 import org.eclipse.jetty.plus.jndi.EnvEntry;
31 import org.eclipse.jetty.plus.jndi.Link;
32 import org.eclipse.jetty.plus.jndi.NamingEntry;
33 import org.eclipse.jetty.plus.jndi.NamingEntryUtil;
34 import org.eclipse.jetty.util.TypeUtil;
35 import org.eclipse.jetty.util.log.Log;
36 import org.eclipse.jetty.webapp.Descriptor;
37 import org.eclipse.jetty.webapp.FragmentDescriptor;
38 import org.eclipse.jetty.webapp.IterativeDescriptorProcessor;
39 import org.eclipse.jetty.webapp.WebAppContext;
40 import org.eclipse.jetty.webapp.MetaData;
41 import org.eclipse.jetty.webapp.MetaData.Origin;
42 import org.eclipse.jetty.xml.XmlParser;
43
44
45
46
47
48
49
50 public class PlusDescriptorProcessor extends IterativeDescriptorProcessor
51 {
52 public PlusDescriptorProcessor ()
53 {
54 try
55 {
56 registerVisitor("env-entry", getClass().getDeclaredMethod("visitEnvEntry", __signature));
57 registerVisitor("resource-ref", getClass().getDeclaredMethod("visitResourceRef", __signature));
58 registerVisitor("resource-env-ref", getClass().getDeclaredMethod("visitResourceEnvRef", __signature));
59 registerVisitor("message-destination-ref", getClass().getDeclaredMethod("visitMessageDestinationRef", __signature));
60 registerVisitor("post-construct", getClass().getDeclaredMethod("visitPostConstruct", __signature));
61 registerVisitor("pre-destroy", getClass().getDeclaredMethod("visitPreDestroy", __signature));
62 }
63 catch (Exception e)
64 {
65 throw new IllegalStateException(e);
66 }
67 }
68
69
70
71
72 public void start(WebAppContext context, Descriptor descriptor)
73 {
74
75 InjectionCollection injections = (InjectionCollection)context.getAttribute(InjectionCollection.INJECTION_COLLECTION);
76 if (injections == null)
77 {
78 injections = new InjectionCollection();
79 context.setAttribute(InjectionCollection.INJECTION_COLLECTION, injections);
80 }
81
82 LifeCycleCallbackCollection callbacks = (LifeCycleCallbackCollection)context.getAttribute(LifeCycleCallbackCollection.LIFECYCLE_CALLBACK_COLLECTION);
83 if (callbacks == null)
84 {
85 callbacks = new LifeCycleCallbackCollection();
86 context.setAttribute(LifeCycleCallbackCollection.LIFECYCLE_CALLBACK_COLLECTION, callbacks);
87 }
88
89 RunAsCollection runAsCollection = (RunAsCollection)context.getAttribute(RunAsCollection.RUNAS_COLLECTION);
90 if (runAsCollection == null)
91 {
92 runAsCollection = new RunAsCollection();
93 context.setAttribute(RunAsCollection.RUNAS_COLLECTION, runAsCollection);
94 }
95 }
96
97
98
99
100
101 public void end(WebAppContext context,Descriptor descriptor)
102 {
103 }
104
105
106
107
108
109
110
111
112
113
114 public void visitEnvEntry (WebAppContext context, Descriptor descriptor, XmlParser.Node node)
115 throws Exception
116 {
117 String name=node.getString("env-entry-name",false,true);
118 String type = node.getString("env-entry-type",false,true);
119 String valueStr = node.getString("env-entry-value",false,true);
120
121
122
123 if (valueStr==null || valueStr.equals(""))
124 {
125 Log.warn("No value for env-entry-name "+name);
126 return;
127 }
128
129 Origin o = context.getMetaData().getOrigin("env-entry."+name);
130 switch (o)
131 {
132 case NotSet:
133 {
134
135 context.getMetaData().setOrigin("env-entry."+name, descriptor);
136
137
138
139
140
141 addInjections (context, descriptor, node, name, TypeUtil.fromName(type));
142 Object value = TypeUtil.valueOf(type,valueStr);
143 bindEnvEntry(name, value);
144 break;
145 }
146 case WebXml:
147 case WebDefaults:
148 case WebOverride:
149 {
150
151
152
153 if (!(descriptor instanceof FragmentDescriptor))
154 {
155
156
157 context.getMetaData().setOrigin("env-entry."+name, descriptor);
158 addInjections (context, descriptor, node, name, TypeUtil.fromName(type));
159 Object value = TypeUtil.valueOf(type,valueStr);
160 bindEnvEntry(name, value);
161 }
162 else
163 {
164
165
166
167 Descriptor d = context.getMetaData().getOriginDescriptor("env-entry."+name+".injection");
168 if (d==null || d instanceof FragmentDescriptor)
169 addInjections(context, descriptor, node, name, TypeUtil.fromName(type));
170 }
171 break;
172 }
173 case WebFragment:
174 {
175
176 throw new IllegalStateException("Conflicting env-entry "+name+" in "+descriptor.getResource());
177 }
178 }
179 }
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211 public void visitResourceRef (WebAppContext context, Descriptor descriptor, XmlParser.Node node)
212 throws Exception
213 {
214 String jndiName = node.getString("res-ref-name",false,true);
215 String type = node.getString("res-type", false, true);
216 String auth = node.getString("res-auth", false, true);
217 String shared = node.getString("res-sharing-scope", false, true);
218
219 Origin o = context.getMetaData().getOrigin("resource-ref."+jndiName);
220 switch (o)
221 {
222 case NotSet:
223 {
224
225 context.getMetaData().setOrigin("resource-ref."+jndiName, descriptor);
226
227
228 Class<?> typeClass = TypeUtil.fromName(type);
229 if (typeClass==null)
230 typeClass = context.loadClass(type);
231 addInjections(context, descriptor, node, jndiName, typeClass);
232 bindResourceRef(context,jndiName, typeClass);
233 break;
234 }
235 case WebXml:
236 case WebDefaults:
237 case WebOverride:
238 {
239
240 if (!(descriptor instanceof FragmentDescriptor))
241 {
242
243
244 context.getMetaData().setOrigin("resource-ref."+jndiName, descriptor);
245
246
247 Class<?> typeClass = TypeUtil.fromName(type);
248 if (typeClass==null)
249 typeClass = context.loadClass(type);
250
251 addInjections(context, descriptor, node, jndiName, typeClass);
252
253
254 bindResourceRef(context,jndiName, typeClass);
255 }
256 else
257 {
258
259
260
261
262 Descriptor d = context.getMetaData().getOriginDescriptor("resource-ref."+jndiName+".injection");
263 if (d==null || d instanceof FragmentDescriptor)
264 {
265 Class<?> typeClass = TypeUtil.fromName(type);
266 if (typeClass==null)
267 typeClass = context.loadClass(type);
268 addInjections(context, descriptor, node, jndiName, TypeUtil.fromName(type));
269 }
270 }
271 break;
272 }
273 case WebFragment:
274 {
275
276 throw new IllegalStateException("Conflicting resource-ref "+jndiName+" in "+descriptor.getResource());
277 }
278 }
279
280 }
281
282
283
284
285
286
287
288
289
290
291
292
293 public void visitResourceEnvRef (WebAppContext context, Descriptor descriptor, XmlParser.Node node)
294 throws Exception
295 {
296 String jndiName = node.getString("resource-env-ref-name",false,true);
297 String type = node.getString("resource-env-ref-type", false, true);
298
299 Origin o = context.getMetaData().getOrigin("resource-env-ref."+jndiName);
300 switch (o)
301 {
302 case NotSet:
303 {
304
305
306
307 Class<?> typeClass = TypeUtil.fromName(type);
308 if (typeClass==null)
309 typeClass = context.loadClass(type);
310 addInjections (context, descriptor, node, jndiName, typeClass);
311 bindResourceEnvRef(context,jndiName, typeClass);
312 break;
313 }
314 case WebXml:
315 case WebDefaults:
316 case WebOverride:
317 {
318
319
320 if (!(descriptor instanceof FragmentDescriptor))
321 {
322
323
324 context.getMetaData().setOrigin("resource-env-ref."+jndiName, descriptor);
325 Class<?> typeClass = TypeUtil.fromName(type);
326 if (typeClass==null)
327 typeClass = context.loadClass(type);
328 addInjections (context, descriptor, node, jndiName, typeClass);
329 bindResourceEnvRef(context,jndiName, typeClass);
330 }
331 else
332 {
333
334
335 Descriptor d = context.getMetaData().getOriginDescriptor("resource-env-ref."+jndiName+".injection");
336 if (d == null || d instanceof FragmentDescriptor)
337 {
338 Class<?> typeClass = TypeUtil.fromName(type);
339 if (typeClass==null)
340 typeClass = context.loadClass(type);
341 addInjections (context, descriptor, node, jndiName, typeClass);
342 }
343 }
344 break;
345 }
346 case WebFragment:
347 {
348
349 throw new IllegalStateException("Conflicting resource-env-ref "+jndiName+" in "+descriptor.getResource());
350 }
351 }
352 }
353
354
355
356
357
358
359
360
361
362
363 public void visitMessageDestinationRef (WebAppContext context, Descriptor descriptor, XmlParser.Node node)
364 throws Exception
365 {
366 String jndiName = node.getString("message-destination-ref-name",false,true);
367 String type = node.getString("message-destination-type",false,true);
368 String usage = node.getString("message-destination-usage",false,true);
369
370 Origin o = context.getMetaData().getOrigin("message-destination-ref."+jndiName);
371 switch (o)
372 {
373 case NotSet:
374 {
375
376 Class<?> typeClass = TypeUtil.fromName(type);
377 if (typeClass==null)
378 typeClass = context.loadClass(type);
379 addInjections(context, descriptor, node, jndiName, typeClass);
380 bindMessageDestinationRef(context,jndiName, typeClass);
381 context.getMetaData().setOrigin("message-destination-ref."+jndiName, descriptor);
382 break;
383 }
384 case WebXml:
385 case WebDefaults:
386 case WebOverride:
387 {
388
389
390 if (!(descriptor instanceof FragmentDescriptor))
391 {
392 Class<?> typeClass = TypeUtil.fromName(type);
393 if (typeClass==null)
394 typeClass = context.loadClass(type);
395 addInjections(context, descriptor, node, jndiName, typeClass);
396 bindMessageDestinationRef(context,jndiName, typeClass);
397 context.getMetaData().setOrigin("message-destination-ref."+jndiName, descriptor);
398 }
399 else
400 {
401
402
403 Descriptor d = context.getMetaData().getOriginDescriptor("message-destination-ref."+jndiName+".injection");
404 if (d == null || d instanceof FragmentDescriptor)
405 {
406 Class<?> typeClass = TypeUtil.fromName(type);
407 if (typeClass==null)
408 typeClass = context.loadClass(type);
409 addInjections(context, descriptor, node, jndiName, typeClass);
410 }
411 }
412 break;
413 }
414 case WebFragment:
415 {
416
417 throw new IllegalStateException("Conflicting message-destination-ref "+jndiName+" in "+descriptor.getResource());
418 }
419 }
420
421 }
422
423
424
425
426
427
428
429
430
431
432
433
434 public void visitPostConstruct(WebAppContext context, Descriptor descriptor, XmlParser.Node node)
435 {
436 String className = node.getString("lifecycle-callback-class", false, true);
437 String methodName = node.getString("lifecycle-callback-method", false, true);
438
439 if (className==null || className.equals(""))
440 {
441 Log.warn("No lifecycle-callback-class specified");
442 return;
443 }
444 if (methodName==null || methodName.equals(""))
445 {
446 Log.warn("No lifecycle-callback-method specified for class "+className);
447 return;
448 }
449
450
451
452 Origin o = context.getMetaData().getOrigin("post-construct");
453 switch (o)
454 {
455 case NotSet:
456 {
457
458 context.getMetaData().setOrigin("post-construct", descriptor);
459
460 try
461 {
462 Class<?> clazz = context.loadClass(className);
463 LifeCycleCallback callback = new PostConstructCallback();
464 callback.setTarget(clazz, methodName);
465 ((LifeCycleCallbackCollection)context.getAttribute(LifeCycleCallbackCollection.LIFECYCLE_CALLBACK_COLLECTION)).add(callback);
466 }
467 catch (ClassNotFoundException e)
468 {
469 Log.warn("Couldn't load post-construct target class "+className);
470 }
471 break;
472 }
473 case WebXml:
474 case WebDefaults:
475 case WebOverride:
476 {
477
478
479 if (!(descriptor instanceof FragmentDescriptor))
480 {
481 try
482 {
483 Class<?> clazz = context.loadClass(className);
484 LifeCycleCallback callback = new PostConstructCallback();
485 callback.setTarget(clazz, methodName);
486 ((LifeCycleCallbackCollection)context.getAttribute(LifeCycleCallbackCollection.LIFECYCLE_CALLBACK_COLLECTION)).add(callback);
487 }
488 catch (ClassNotFoundException e)
489 {
490 Log.warn("Couldn't load post-construct target class "+className);
491 }
492 }
493 break;
494 }
495 case WebFragment:
496 {
497
498 try
499 {
500 Class<?> clazz = context.loadClass(className);
501 LifeCycleCallback callback = new PostConstructCallback();
502 callback.setTarget(clazz, methodName);
503 ((LifeCycleCallbackCollection)context.getAttribute(LifeCycleCallbackCollection.LIFECYCLE_CALLBACK_COLLECTION)).add(callback);
504 }
505 catch (ClassNotFoundException e)
506 {
507 Log.warn("Couldn't load post-construct target class "+className);
508 }
509 break;
510 }
511 }
512
513 }
514
515
516
517
518
519
520
521
522 public void visitPreDestroy(WebAppContext context, Descriptor descriptor, XmlParser.Node node)
523 {
524 String className = node.getString("lifecycle-callback-class", false, true);
525 String methodName = node.getString("lifecycle-callback-method", false, true);
526 if (className==null || className.equals(""))
527 {
528 Log.warn("No lifecycle-callback-class specified for pre-destroy");
529 return;
530 }
531 if (methodName==null || methodName.equals(""))
532 {
533 Log.warn("No lifecycle-callback-method specified for pre-destroy class "+className);
534 return;
535 }
536
537 Origin o = context.getMetaData().getOrigin("pre-destroy");
538 switch(o)
539 {
540 case NotSet:
541 {
542
543
544 context.getMetaData().setOrigin("pre-destroy", descriptor);
545 try
546 {
547 Class<?> clazz = context.loadClass(className);
548 LifeCycleCallback callback = new PreDestroyCallback();
549 callback.setTarget(clazz, methodName);
550 ((LifeCycleCallbackCollection)context.getAttribute(LifeCycleCallbackCollection.LIFECYCLE_CALLBACK_COLLECTION)).add(callback);
551 }
552 catch (ClassNotFoundException e)
553 {
554 Log.warn("Couldn't load pre-destory target class "+className);
555 }
556 break;
557 }
558 case WebXml:
559 case WebDefaults:
560 case WebOverride:
561 {
562
563
564 if (!(descriptor instanceof FragmentDescriptor))
565 {
566 try
567 {
568 Class<?> clazz = context.loadClass(className);
569 LifeCycleCallback callback = new PreDestroyCallback();
570 callback.setTarget(clazz, methodName);
571 ((LifeCycleCallbackCollection)context.getAttribute(LifeCycleCallbackCollection.LIFECYCLE_CALLBACK_COLLECTION)).add(callback);
572 }
573 catch (ClassNotFoundException e)
574 {
575 Log.warn("Couldn't load pre-destory target class "+className);
576 }
577 }
578 break;
579 }
580 case WebFragment:
581 {
582
583 try
584 {
585 Class<?> clazz = context.loadClass(className);
586 LifeCycleCallback callback = new PreDestroyCallback();
587 callback.setTarget(clazz, methodName);
588 ((LifeCycleCallbackCollection)context.getAttribute(LifeCycleCallbackCollection.LIFECYCLE_CALLBACK_COLLECTION)).add(callback);
589 }
590 catch (ClassNotFoundException e)
591 {
592 Log.warn("Couldn't load pre-destory target class "+className);
593 }
594 break;
595 }
596 }
597 }
598
599
600
601
602
603
604
605
606
607
608
609 public void addInjections (WebAppContext context, Descriptor descriptor, XmlParser.Node node, String jndiName, Class<?> valueClass)
610 {
611 Iterator itor = node.iterator("injection-target");
612
613 while(itor.hasNext())
614 {
615 XmlParser.Node injectionNode = (XmlParser.Node)itor.next();
616 String targetClassName = injectionNode.getString("injection-target-class", false, true);
617 String targetName = injectionNode.getString("injection-target-name", false, true);
618 if ((targetClassName==null) || targetClassName.equals(""))
619 {
620 Log.warn("No classname found in injection-target");
621 continue;
622 }
623 if ((targetName==null) || targetName.equals(""))
624 {
625 Log.warn("No field or method name in injection-target");
626 continue;
627 }
628
629 InjectionCollection injections = (InjectionCollection)context.getAttribute(InjectionCollection.INJECTION_COLLECTION);
630 if (injections == null)
631 {
632 injections = new InjectionCollection();
633 context.setAttribute(InjectionCollection.INJECTION_COLLECTION, injections);
634 }
635
636
637 try
638 {
639 Class<?> clazz = context.loadClass(targetClassName);
640 Injection injection = new Injection();
641 injection.setJndiName(jndiName);
642 injection.setTarget(clazz, targetName, valueClass);
643 injections.add(injection);
644
645
646 if (context.getMetaData().getOriginDescriptor(node.getTag()+"."+jndiName+".injection") == null)
647 context.getMetaData().setOrigin(node.getTag()+"."+jndiName+".injection", descriptor);
648 }
649 catch (ClassNotFoundException e)
650 {
651 Log.warn("Couldn't load injection target class "+targetClassName);
652 }
653 }
654 }
655
656
657
658
659
660
661
662
663
664
665 public void bindEnvEntry(String name, Object value) throws Exception
666 {
667 InitialContext ic = null;
668 boolean bound = false;
669
670
671
672 ic = new InitialContext();
673 try
674 {
675 NamingEntry ne = (NamingEntry)ic.lookup("java:comp/env/"+NamingEntryUtil.makeNamingEntryName(ic.getNameParser(""), name));
676 if (ne!=null && ne instanceof EnvEntry)
677 {
678 EnvEntry ee = (EnvEntry)ne;
679 bound = ee.isOverrideWebXml();
680 }
681 }
682 catch (NameNotFoundException e)
683 {
684 bound = false;
685 }
686
687 if (!bound)
688 {
689
690 Context envCtx = (Context)ic.lookup("java:comp/env");
691 NamingUtil.bind(envCtx, name, value);
692 }
693 }
694
695
696
697
698
699
700
701
702
703
704
705 public void bindResourceRef(WebAppContext context, String name, Class<?> typeClass)
706 throws Exception
707 {
708 bindEntry(context, name, typeClass);
709 }
710
711
712
713
714
715
716 public void bindResourceEnvRef(WebAppContext context, String name, Class<?> typeClass)
717 throws Exception
718 {
719 bindEntry(context, name, typeClass);
720 }
721
722
723 public void bindMessageDestinationRef(WebAppContext context, String name, Class<?> typeClass)
724 throws Exception
725 {
726 bindEntry(context, name, typeClass);
727 }
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745 protected void bindEntry (WebAppContext context, String name, Class<?> typeClass)
746 throws Exception
747 {
748 String nameInEnvironment = name;
749 boolean bound = false;
750
751
752
753 Object scope = context;
754 NamingEntry ne = NamingEntryUtil.lookupNamingEntry(scope, name);
755
756 if (ne!=null && (ne instanceof Link))
757 {
758
759 nameInEnvironment = (String)((Link)ne).getObjectToBind();
760 Link l = (Link)ne;
761 }
762
763
764 scope = context;
765 bound = NamingEntryUtil.bindToENC(scope, name, nameInEnvironment);
766
767 if (bound)
768 return;
769
770
771 scope = context.getServer();
772 bound = NamingEntryUtil.bindToENC(scope, name, nameInEnvironment);
773 if (bound)
774 return;
775
776
777 bound = NamingEntryUtil.bindToENC(null, name, nameInEnvironment);
778 if (bound)
779 return;
780
781
782
783
784 nameInEnvironment = typeClass.getName()+"/default";
785
786 NamingEntry defaultNE = NamingEntryUtil.lookupNamingEntry(context.getServer(), nameInEnvironment);
787 if (defaultNE==null)
788 defaultNE = NamingEntryUtil.lookupNamingEntry(null, nameInEnvironment);
789
790 if (defaultNE!=null)
791 defaultNE.bindToENC(name);
792 else
793 throw new IllegalStateException("Nothing to bind for name "+nameInEnvironment);
794 }
795
796
797 }