Source code: org/apache/struts/taglib/tiles/InsertTag.java
1 /*
2 * $Id: InsertTag.java 54929 2004-10-16 16:38:42Z germuska $
3 *
4 * Copyright 1999-2004 The Apache Software Foundation.
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 */
18
19 package org.apache.struts.taglib.tiles;
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.taglib.tiles.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: 54929 $ $Date: 2004-10-16 09:38:42 -0700 (Sat, 16 Oct 2004) $
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 /* JSP Tag attributes */
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 /* Internal properties */
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 // pageContext = null; // orion doesn't set it between two tags
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 // Check role
324 HttpServletRequest request =
325 (HttpServletRequest) pageContext.getRequest();
326 String role = nestedTag.getRole();
327 if (role != null && !request.isUserInRole(role)) {
328 // not allowed : skip attribute
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 // Check role
343 HttpServletRequest request =
344 (HttpServletRequest) pageContext.getRequest();
345 String role = nestedTag.getRole();
346 if (role != null && !request.isUserInRole(role)) {
347 // not allowed : skip attribute
348 return;
349 }
350
351 // Check if a name is defined
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 // now add attribute to enclosing parent (i.e. : this object).
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 // Check role
366 HttpServletRequest request =
367 (HttpServletRequest) pageContext.getRequest();
368 String role = nestedTag.getRole();
369 if (role != null && !request.isUserInRole(role)) {
370 // not allowed : skip attribute
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.getMessage());
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 // Check role immediatly to avoid useless stuff.
424 // In case of insertion of a "definition", definition's role still checked later.
425 // This lead to a double check of "role" ;-(
426 HttpServletRequest request =
427 (HttpServletRequest) pageContext.getRequest();
428 if (role != null && !request.isUserInRole(role)) {
429 processEndTag = false;
430 return SKIP_BODY;
431 }
432
433 try {
434 tagHandler = createTagHandler();
435
436 } catch (JspException e) {
437 if (isErrorIgnored) {
438 processEndTag = false;
439 return SKIP_BODY;
440 } else {
441 throw e;
442 }
443 }
444
445 return tagHandler.doStartTag();
446 }
447
448 /**
449 * Process the end tag by including the template.
450 * Simply call the handler doEndTag
451 */
452 public int doEndTag() throws JspException {
453 if (!processEndTag) {
454 releaseInternal();
455 return EVAL_PAGE;
456 }
457
458 int res = tagHandler.doEndTag();
459 // Reset properties used by object, in order to be able to reuse object.
460 releaseInternal();
461 return res;
462 }
463
464 /**
465 * Process tag attribute and create corresponding tag handler.
466 */
467 public TagHandler createTagHandler() throws JspException {
468 // Check each tag attribute.
469 // page Url attribute must be the last checked because it can appears concurrently
470 // with others attributes.
471 if (definitionName != null) {
472 return processDefinitionName(definitionName);
473 } else if (attribute != null) {
474 return processAttribute(attribute);
475 } else if (beanName != null) {
476 return processBean(beanName, beanProperty, beanScope);
477 } else if (name != null) {
478 return processName(name);
479 } else if (page != null) {
480 return processUrl(page);
481 } else {
482 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");
483 }
484 }
485
486 /**
487 * Process an object retrieved as a bean or attribute.
488 * Object can be a typed attribute, a String, or anything else.
489 * If typed attribute, use associated type.
490 * Otherwise, apply toString() on object, and use returned string as a name.
491 * @throws JspException - Throws by underlying nested call to
492 * processDefinitionName()
493 */
494 public TagHandler processObjectValue(Object value) throws JspException {
495 // First, check if value is one of the Typed Attribute
496 if (value instanceof AttributeDefinition) {
497 // We have a type => return appropriate IncludeType
498 return processTypedAttribute((AttributeDefinition) value);
499
500 } else if (value instanceof ComponentDefinition) {
501 return processDefinition((ComponentDefinition) value);
502 }
503
504 // Value must denote a valid String
505 return processAsDefinitionOrURL(value.toString());
506 }
507
508 /**
509 * Process name.
510 * Search in following order :
511 * <ul>
512 * <li>Component context - if found, process it as value.</li>
513 * <li>definitions factory</li>
514 * <li>URL</li>
515 * <li></li>
516 * </ul>
517 *
518 * @return appropriate tag handler.
519 * @throws JspException - Throws by underlying nested call to
520 * processDefinitionName()
521 */
522 public TagHandler processName(String name) throws JspException {
523 Object attrValue = getCurrentContext().getAttribute(name);
524
525 if (attrValue != null) {
526 return processObjectValue(attrValue);
527 }
528
529 return processAsDefinitionOrURL(name);
530 }
531
532 /**
533 * Process the url.
534 * @throws JspException If failed to create controller
535 */
536 public TagHandler processUrl(String url) throws JspException {
537 return new InsertHandler(url, role, getController());
538 }
539
540 /**
541 * Process tag attribute "definition".
542 * First, search definition in the factory, then create handler from this definition.
543 * @param name Name of the definition.
544 * @return Appropriate TagHandler.
545 * @throws JspException- NoSuchDefinitionException No Definition found for name.
546 * @throws JspException- FactoryNotFoundException Can't find Definitions factory.
547 * @throws JspException- DefinedComponentFactoryException General error in factory.
548 * @throws JspException InstantiationException Can't create requested controller
549 */
550 protected TagHandler processDefinitionName(String name)
551 throws JspException {
552
553 try {
554 ComponentDefinition definition =
555 TilesUtil.getDefinition(
556 name,
557 (HttpServletRequest) pageContext.getRequest(),
558 pageContext.getServletContext());
559
560 if (definition == null) { // is it possible ?
561 throw new NoSuchDefinitionException();
562 }
563
564 return processDefinition(definition);
565
566 } catch (NoSuchDefinitionException ex) {
567 throw new JspException(
568 "Error - Tag Insert : Can't get definition '"
569 + definitionName
570 + "'. Check if this name exist in definitions factory.");
571
572 } catch (FactoryNotFoundException ex) {
573 throw new JspException(ex.getMessage());
574
575 } catch (DefinitionsFactoryException ex) {
576 if (log.isDebugEnabled()) {
577 ex.printStackTrace();
578 }
579
580 // Save exception to be able to show it later
581 pageContext.setAttribute(
582 Globals.EXCEPTION_KEY,
583 ex,
584 PageContext.REQUEST_SCOPE);
585 throw new JspException(ex.getMessage());
586 }
587 }
588
589 /**
590 * End of Process tag attribute "definition".
591 * Overload definition with tag attributes "template" and "role".
592 * Then, create appropriate tag handler.
593 * @param definition Definition to process.
594 * @return Appropriate TagHandler.
595 * @throws JspException InstantiationException Can't create requested controller
596 */
597 protected TagHandler processDefinition(ComponentDefinition definition)
598 throws JspException {
599 // Declare local variable in order to not change Tag attribute values.
600 String role = this.role;
601 String page = this.page;
602 Controller controller = null;
603
604 try {
605 controller = definition.getOrCreateController();
606
607 // Overload definition with tag's template and role.
608 if (role == null) {
609 role = definition.getRole();
610 }
611
612 if (page == null) {
613 page = definition.getTemplate();
614 }
615
616 if (controllerName != null) {
617 controller =
618 ComponentDefinition.createController(
619 controllerName,
620 controllerType);
621 }
622
623 // Can check if page is set
624 return new InsertHandler(
625 definition.getAttributes(),
626 page,
627 role,
628 controller);
629
630 } catch (InstantiationException ex) {
631 throw new JspException(ex.getMessage());
632 }
633 }
634
635 /**
636 * Process a bean.
637 * Get bean value, eventually using property and scope. Found value is process by processObjectValue().
638 * @param beanName Name of the bean
639 * @param beanProperty Property in the bean, or null.
640 * @param beanScope bean scope, or null.
641 * @return Appropriate TagHandler.
642 * @throws JspException - NoSuchDefinitionException No value associated to bean.
643 * @throws JspException an error occur while reading bean, or no definition found.
644 * @throws JspException - Throws by underlying nested call to processDefinitionName()
645 */
646 protected TagHandler processBean(
647 String beanName,
648 String beanProperty,
649 String beanScope)
650 throws JspException {
651
652 Object beanValue =
653 TagUtils.getRealValueFromBean(
654 beanName,
655 beanProperty,
656 beanScope,
657 pageContext);
658
659 if (beanValue == null) {
660 throw new JspException(
661 "Error - Tag Insert : No value defined for bean '"
662 + beanName
663 + "' with property '"
664 + beanProperty
665 + "' in scope '"
666 + beanScope
667 + "'.");
668 }
669
670 return processObjectValue(beanValue);
671 }
672
673 /**
674 * Process tag attribute "attribute".
675 * Get value from component attribute.
676 * Found value is process by processObjectValue().
677 * @param name Name of the attribute.
678 * @return Appropriate TagHandler.
679 * @throws JspException - NoSuchDefinitionException No Definition found for name.
680 * @throws JspException - Throws by underlying nested call to processDefinitionName()
681 */
682 public TagHandler processAttribute(String name) throws JspException {
683 Object attrValue = getCurrentContext().getAttribute(name);
684
685 if (attrValue == null) {
686 throw new JspException(
687 "Error - Tag Insert : No value found for attribute '"
688 + name
689 + "'.");
690 }
691
692 return processObjectValue(attrValue);
693 }
694
695 /**
696 * Try to process name as a definition, or as an URL if not found.
697 * @param name Name to process.
698 * @return appropriate TagHandler
699 * @throws JspException InstantiationException Can't create requested controller
700 */
701 public TagHandler processAsDefinitionOrURL(String name)
702 throws JspException {
703 try {
704 ComponentDefinition definition =
705 TilesUtil.getDefinition(
706 name,
707 pageContext.getRequest(),
708 pageContext.getServletContext());
709
710 if (definition != null) {
711 return processDefinition(definition);
712 }
713
714 } catch (DefinitionsFactoryException ex) {
715 // silently failed, because we can choose to not define a factory.
716 }
717
718 // no definition found, try as url
719 return processUrl(name);
720 }
721
722 /**
723 * Process typed attribute according to its type.
724 * @param value Typed attribute to process.
725 * @return appropriate TagHandler.
726 * @throws JspException - Throws by underlying nested call to processDefinitionName()
727 */
728 public TagHandler processTypedAttribute(AttributeDefinition value)
729 throws JspException {
730 if (value instanceof DirectStringAttribute) {
731 return new DirectStringHandler((String) value.getValue());
732
733 } else if (value instanceof DefinitionAttribute) {
734 return processDefinition((ComponentDefinition) value.getValue());
735
736 } else if (value instanceof DefinitionNameAttribute) {
737 return processDefinitionName((String) value.getValue());
738 }
739
740 return new InsertHandler(
741 (String) value.getValue(),
742 role,
743 getController());
744 }
745
746 /**
747 * Do an include of specified page.
748 * This method is used internally to do all includes from this class. It delegates
749 * the include call to the TilesUtil.doInclude().
750 * @param page The page that will be included
751 * @throws ServletException - Thrown by call to pageContext.include()
752 * @throws IOException - Thrown by call to pageContext.include()
753 */
754 protected void doInclude(String page)
755 throws ServletException, IOException {
756 TilesUtil.doInclude(page, pageContext);
757 }
758
759 /////////////////////////////////////////////////////////////////////////////
760
761 /**
762 * Inner Interface.
763 * Sub handler for tag.
764 */
765 protected interface TagHandler {
766 /**
767 * Create ComponentContext for type depicted by implementation class.
768 */
769 public int doStartTag() throws JspException;
770 /**
771 * Do include for type depicted by implementation class.
772 */
773 public int doEndTag() throws JspException;
774 /**
775 * Add a component parameter (attribute) to subContext.
776 */
777 public void putAttribute(String name, Object value);
778 } // end inner interface
779
780 /////////////////////////////////////////////////////////////////////////////
781
782 /**
783 * Real handler, after attribute resolution.
784 * Handle include sub-component.
785 */
786 protected class InsertHandler implements TagHandler {
787 protected String page;
788 protected ComponentContext currentContext;
789 protected ComponentContext subCompContext;
790 protected String role;
791 protected Controller controller;
792
793 /**
794 * Constructor.
795 * Create insert handler using Component definition.
796 */
797 public InsertHandler(
798 Map attributes,
799 String page,
800 String role,
801 Controller controller) {
802
803 this.page = page;
804 this.role = role;
805 this.controller = controller;
806 subCompContext = new ComponentContext(attributes);
807 }
808
809 /**
810 * Constructor.
811 * Create insert handler to insert page at specified location.
812 */
813 public InsertHandler(String page, String role, Controller controller) {
814 this.page = page;
815 this.role = role;
816 this.controller = controller;
817 subCompContext = new ComponentContext();
818 }
819
820 /**
821 * Create a new empty context.
822 */
823 public int doStartTag() throws JspException {
824 // Check role
825 HttpServletRequest request =
826 (HttpServletRequest) pageContext.getRequest();
827
828 if (role != null && !request.isUserInRole(role)) {
829 return SKIP_BODY;
830 }
831
832 // save current context
833 this.currentContext = getCurrentContext();
834 return EVAL_BODY_INCLUDE;
835 }
836
837 /**
838 * Add attribute to sub context.
839 * Do nothing.
840 */
841 public void putAttribute(String name, Object value) {
842 subCompContext.putAttribute(name, value);
843 }
844
845 /**
846 * Include requested page.
847 */
848 public int doEndTag() throws JspException {
849 // Check role
850 HttpServletRequest request =
851 (HttpServletRequest) pageContext.getRequest();
852
853 if (role != null && !request.isUserInRole(role)) {
854 return EVAL_PAGE;
855 }
856
857 try {
858 if (log.isDebugEnabled()) {
859 log.debug("insert page='" + page + "'.");
860 }
861
862 // set new context for included component.
863 pageContext.setAttribute(
864 ComponentConstants.COMPONENT_CONTEXT,
865 subCompContext,
866 PageContext.REQUEST_SCOPE);
867
868 // Call controller if any
869 if (controller != null) {
870 try {
871 controller.execute(
872 subCompContext,
873 (HttpServletRequest) pageContext.getRequest(),
874 (HttpServletResponse) pageContext.getResponse(),
875 pageContext.getServletContext());
876
877 } catch (Exception e) {
878 throw new ServletException(e);
879 }
880
881 }
882
883 // include requested component.
884 if (flush) {
885 pageContext.getOut().flush();
886 }
887
888 doInclude(page);
889
890 } catch (IOException e) {
891 String msg =
892 "Can't insert page '" + page + "' : " + e.getMessage();
893 log.error(msg, e);
894 throw new JspException(msg);
895
896 } catch (IllegalArgumentException e) {
897 // Can't resolve page uri, should we ignore it?
898 if (!(page == null && isErrorIgnored)) {
899 String msg =
900 "Can't insert page '"
901 + page
902 + "'. Check if it exists.\n"
903 + e.getMessage();
904
905 log.error(msg, e);
906 throw new JspException(msg);
907 }
908
909 } catch (ServletException e) {
910 Throwable cause = e;
911 if (e.getRootCause() != null) {
912 cause = e.getRootCause();
913 }
914
915 String msg =
916 "ServletException in '" + page + "': " + cause.getMessage();
917
918 log.error(msg, e);
919 throw new JspException(msg);
920
921 } finally {
922 // restore old context only if currentContext not null
923 // (bug with Silverstream ?; related by Arvindra Sehmi 20010712)
924 if (currentContext != null) {
925 pageContext.setAttribute(
926 ComponentConstants.COMPONENT_CONTEXT,
927 currentContext,
928 PageContext.REQUEST_SCOPE);
929 }
930 }
931
932 return EVAL_PAGE;
933 }
934
935 /**
936 * Process an exception.
937 * Depending of debug attribute, print full exception trace or only
938 * its message in output page.
939 * @param ex Exception
940 * @param msg An additional message to show in console and to propagate if we can't output exception.
941 * @deprecated This method will be removed in a release after Struts 1.2.
942 */
943 protected void processException(Throwable ex, String msg)
944 throws JspException {
945
946 try {
947 if (msg == null) {
948 msg = ex.getMessage();
949 }
950
951 if (log.isDebugEnabled()) { // show full trace
952 log.debug(msg, ex);
953 pageContext.getOut().println(msg);
954 ex.printStackTrace(
955 new PrintWriter(pageContext.getOut(), true));
956 } else { // show only message
957 pageContext.getOut().println(msg);
958 }
959
960 } catch (IOException ioex) { // problems. Propagate original exception
961 pageContext.setAttribute(
962 ComponentConstants.EXCEPTION_KEY,
963 ex,
964 PageContext.REQUEST_SCOPE);
965 throw new JspException(msg);
966 }
967 }
968 }
969
970 /**
971 * Parse the list of roles and return <code>true</code> or <code>false</code> based on whether
972 * the user has that role or not.
973 * @param role Comma-delimited list of roles.
974 * @param request The request.
975 */
976 static public boolean userHasRole(
977 HttpServletRequest request,
978 String role) {
979 StringTokenizer st = new StringTokenizer(role, ",");
980 while (st.hasMoreTokens()) {
981 if (request.isUserInRole(st.nextToken())) {
982 return true;
983 }
984 }
985
986 return false;
987 }
988
989 /////////////////////////////////////////////////////////////////////////////
990
991 /**
992 * Handle insert direct string.
993 */
994 protected class DirectStringHandler implements TagHandler {
995 /** Object to print as a direct string */
996 private Object value;
997
998 /**
999 * Constructor.
1000 */
1001 public DirectStringHandler(Object value) {
1002 this.value = value;
1003 }
1004
1005 /**
1006 * Do nothing, there is no context for a direct string.
1007 */
1008 public int doStartTag() throws JspException {
1009 return SKIP_BODY;
1010 }
1011
1012 /**
1013 * Add attribute to sub context.
1014 * Do nothing.
1015 */
1016 public void putAttribute(String name, Object value) {
1017 }
1018
1019 /**
1020 * Print String in page output stream.
1021 */
1022 public int doEndTag() throws JspException {
1023 try {
1024 if (flush) {
1025 pageContext.getOut().flush();
1026 }
1027
1028 pageContext.getOut().print(value);
1029
1030 } catch (IOException ex) {
1031 if (log.isDebugEnabled()) {
1032 log.debug("Can't write string '" + value + "' : ", ex);
1033 }
1034
1035 pageContext.setAttribute(
1036 ComponentConstants.EXCEPTION_KEY,
1037 ex,
1038 PageContext.REQUEST_SCOPE);
1039
1040 throw new JspException(
1041 "Can't write string '" + value + "' : " + ex.getMessage());
1042 }
1043
1044 return EVAL_PAGE;
1045 }
1046 }
1047}