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