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