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 * This is the tag handler for <tiles:insert>, which includes
53 * a template. The tag's body content consists of <tiles:put>
54 * tags, which are accessed by <tiles:get> in the template.
55 *
56 * @version $Rev: 471754 $ $Date: 2006-11-06 08:55:09 -0600 (Mon, 06 Nov 2006) $
57 */
58 public class InsertTag
59 extends DefinitionTagSupport
60 implements PutTagParent, ComponentConstants, PutListTagParent {
61
62 /**
63 * The role delimiter.
64 * @deprecated This will be removed in a release after Struts 1.2.
65 */
66 public static final String ROLE_DELIMITER = ",";
67
68 /**
69 * Commons Logging instance.
70 */
71 protected static Log log = LogFactory.getLog(InsertTag.class);
72
73
74
75 /**
76 * Flush attribute value.
77 */
78 protected boolean flush = true;
79
80 /**
81 * Name to insert.
82 */
83 protected String name = null;
84
85 /**
86 * Name of attribute from which to read page name to include.
87 */
88 protected String attribute = null;
89
90 /**
91 * Name of bean used as entity to include.
92 */
93 protected String beanName = null;
94
95 /**
96 * Name of bean property, if any.
97 */
98 protected String beanProperty = null;
99
100 /**
101 * Scope of bean, if any.
102 */
103 protected String beanScope = null;
104
105 /**
106 * Are errors ignored. This is the property for attribute 'ignore'.
107 * Default value is false, which throw an exception.
108 * Only 'attribute not found' errors are ignored.
109 */
110 protected boolean isErrorIgnored = false;
111
112 /**
113 * Name of component instance to include.
114 */
115 protected String definitionName = null;
116
117
118 /**
119 * Does the end tag need to be processed.
120 * Default value is true. Boolean set in case of ignored errors.
121 */
122 protected boolean processEndTag = true;
123
124 /**
125 * Current component context.
126 */
127 protected ComponentContext cachedCurrentContext;
128
129 /**
130 * Final handler of tag methods.
131 */
132 protected TagHandler tagHandler = null;
133
134 /**
135 * Trick to allows inner classes to access pageContext.
136 */
137 protected PageContext pageContext = null;
138
139 /**
140 * Reset member values for reuse. This method calls super.release(),
141 * which invokes TagSupport.release(), which typically does nothing.
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 * Reset internal member values for reuse.
163 */
164 protected void releaseInternal() {
165 cachedCurrentContext = null;
166 processEndTag = true;
167
168 tagHandler = null;
169 }
170
171 /**
172 * Set the current page context.
173 * Called by the page implementation prior to doStartTag().
174 * <p>
175 * Needed to allow inner classes to access pageContext.
176 */
177 public void setPageContext(PageContext pc) {
178 this.pageContext = pc;
179 super.setPageContext(pc);
180 }
181
182 /**
183 * Get the pageContext property.
184 */
185 public PageContext getPageContext() {
186 return pageContext;
187 }
188
189 /**
190 * Set name.
191 */
192 public void setName(String value) {
193 this.name = value;
194 }
195
196 /**
197 * Get name.
198 */
199 public String getName() {
200 return name;
201 }
202
203 /**
204 * Set component.
205 */
206 public void setComponent(String name) {
207 this.page = name;
208 }
209
210 /**
211 * Set definition.
212 */
213 public void setDefinition(String name) {
214 this.definitionName = name;
215 }
216
217 /**
218 * Get definition name.
219 */
220 public String getDefinitionName() {
221 return definitionName;
222 }
223
224 /**
225 * Set attribute.
226 */
227 public void setAttribute(String value) {
228 this.attribute = value;
229 }
230
231 /**
232 * Set bean name.
233 */
234 public void setBeanName(String value) {
235 this.beanName = value;
236 }
237
238 /**
239 * Get bean name.
240 */
241 public String getBeanName() {
242 return beanName;
243 }
244
245 /**
246 * Set bean property.
247 */
248 public void setBeanProperty(String value) {
249 this.beanProperty = value;
250 }
251
252 /**
253 * Get bean property.
254 */
255 public String getBeanProperty() {
256 return beanProperty;
257 }
258
259 /**
260 * Set bean scope.
261 */
262 public void setBeanScope(String value) {
263 this.beanScope = value;
264 }
265
266 /**
267 * Get bean scope.
268 */
269 public String getBeanScope() {
270 return beanScope;
271 }
272
273 /**
274 * Set flush.
275 */
276 public void setFlush(boolean flush) {
277 this.flush = flush;
278 }
279
280 /**
281 * Get flush.
282 */
283 public boolean getFlush() {
284 return flush;
285 }
286
287 /**
288 * Set flush.
289 * Method added for compatibility with JSP1.1
290 */
291 public void setFlush(String flush) {
292 this.flush = (Boolean.valueOf(flush).booleanValue());
293 }
294
295 /**
296 * Set ignore.
297 */
298 public void setIgnore(boolean ignore) {
299 this.isErrorIgnored = ignore;
300 }
301
302 /**
303 * Get ignore.
304 */
305 public boolean getIgnore() {
306 return isErrorIgnored;
307 }
308
309
310
311 /**
312 * Add a body attribute.
313 * Erase any attribute with same name previously set.
314 */
315 public void putAttribute(String name, Object value) {
316 tagHandler.putAttribute(name, value);
317 }
318
319 /**
320 * Process nested ≶put> tag.
321 * Method calls by nested ≶put> tags.
322 * Nested list is added to current list.
323 * If role is defined, it is checked immediately.
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 * Process nested ≶putList> tag.
340 * Method calls by nested ≶putList> tags.
341 * Nested list is added to sub-component attributes
342 * If role is defined, it is checked immediately.
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 * Method calls by nested ≶putList> tags.
365 * A new list is added to current insert object.
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 * Get current component context.
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 * Get instantiated Controller.
396 * Return controller denoted by controllerType, or <code>null</code> if controllerType
397 * is null.
398 * @throws JspException If controller can't be created.
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 * Process the start tag by checking tag's attributes and creating appropriate handler.
417 * Possible handlers :
418 * <ul>
419 * <li> URL
420 * <li> definition
421 * <li> direct String
422 * </ul>
423 * Handlers also contain sub-component context.
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 * Process the end tag by including the template.
457 * Simply call the handler doEndTag
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 * Process tag attribute and create corresponding tag handler.
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 * Process an object retrieved as a bean or attribute.
495 * Object can be a typed attribute, a String, or anything else.
496 * If typed attribute, use associated type.
497 * Otherwise, apply toString() on object, and use returned string as a name.
498 * @throws JspException - Throws by underlying nested call to
499 * processDefinitionName()
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 * Process name.
517 * Search in following order :
518 * <ul>
519 * <li>Component context - if found, process it as value.</li>
520 * <li>definitions factory</li>
521 * <li>URL</li>
522 * <li></li>
523 * </ul>
524 *
525 * @return appropriate tag handler.
526 * @throws JspException - Throws by underlying nested call to
527 * processDefinitionName()
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 * Process the url.
541 * @throws JspException If failed to create controller
542 */
543 public TagHandler processUrl(String url) throws JspException {
544 return new InsertHandler(url, role, getController());
545 }
546
547 /**
548 * Process tag attribute "definition".
549 * First, search definition in the factory, then create handler from this definition.
550 * @param name Name of the definition.
551 * @return Appropriate TagHandler.
552 * @throws JspException- NoSuchDefinitionException No Definition found for name.
553 * @throws JspException- FactoryNotFoundException Can't find Definitions factory.
554 * @throws JspException- DefinedComponentFactoryException General error in factory.
555 * @throws JspException InstantiationException Can't create requested controller
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 * End of Process tag attribute "definition".
598 * Overload definition with tag attributes "template" and "role".
599 * Then, create appropriate tag handler.
600 * @param definition Definition to process.
601 * @return Appropriate TagHandler.
602 * @throws JspException InstantiationException Can't create requested controller
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 * Process a bean.
644 * Get bean value, eventually using property and scope. Found value is process by processObjectValue().
645 * @param beanName Name of the bean
646 * @param beanProperty Property in the bean, or null.
647 * @param beanScope bean scope, or null.
648 * @return Appropriate TagHandler.
649 * @throws JspException - NoSuchDefinitionException No value associated to bean.
650 * @throws JspException an error occur while reading bean, or no definition found.
651 * @throws JspException - Throws by underlying nested call to processDefinitionName()
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 * Process tag attribute "attribute".
682 * Get value from component attribute.
683 * Found value is process by processObjectValue().
684 * @param name Name of the attribute.
685 * @return Appropriate TagHandler.
686 * @throws JspException - NoSuchDefinitionException No Definition found for name.
687 * @throws JspException - Throws by underlying nested call to processDefinitionName()
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 * Try to process name as a definition, or as an URL if not found.
704 * @param name Name to process.
705 * @return appropriate TagHandler
706 * @throws JspException InstantiationException Can't create requested controller
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 * Process typed attribute according to its type.
731 * @param value Typed attribute to process.
732 * @return appropriate TagHandler.
733 * @throws JspException - Throws by underlying nested call to processDefinitionName()
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 * Do an include of specified page.
755 * This method is used internally to do all includes from this class. It delegates
756 * the include call to the TilesUtil.doInclude().
757 * @param page The page that will be included
758 * @param flush If the writer should be flushed before the include
759 * @throws ServletException - Thrown by call to pageContext.include()
760 * @throws IOException - Thrown by call to pageContext.include()
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 * Inner Interface.
771 * Sub handler for tag.
772 */
773 protected interface TagHandler {
774 /**
775 * Create ComponentContext for type depicted by implementation class.
776 */
777 public int doStartTag() throws JspException;
778 /**
779 * Do include for type depicted by implementation class.
780 */
781 public int doEndTag() throws JspException;
782 /**
783 * Add a component parameter (attribute) to subContext.
784 */
785 public void putAttribute(String name, Object value);
786 }
787
788
789
790 /**
791 * Real handler, after attribute resolution.
792 * Handle include sub-component.
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 * Constructor.
803 * Create insert handler using Component definition.
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 * Constructor.
819 * Create insert handler to insert page at specified location.
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 * Create a new empty context.
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 * Add attribute to sub context.
847 * Do nothing.
848 */
849 public void putAttribute(String name, Object value) {
850 subCompContext.putAttribute(name, value);
851 }
852
853 /**
854 * Include requested page.
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 * Process an exception.
945 * Depending of debug attribute, print full exception trace or only
946 * its message in output page.
947 * @param ex Exception
948 * @param msg An additional message to show in console and to propagate if we can't output exception.
949 * @deprecated This method will be removed in a release after Struts 1.2.
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 * Parse the list of roles and return <code>true</code> or <code>false</code> based on whether
980 * the user has that role or not.
981 * @param role Comma-delimited list of roles.
982 * @param request The request.
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 * Handle insert direct string.
1001 */
1002 protected class DirectStringHandler implements TagHandler {
1003 /** Object to print as a direct string */
1004 private Object value;
1005
1006 /**
1007 * Constructor.
1008 */
1009 public DirectStringHandler(Object value) {
1010 this.value = value;
1011 }
1012
1013 /**
1014 * Do nothing, there is no context for a direct string.
1015 */
1016 public int doStartTag() throws JspException {
1017 return SKIP_BODY;
1018 }
1019
1020 /**
1021 * Add attribute to sub context.
1022 * Do nothing.
1023 */
1024 public void putAttribute(String name, Object value) {
1025 }
1026
1027 /**
1028 * Print String in page output stream.
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 }