View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  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,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.myfaces.view.facelets.tag;
20  
21  import java.io.FileNotFoundException;
22  import java.io.IOException;
23  import java.net.URL;
24  import java.util.Collection;
25  import java.util.HashMap;
26  import java.util.Map;
27  
28  import javax.el.ELException;
29  import javax.el.ValueExpression;
30  import javax.faces.FacesException;
31  import javax.faces.component.UIComponent;
32  import javax.faces.view.facelets.FaceletContext;
33  import javax.faces.view.facelets.FaceletException;
34  import javax.faces.view.facelets.TagAttribute;
35  import javax.faces.view.facelets.TagConfig;
36  import javax.faces.view.facelets.TagException;
37  import javax.faces.view.facelets.TagHandler;
38  
39  import org.apache.myfaces.view.facelets.AbstractFaceletContext;
40  import org.apache.myfaces.view.facelets.ELExpressionCacheMode;
41  import org.apache.myfaces.view.facelets.TemplateClient;
42  import org.apache.myfaces.view.facelets.TemplateContext;
43  import org.apache.myfaces.view.facelets.impl.TemplateContextImpl;
44  import org.apache.myfaces.view.facelets.tag.ui.DefineHandler;
45  
46  /**
47   * A Tag that is specified in a FaceletFile. Takes all attributes specified and sets them on the FaceletContext before
48   * including the targeted Facelet file.
49   * 
50   * @author Jacob Hookom
51   * @version $Id: UserTagHandler.java 1470662 2013-04-22 19:04:45Z lu4242 $
52   */
53  final class UserTagHandler extends TagHandler implements TemplateClient, ComponentContainerHandler
54  {
55  
56      protected final TagAttribute[] _vars;
57  
58      protected final URL _location;
59  
60      protected final Map<String, DefineHandler> _handlers;
61  
62      /**
63       * @param config
64       */
65      public UserTagHandler(TagConfig config, URL location)
66      {
67          super(config);
68          this._vars = this.tag.getAttributes().getAll();
69          this._location = location;
70          
71          Collection<DefineHandler> defines = TagHandlerUtils.findNextByType(nextHandler, DefineHandler.class);
72          if (defines.isEmpty())
73          {
74              _handlers = null;
75          }
76          else
77          {
78              _handlers = new HashMap<String, DefineHandler>();
79              for (DefineHandler handler : defines)
80              {
81                  _handlers.put(handler.getName(), handler);
82              }
83          }
84      }
85  
86      /**
87       * Iterate over all TagAttributes and set them on the FaceletContext's VariableMapper, then include the target
88       * Facelet. Finally, replace the old VariableMapper.
89       * 
90       * @see TagAttribute#getValueExpression(FaceletContext, Class)
91       * @see javax.el.VariableMapper
92       * @see javax.faces.view.facelets.FaceletHandler#apply(javax.faces.view.facelets.FaceletContext,
93       *        javax.faces.component.UIComponent)
94       */
95      public void apply(FaceletContext ctx, UIComponent parent) throws IOException, FacesException, FaceletException,
96              ELException
97      {
98          AbstractFaceletContext actx = (AbstractFaceletContext) ctx;
99          // eval include
100         try
101         {
102             String[] names = null;
103             ValueExpression[] values = null;
104             if (this._vars.length > 0)
105             {
106                 names = new String[_vars.length];
107                 values = new ValueExpression[_vars.length];
108                 for (int i = 0; i < _vars.length; i++)
109                 {
110                     names[i] = _vars[i].getLocalName();
111                     values[i] = _vars[i].getValueExpression(ctx, Object.class);
112                 }
113             }
114             actx.pushTemplateContext(new TemplateContextImpl());
115             actx.pushClient(this);
116             if (this._vars.length > 0)
117             {
118                 for (int i = 0; i < this._vars.length; i++)
119                 {
120                     ((AbstractFaceletContext) ctx).getTemplateContext().setParameter(names[i], values[i]);
121                 }
122             }
123             // Disable caching always, even in 'always' mode
124             // The only mode that can support EL caching in this condition is alwaysRedirect.
125             if (!ELExpressionCacheMode.alwaysRecompile.equals(actx.getELExpressionCacheMode()))
126             {
127                 actx.getTemplateContext().setAllowCacheELExpressions(false);
128             }
129             ctx.includeFacelet(parent, this._location);
130         }
131         catch (FileNotFoundException e)
132         {
133             throw new TagException(this.tag, e.getMessage());
134         }
135         finally
136         {
137 
138             // make sure we undo our changes
139             actx.popClient(this);
140             actx.popTemplateContext();
141             //ctx.setVariableMapper(orig);
142         }
143     }
144 
145     public boolean apply(FaceletContext ctx, UIComponent parent, String name) throws IOException, FacesException,
146             FaceletException, ELException
147     {
148         if (name != null)
149         {
150             if (this._handlers == null)
151             {
152                 return false;
153             }
154             DefineHandler handler = (DefineHandler) this._handlers.get(name);
155             if (handler != null)
156             {
157                 AbstractFaceletContext actx = (AbstractFaceletContext) ctx;
158                 TemplateContext itc = actx.popTemplateContext();
159                 try
160                 {
161                     handler.applyDefinition(ctx, parent);
162                 }
163                 finally
164                 {
165                     actx.pushTemplateContext(itc);
166                 }
167                 return true;
168             }
169             else
170             {
171                 return false;
172             }
173         }
174         else
175         {
176             AbstractFaceletContext actx = (AbstractFaceletContext) ctx;
177             TemplateContext itc = actx.popTemplateContext();
178             try
179             {
180                 this.nextHandler.apply(ctx, parent);
181             }
182             finally
183             {
184                 actx.pushTemplateContext(itc);
185             }
186             return true;
187         }
188     }
189 
190 }