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  import org.apache.myfaces.util.ExternalSpecifications;
39  
40  import org.apache.myfaces.view.facelets.AbstractFaceletContext;
41  import org.apache.myfaces.view.facelets.ELExpressionCacheMode;
42  import org.apache.myfaces.view.facelets.FaceletCompositionContext;
43  import org.apache.myfaces.view.facelets.TemplateClient;
44  import org.apache.myfaces.view.facelets.TemplateContext;
45  import org.apache.myfaces.view.facelets.el.FaceletStateValueExpression;
46  import org.apache.myfaces.view.facelets.el.FaceletStateValueExpressionUEL;
47  import org.apache.myfaces.view.facelets.impl.TemplateContextImpl;
48  import org.apache.myfaces.view.facelets.tag.jsf.ComponentSupport;
49  import org.apache.myfaces.view.facelets.tag.jsf.FaceletState;
50  import org.apache.myfaces.view.facelets.tag.ui.DefineHandler;
51  
52  /**
53   * A Tag that is specified in a FaceletFile. Takes all attributes specified and sets them on the FaceletContext before
54   * including the targeted Facelet file.
55   * 
56   * @author Jacob Hookom
57   * @version $Id$
58   */
59  final class UserTagHandler extends TagHandler implements TemplateClient, ComponentContainerHandler
60  {
61  
62      protected final TagAttribute[] _vars;
63  
64      protected final URL _location;
65  
66      protected final Map<String, DefineHandler> _handlers;
67  
68      /**
69       * @param config
70       */
71      public UserTagHandler(TagConfig config, URL location)
72      {
73          super(config);
74          this._vars = this.tag.getAttributes().getAll();
75          this._location = location;
76          
77          Collection<DefineHandler> defines = TagHandlerUtils.findNextByType(nextHandler, DefineHandler.class);
78          if (defines.isEmpty())
79          {
80              _handlers = null;
81          }
82          else
83          {
84              _handlers = new HashMap<String, DefineHandler>();
85              for (DefineHandler handler : defines)
86              {
87                  _handlers.put(handler.getName(), handler);
88              }
89          }
90      }
91  
92      /**
93       * Iterate over all TagAttributes and set them on the FaceletContext's VariableMapper, then include the target
94       * Facelet. Finally, replace the old VariableMapper.
95       * 
96       * @see TagAttribute#getValueExpression(FaceletContext, Class)
97       * @see javax.el.VariableMapper
98       * @see javax.faces.view.facelets.FaceletHandler#apply(javax.faces.view.facelets.FaceletContext,
99       *        javax.faces.component.UIComponent)
100      */
101     public void apply(FaceletContext ctx, UIComponent parent) throws IOException, FacesException, FaceletException,
102             ELException
103     {
104         AbstractFaceletContext actx = (AbstractFaceletContext) ctx;
105         // eval include
106         try
107         {
108             String[] names = null;
109             ValueExpression[] values = null;
110             if (this._vars.length > 0)
111             {
112                 names = new String[_vars.length];
113                 values = new ValueExpression[_vars.length];
114                 for (int i = 0; i < _vars.length; i++)
115                 {
116                     names[i] = _vars[i].getLocalName();
117                     values[i] = _vars[i].getValueExpression(ctx, Object.class);
118                 }
119             }
120             actx.pushTemplateContext(new TemplateContextImpl());
121             actx.pushClient(this);
122             FaceletCompositionContext fcc = FaceletCompositionContext.getCurrentInstance(ctx);
123             String uniqueId = fcc.startComponentUniqueIdSection();
124             try
125             {
126                 if (this._vars.length > 0)
127                 {
128                     if (ELExpressionCacheMode.alwaysRecompile.equals(actx.getELExpressionCacheMode()))
129                     {
130                         FaceletState faceletState = ComponentSupport.getFaceletState(ctx, parent, true);
131                         for (int i = 0; i < this._vars.length; i++)
132                         {
133                             //((AbstractFaceletContext) ctx).getTemplateContext().setParameter(names[i], values[i]);
134                             faceletState.putBinding(uniqueId, names[i], values[i]);
135                             ValueExpression ve;
136                             if (ExternalSpecifications.isUnifiedELAvailable())
137                             {
138                                 ve = new FaceletStateValueExpressionUEL(uniqueId, names[i]);
139                             }
140                             else
141                             {
142                                 ve = new FaceletStateValueExpression(uniqueId, names[i]);
143                             }
144                             actx.getTemplateContext().setParameter(names[i], ve);
145                         }
146                     }
147                     else
148                     {
149                         for (int i = 0; i < this._vars.length; i++)
150                         {
151                             ((AbstractFaceletContext) ctx).getTemplateContext().setParameter(names[i], values[i]);
152                         }
153                     }
154                 }
155                 // Disable caching always, even in 'always' mode
156                 // The only mode that can support EL caching in this condition is alwaysRedirect.
157                 if (!ELExpressionCacheMode.alwaysRecompile.equals(actx.getELExpressionCacheMode()))
158                 {
159                     actx.getTemplateContext().setAllowCacheELExpressions(false);
160                 }
161                 ctx.includeFacelet(parent, this._location);
162             }
163             finally
164             {
165                 fcc.endComponentUniqueIdSection();
166             }
167         }
168         catch (FileNotFoundException e)
169         {
170             throw new TagException(this.tag, e.getMessage());
171         }
172         finally
173         {
174 
175             // make sure we undo our changes
176             actx.popClient(this);
177             actx.popTemplateContext();
178             //ctx.setVariableMapper(orig);
179         }
180     }
181 
182     public boolean apply(FaceletContext ctx, UIComponent parent, String name) throws IOException, FacesException,
183             FaceletException, ELException
184     {
185         if (name != null)
186         {
187             if (this._handlers == null)
188             {
189                 return false;
190             }
191             DefineHandler handler = (DefineHandler) this._handlers.get(name);
192             if (handler != null)
193             {
194                 AbstractFaceletContext actx = (AbstractFaceletContext) ctx;
195                 TemplateContext itc = actx.popTemplateContext();
196                 try
197                 {
198                     handler.applyDefinition(ctx, parent);
199                 }
200                 finally
201                 {
202                     actx.pushTemplateContext(itc);
203                 }
204                 return true;
205             }
206             else
207             {
208                 return false;
209             }
210         }
211         else
212         {
213             AbstractFaceletContext actx = (AbstractFaceletContext) ctx;
214             TemplateContext itc = actx.popTemplateContext();
215             try
216             {
217                 this.nextHandler.apply(ctx, parent);
218             }
219             finally
220             {
221                 actx.pushTemplateContext(itc);
222             }
223             return true;
224         }
225     }
226 
227 }