Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

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 &lg;put&gt; tag.
318    * Method calls by nested &lg;put&gt; 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 &lg;putList&gt; tag.
337    * Method calls by nested &lg;putList&gt; 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 &lg;putList&gt; 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}