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.jstl.core;
20  
21  import java.io.IOException;
22  
23  import javax.el.ELContext;
24  import javax.el.ELException;
25  import javax.el.ValueExpression;
26  import javax.faces.FacesException;
27  import javax.faces.component.UIComponent;
28  import javax.faces.view.facelets.FaceletContext;
29  import javax.faces.view.facelets.FaceletException;
30  import javax.faces.view.facelets.TagAttribute;
31  import javax.faces.view.facelets.TagConfig;
32  import javax.faces.view.facelets.TagException;
33  import javax.faces.view.facelets.TagHandler;
34  
35  import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFFaceletAttribute;
36  import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFFaceletTag;
37  import org.apache.myfaces.util.ExternalSpecifications;
38  import org.apache.myfaces.view.facelets.AbstractFaceletContext;
39  import org.apache.myfaces.view.facelets.ELExpressionCacheMode;
40  import org.apache.myfaces.view.facelets.el.CacheableValueExpressionUELWrapper;
41  import org.apache.myfaces.view.facelets.el.CacheableValueExpressionWrapper;
42  
43  /**
44   * Simplified implementation of c:set
45   * 
46   * Sets the result of an expression evaluation in a 'scope'
47   * 
48   * @author Jacob Hookom
49   * @version $Id$
50   */
51  @JSFFaceletTag(name="c:set")
52  public class SetHandler extends TagHandler
53  {
54  
55      /**
56       * Name of the exported scoped variable to hold the value
57       * specified in the action. The type of the scoped variable is
58       * whatever type the value expression evaluates to.
59       */
60      @JSFFaceletAttribute(className="java.lang.String")
61      private final TagAttribute var;
62  
63      /**
64       * Expression to be evaluated.
65       */
66      @JSFFaceletAttribute(
67              className="javax.el.ValueExpression",
68              deferredValueType="java.lang.Object")
69      private final TagAttribute value;
70  
71      @JSFFaceletAttribute(
72              name="scope",
73              className="java.lang.String",
74              longDescription="Scope for var.")
75      private final TagAttribute scope;
76  
77      @JSFFaceletAttribute(
78          name="target",
79          className="java.lang.String",
80          longDescription="Target object whose property will be set."+
81          " Must evaluate to a JavaBeans object with setter property"+
82          "property, or to a java.util.Map object.")
83      private final TagAttribute target;
84  
85      @JSFFaceletAttribute(
86          name="property",
87          className="java.lang.String",
88          longDescription="Name of the property to be set in the target object.")
89      private final TagAttribute property;
90  
91      public SetHandler(TagConfig config)
92      {
93          super(config);
94          this.value = this.getAttribute("value");
95          this.var = this.getAttribute("var");
96          this.scope = this.getAttribute("scope");
97          this.target = this.getAttribute("target");
98          this.property = this.getAttribute("property");
99      }
100 
101     public void apply(FaceletContext ctx, UIComponent parent) throws IOException, FacesException, FaceletException,
102             ELException
103     {
104         ValueExpression veObj = this.value.getValueExpression(ctx, Object.class);
105 
106         if (this.var != null)
107         {
108             // Get variable name
109             String varStr = this.var.getValue(ctx);
110 
111             if (this.scope != null)
112             {
113                 String scopeStr = this.scope.getValue(ctx);
114 
115                 // Check scope string
116                 if (scopeStr == null || scopeStr.length() == 0)
117                 {
118                     throw new TagException(tag, "scope must not be empty");
119                 }
120                 if ("page".equals(scopeStr))
121                 {
122                     throw new TagException(tag, "page scope is not allowed");
123                 }
124 
125                 // Build value expression string to set variable
126                 StringBuilder expStr = new StringBuilder().append("#{").append(scopeStr);
127                 if ("request".equals(scopeStr) || "view".equals(scopeStr) || "session".equals(scopeStr)
128                         || "application".equals(scopeStr))
129                 {
130                     expStr.append("Scope");
131                 }
132                 expStr.append(".").append(varStr).append("}");
133                 ELContext elCtx = ctx.getFacesContext().getELContext();
134                 ValueExpression expr = ctx.getExpressionFactory().createValueExpression(
135                         elCtx, expStr.toString(), Object.class);
136                 expr.setValue(elCtx, veObj.getValue(elCtx));
137             }
138             else
139             {
140                 //ctx.getVariableMapper().setVariable(varStr, veObj);
141                 AbstractFaceletContext actx = ((AbstractFaceletContext) ctx);
142                 if (ELExpressionCacheMode.alwaysRecompile.equals(actx.getELExpressionCacheMode()))
143                 {
144                     if (ExternalSpecifications.isUnifiedELAvailable())
145                     {
146                         actx.getPageContext().getAttributes().put(varStr, 
147                             new CacheableValueExpressionUELWrapper(veObj));
148                     }
149                     else
150                     {
151                         actx.getPageContext().getAttributes().put(varStr, 
152                             new CacheableValueExpressionWrapper(veObj));
153                     }
154                 }
155                 else
156                 {
157                     actx.getPageContext().getAttributes().put(varStr, veObj);
158                 }
159                 if (actx.getPageContext().isAllowCacheELExpressions())
160                 {
161                     if (ELExpressionCacheMode.strict.equals(actx.getELExpressionCacheMode()))
162                     {
163                         actx.getPageContext().setAllowCacheELExpressions(false);
164                     }
165                 }
166             }
167         }
168         else
169         {
170             // Check attributes
171             if (this.target == null || this.property == null || this.value == null)
172             {
173                 throw new TagException(
174                         tag, "either attributes var and value or target, property and value must be set");
175             }
176             if (this.target.isLiteral())
177             {
178                 throw new TagException(tag, "attribute target must contain a value expression");
179             }
180 
181             // Get target object and name of property to set
182             ELContext elCtx = ctx.getFacesContext().getELContext();
183             ValueExpression targetExpr = this.target.getValueExpression(ctx, Object.class);
184             Object targetObj = targetExpr.getValue(elCtx);
185             String propertyName = this.property.getValue(ctx);
186             // Set property on target object
187             ctx.getELResolver().setValue(elCtx, targetObj, propertyName, veObj.getValue(elCtx));
188         }
189     }
190 }