1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 package org.apache.struts.tiles.taglib;
23
24 import java.io.IOException;
25 import java.io.PrintWriter;
26 import java.util.Map;
27 import java.util.StringTokenizer;
28
29 import javax.servlet.ServletException;
30 import javax.servlet.http.HttpServletRequest;
31 import javax.servlet.http.HttpServletResponse;
32 import javax.servlet.jsp.JspException;
33 import javax.servlet.jsp.PageContext;
34
35 import org.apache.commons.logging.Log;
36 import org.apache.commons.logging.LogFactory;
37 import org.apache.struts.Globals;
38 import org.apache.struts.tiles.taglib.util.TagUtils;
39 import org.apache.struts.tiles.AttributeDefinition;
40 import org.apache.struts.tiles.ComponentContext;
41 import org.apache.struts.tiles.ComponentDefinition;
42 import org.apache.struts.tiles.Controller;
43 import org.apache.struts.tiles.DefinitionAttribute;
44 import org.apache.struts.tiles.DefinitionNameAttribute;
45 import org.apache.struts.tiles.DefinitionsFactoryException;
46 import org.apache.struts.tiles.DirectStringAttribute;
47 import org.apache.struts.tiles.FactoryNotFoundException;
48 import org.apache.struts.tiles.NoSuchDefinitionException;
49 import org.apache.struts.tiles.TilesUtil;
50
51
52
53
54
55
56
57
58 public class InsertTag
59 extends DefinitionTagSupport
60 implements PutTagParent, ComponentConstants, PutListTagParent {
61
62
63
64
65
66 public static final String ROLE_DELIMITER = ",";
67
68
69
70
71 protected static Log log = LogFactory.getLog(InsertTag.class);
72
73
74
75
76
77
78 protected boolean flush = true;
79
80
81
82
83 protected String name = null;
84
85
86
87
88 protected String attribute = null;
89
90
91
92
93 protected String beanName = null;
94
95
96
97
98 protected String beanProperty = null;
99
100
101
102
103 protected String beanScope = null;
104
105
106
107
108
109
110 protected boolean isErrorIgnored = false;
111
112
113
114
115 protected String definitionName = null;
116
117
118
119
120
121
122 protected boolean processEndTag = true;
123
124
125
126
127 protected ComponentContext cachedCurrentContext;
128
129
130
131
132 protected TagHandler tagHandler = null;
133
134
135
136
137 protected PageContext pageContext = null;
138
139
140
141
142
143 public void release() {
144
145 super.release();
146 attribute = null;
147 beanName = null;
148 beanProperty = null;
149 beanScope = null;
150
151 definitionName = null;
152 flush = true;
153 name = null;
154 page = null;
155 role = null;
156 isErrorIgnored = false;
157
158 releaseInternal();
159 }
160
161
162
163
164 protected void releaseInternal() {
165 cachedCurrentContext = null;
166 processEndTag = true;
167
168 tagHandler = null;
169 }
170
171
172
173
174
175
176
177 public void setPageContext(PageContext pc) {
178 this.pageContext = pc;
179 super.setPageContext(pc);
180 }
181
182
183
184
185 public PageContext getPageContext() {
186 return pageContext;
187 }
188
189
190
191
192 public void setName(String value) {
193 this.name = value;
194 }
195
196
197
198
199 public String getName() {
200 return name;
201 }
202
203
204
205
206 public void setComponent(String name) {
207 this.page = name;
208 }
209
210
211
212
213 public void setDefinition(String name) {
214 this.definitionName = name;
215 }
216
217
218
219
220 public String getDefinitionName() {
221 return definitionName;
222 }
223
224
225
226
227 public void setAttribute(String value) {
228 this.attribute = value;
229 }
230
231
232
233
234 public void setBeanName(String value) {
235 this.beanName = value;
236 }
237
238
239
240
241 public String getBeanName() {
242 return beanName;
243 }
244
245
246
247
248 public void setBeanProperty(String value) {
249 this.beanProperty = value;
250 }
251
252
253
254
255 public String getBeanProperty() {
256 return beanProperty;
257 }
258
259
260
261
262 public void setBeanScope(String value) {
263 this.beanScope = value;
264 }
265
266
267
268
269 public String getBeanScope() {
270 return beanScope;
271 }
272
273
274
275
276 public void setFlush(boolean flush) {
277 this.flush = flush;
278 }
279
280
281
282
283 public boolean getFlush() {
284 return flush;
285 }
286
287
288
289
290
291 public void setFlush(String flush) {
292 this.flush = (Boolean.valueOf(flush).booleanValue());
293 }
294
295
296
297
298 public void setIgnore(boolean ignore) {
299 this.isErrorIgnored = ignore;
300 }
301
302
303
304
305 public boolean getIgnore() {
306 return isErrorIgnored;
307 }
308
309
310
311
312
313
314
315 public void putAttribute(String name, Object value) {
316 tagHandler.putAttribute(name, value);
317 }
318
319
320
321
322
323
324
325 public void processNestedTag(PutTag nestedTag) throws JspException {
326
327 HttpServletRequest request =
328 (HttpServletRequest) pageContext.getRequest();
329 String role = nestedTag.getRole();
330 if (role != null && !request.isUserInRole(role)) {
331
332 return;
333 }
334
335 putAttribute(nestedTag.getName(), nestedTag.getRealValue());
336 }
337
338
339
340
341
342
343
344 public void processNestedTag(PutListTag nestedTag) throws JspException {
345
346 HttpServletRequest request =
347 (HttpServletRequest) pageContext.getRequest();
348 String role = nestedTag.getRole();
349 if (role != null && !request.isUserInRole(role)) {
350
351 return;
352 }
353
354
355 if (nestedTag.getName() == null) {
356 throw new JspException("Error - PutList : attribute name is not defined. It is mandatory as the list is added as attribute of 'insert'.");
357 }
358
359
360 putAttribute(nestedTag.getName(), nestedTag.getList());
361 }
362
363
364
365
366
367 public void putAttribute(PutListTag nestedTag) throws JspException {
368
369 HttpServletRequest request =
370 (HttpServletRequest) pageContext.getRequest();
371 String role = nestedTag.getRole();
372 if (role != null && !request.isUserInRole(role)) {
373
374 return;
375 }
376
377 putAttribute(nestedTag.getName(), nestedTag.getList());
378 }
379
380
381
382
383 private ComponentContext getCurrentContext() {
384 if (cachedCurrentContext == null) {
385 cachedCurrentContext =
386 (ComponentContext) pageContext.getAttribute(
387 ComponentConstants.COMPONENT_CONTEXT,
388 PageContext.REQUEST_SCOPE);
389 }
390
391 return cachedCurrentContext;
392 }
393
394
395
396
397
398
399
400 private Controller getController() throws JspException {
401 if (controllerType == null) {
402 return null;
403 }
404
405 try {
406 return ComponentDefinition.createController(
407 controllerName,
408 controllerType);
409
410 } catch (InstantiationException ex) {
411 throw new JspException(ex);
412 }
413 }
414
415
416
417
418
419
420
421
422
423
424
425 public int doStartTag() throws JspException {
426
427
428 cachedCurrentContext = null;
429
430
431
432
433 HttpServletRequest request =
434 (HttpServletRequest) pageContext.getRequest();
435 if (role != null && !request.isUserInRole(role)) {
436 processEndTag = false;
437 return SKIP_BODY;
438 }
439
440 try {
441 tagHandler = createTagHandler();
442
443 } catch (JspException e) {
444 if (isErrorIgnored) {
445 processEndTag = false;
446 return SKIP_BODY;
447 } else {
448 throw e;
449 }
450 }
451
452 return tagHandler.doStartTag();
453 }
454
455
456
457
458
459 public int doEndTag() throws JspException {
460 if (!processEndTag) {
461 releaseInternal();
462 return EVAL_PAGE;
463 }
464
465 int res = tagHandler.doEndTag();
466
467 releaseInternal();
468 return res;
469 }
470
471
472
473
474 public TagHandler createTagHandler() throws JspException {
475
476
477
478 if (definitionName != null) {
479 return processDefinitionName(definitionName);
480 } else if (attribute != null) {
481 return processAttribute(attribute);
482 } else if (beanName != null) {
483 return processBean(beanName, beanProperty, beanScope);
484 } else if (name != null) {
485 return processName(name);
486 } else if (page != null) {
487 return processUrl(page);
488 } else {
489 throw new JspException("Error - Tag Insert : At least one of the following attribute must be defined : template|page|attribute|definition|name|beanName. Check tag syntax");
490 }
491 }
492
493
494
495
496
497
498
499
500
501 public TagHandler processObjectValue(Object value) throws JspException {
502
503 if (value instanceof AttributeDefinition) {
504
505 return processTypedAttribute((AttributeDefinition) value);
506
507 } else if (value instanceof ComponentDefinition) {
508 return processDefinition((ComponentDefinition) value);
509 }
510
511
512 return processAsDefinitionOrURL(value.toString());
513 }
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529 public TagHandler processName(String name) throws JspException {
530 Object attrValue = getCurrentContext().getAttribute(name);
531
532 if (attrValue != null) {
533 return processObjectValue(attrValue);
534 }
535
536 return processAsDefinitionOrURL(name);
537 }
538
539
540
541
542
543 public TagHandler processUrl(String url) throws JspException {
544 return new InsertHandler(url, role, getController());
545 }
546
547
548
549
550
551
552
553
554
555
556
557 protected TagHandler processDefinitionName(String name)
558 throws JspException {
559
560 try {
561 ComponentDefinition definition =
562 TilesUtil.getDefinition(
563 name,
564 (HttpServletRequest) pageContext.getRequest(),
565 pageContext.getServletContext());
566
567 if (definition == null) {
568 throw new NoSuchDefinitionException();
569 }
570
571 return processDefinition(definition);
572
573 } catch (NoSuchDefinitionException ex) {
574 throw new JspException(
575 "Error - Tag Insert : Can't get definition '"
576 + definitionName
577 + "'. Check if this name exist in definitions factory.", ex);
578
579 } catch (FactoryNotFoundException ex) {
580 throw new JspException(ex.getMessage());
581
582 } catch (DefinitionsFactoryException ex) {
583 if (log.isDebugEnabled()) {
584 ex.printStackTrace();
585 }
586
587
588 pageContext.setAttribute(
589 Globals.EXCEPTION_KEY,
590 ex,
591 PageContext.REQUEST_SCOPE);
592 throw new JspException(ex);
593 }
594 }
595
596
597
598
599
600
601
602
603
604 protected TagHandler processDefinition(ComponentDefinition definition)
605 throws JspException {
606
607 String role = this.role;
608 String page = this.page;
609 Controller controller = null;
610
611 try {
612 controller = definition.getOrCreateController();
613
614
615 if (role == null) {
616 role = definition.getRole();
617 }
618
619 if (page == null) {
620 page = definition.getTemplate();
621 }
622
623 if (controllerName != null) {
624 controller =
625 ComponentDefinition.createController(
626 controllerName,
627 controllerType);
628 }
629
630
631 return new InsertHandler(
632 definition.getAttributes(),
633 page,
634 role,
635 controller);
636
637 } catch (InstantiationException ex) {
638 throw new JspException(ex);
639 }
640 }
641
642
643
644
645
646
647
648
649
650
651
652
653 protected TagHandler processBean(
654 String beanName,
655 String beanProperty,
656 String beanScope)
657 throws JspException {
658
659 Object beanValue =
660 TagUtils.getRealValueFromBean(
661 beanName,
662 beanProperty,
663 beanScope,
664 pageContext);
665
666 if (beanValue == null) {
667 throw new JspException(
668 "Error - Tag Insert : No value defined for bean '"
669 + beanName
670 + "' with property '"
671 + beanProperty
672 + "' in scope '"
673 + beanScope
674 + "'.");
675 }
676
677 return processObjectValue(beanValue);
678 }
679
680
681
682
683
684
685
686
687
688
689 public TagHandler processAttribute(String name) throws JspException {
690 Object attrValue = getCurrentContext().getAttribute(name);
691
692 if (attrValue == null) {
693 throw new JspException(
694 "Error - Tag Insert : No value found for attribute '"
695 + name
696 + "'.");
697 }
698
699 return processObjectValue(attrValue);
700 }
701
702
703
704
705
706
707
708 public TagHandler processAsDefinitionOrURL(String name)
709 throws JspException {
710 try {
711 ComponentDefinition definition =
712 TilesUtil.getDefinition(
713 name,
714 pageContext.getRequest(),
715 pageContext.getServletContext());
716
717 if (definition != null) {
718 return processDefinition(definition);
719 }
720
721 } catch (DefinitionsFactoryException ex) {
722
723 }
724
725
726 return processUrl(name);
727 }
728
729
730
731
732
733
734
735 public TagHandler processTypedAttribute(AttributeDefinition value)
736 throws JspException {
737 if (value instanceof DirectStringAttribute) {
738 return new DirectStringHandler((String) value.getValue());
739
740 } else if (value instanceof DefinitionAttribute) {
741 return processDefinition((ComponentDefinition) value.getValue());
742
743 } else if (value instanceof DefinitionNameAttribute) {
744 return processDefinitionName((String) value.getValue());
745 }
746
747 return new InsertHandler(
748 (String) value.getValue(),
749 role,
750 getController());
751 }
752
753
754
755
756
757
758
759
760
761
762 protected void doInclude(String page, boolean flush)
763 throws ServletException, IOException {
764 TilesUtil.doInclude(page, pageContext, flush);
765 }
766
767
768
769
770
771
772
773 protected interface TagHandler {
774
775
776
777 public int doStartTag() throws JspException;
778
779
780
781 public int doEndTag() throws JspException;
782
783
784
785 public void putAttribute(String name, Object value);
786 }
787
788
789
790
791
792
793
794 protected class InsertHandler implements TagHandler {
795 protected String page;
796 protected ComponentContext currentContext;
797 protected ComponentContext subCompContext;
798 protected String role;
799 protected Controller controller;
800
801
802
803
804
805 public InsertHandler(
806 Map attributes,
807 String page,
808 String role,
809 Controller controller) {
810
811 this.page = page;
812 this.role = role;
813 this.controller = controller;
814 subCompContext = new ComponentContext(attributes);
815 }
816
817
818
819
820
821 public InsertHandler(String page, String role, Controller controller) {
822 this.page = page;
823 this.role = role;
824 this.controller = controller;
825 subCompContext = new ComponentContext();
826 }
827
828
829
830
831 public int doStartTag() throws JspException {
832
833 HttpServletRequest request =
834 (HttpServletRequest) pageContext.getRequest();
835
836 if (role != null && !request.isUserInRole(role)) {
837 return SKIP_BODY;
838 }
839
840
841 this.currentContext = getCurrentContext();
842 return EVAL_BODY_INCLUDE;
843 }
844
845
846
847
848
849 public void putAttribute(String name, Object value) {
850 subCompContext.putAttribute(name, value);
851 }
852
853
854
855
856 public int doEndTag() throws JspException {
857
858 HttpServletRequest request =
859 (HttpServletRequest) pageContext.getRequest();
860
861 if (role != null && !request.isUserInRole(role)) {
862 return EVAL_PAGE;
863 }
864
865 try {
866 if (log.isDebugEnabled()) {
867 log.debug("insert page='" + page + "'.");
868 }
869
870
871 pageContext.setAttribute(
872 ComponentConstants.COMPONENT_CONTEXT,
873 subCompContext,
874 PageContext.REQUEST_SCOPE);
875
876
877 if (controller != null) {
878 try {
879 controller.execute(
880 subCompContext,
881 (HttpServletRequest) pageContext.getRequest(),
882 (HttpServletResponse) pageContext.getResponse(),
883 pageContext.getServletContext());
884
885 } catch (Exception e) {
886 throw new ServletException(e);
887 }
888
889 }
890
891
892 if (flush) {
893 pageContext.getOut().flush();
894 }
895
896 doInclude(page, flush);
897
898 } catch (IOException e) {
899 String msg =
900 "Can't insert page '" + page + "' : " + e.getMessage();
901 log.error(msg, e);
902 throw new JspException(msg);
903
904 } catch (IllegalArgumentException e) {
905
906 if (!(page == null && isErrorIgnored)) {
907 String msg =
908 "Can't insert page '"
909 + page
910 + "'. Check if it exists.\n"
911 + e.getMessage();
912
913 log.error(msg, e);
914 throw new JspException(msg,e);
915 }
916
917 } catch (ServletException e) {
918 Throwable cause = e;
919 if (e.getRootCause() != null) {
920 cause = e.getRootCause();
921 }
922
923 String msg =
924 "ServletException in '" + page + "': " + cause.getMessage();
925
926 log.error(msg, e);
927 throw new JspException(msg,e);
928
929 } finally {
930
931
932 if (currentContext != null) {
933 pageContext.setAttribute(
934 ComponentConstants.COMPONENT_CONTEXT,
935 currentContext,
936 PageContext.REQUEST_SCOPE);
937 }
938 }
939
940 return EVAL_PAGE;
941 }
942
943
944
945
946
947
948
949
950
951 protected void processException(Throwable ex, String msg)
952 throws JspException {
953
954 try {
955 if (msg == null) {
956 msg = ex.getMessage();
957 }
958
959 if (log.isDebugEnabled()) {
960 log.debug(msg, ex);
961 pageContext.getOut().println(msg);
962 ex.printStackTrace(
963 new PrintWriter(pageContext.getOut(), true));
964 } else {
965 pageContext.getOut().println(msg);
966 }
967
968 } catch (IOException ioex) {
969 pageContext.setAttribute(
970 ComponentConstants.EXCEPTION_KEY,
971 ex,
972 PageContext.REQUEST_SCOPE);
973 throw new JspException(msg,ioex);
974 }
975 }
976 }
977
978
979
980
981
982
983
984 static public boolean userHasRole(
985 HttpServletRequest request,
986 String role) {
987 StringTokenizer st = new StringTokenizer(role, ",");
988 while (st.hasMoreTokens()) {
989 if (request.isUserInRole(st.nextToken())) {
990 return true;
991 }
992 }
993
994 return false;
995 }
996
997
998
999
1000
1001
1002 protected class DirectStringHandler implements TagHandler {
1003
1004 private Object value;
1005
1006
1007
1008
1009 public DirectStringHandler(Object value) {
1010 this.value = value;
1011 }
1012
1013
1014
1015
1016 public int doStartTag() throws JspException {
1017 return SKIP_BODY;
1018 }
1019
1020
1021
1022
1023
1024 public void putAttribute(String name, Object value) {
1025 }
1026
1027
1028
1029
1030 public int doEndTag() throws JspException {
1031 try {
1032 if (flush) {
1033 pageContext.getOut().flush();
1034 }
1035
1036 pageContext.getOut().print(value);
1037
1038 } catch (IOException ex) {
1039 if (log.isDebugEnabled()) {
1040 log.debug("Can't write string '" + value + "' : ", ex);
1041 }
1042
1043 pageContext.setAttribute(
1044 ComponentConstants.EXCEPTION_KEY,
1045 ex,
1046 PageContext.REQUEST_SCOPE);
1047
1048 throw new JspException(
1049 "Can't write string '" + value + "' : " + ex.getMessage(), ex);
1050 }
1051
1052 return EVAL_PAGE;
1053 }
1054 }
1055 }