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.custom.facelets.tag;
20  
21  import java.lang.reflect.InvocationTargetException;
22  import java.lang.reflect.Method;
23  
24  import javax.el.MethodExpression;
25  import javax.faces.el.MethodBinding;
26  import javax.faces.view.facelets.FaceletContext;
27  import javax.faces.view.facelets.MetaRule;
28  import javax.faces.view.facelets.Metadata;
29  import javax.faces.view.facelets.MetadataTarget;
30  import javax.faces.view.facelets.TagAttribute;
31  import javax.faces.view.facelets.TagAttributeException;
32  
33  /**
34   * Optional Rule for binding Method[Binding|Expression] properties
35   * 
36   * @author Mike Kienenberger
37   * @author Jacob Hookom
38   */
39  public final class MethodRule extends MetaRule
40  {
41  
42      private final String methodName;
43      
44      private final String propertyName;
45  
46      private final Class<?> returnTypeClass;
47  
48      private final Class<?>[] params;
49  
50      public MethodRule(String methodName, Class<?> returnTypeClass,
51              Class<?>[] params)
52      {
53          this.methodName = methodName;
54          this.propertyName = methodName;
55          this.returnTypeClass = returnTypeClass;
56          this.params = params;
57      }
58      
59      public MethodRule(String methodName, String propertyName, Class<?> returnTypeClass,
60              Class<?>[] params)
61      {
62          this.methodName = methodName;
63          this.propertyName = propertyName;
64          this.returnTypeClass = returnTypeClass;
65          this.params = params;
66      }
67  
68      public Metadata applyRule(String name, TagAttribute attribute,
69              MetadataTarget meta)
70      {
71          if (false == name.equals(this.methodName))
72              return null;
73  
74          if (MethodExpression.class.equals(meta.getPropertyType(propertyName)))
75          {
76              Method method = meta.getWriteMethod(propertyName);
77              if (method != null)
78              {
79                  return new MethodExpressionMetadata(method, attribute,
80                          this.returnTypeClass, this.params);
81              }
82          }
83          else if (MethodBinding.class.equals(meta.getPropertyType(propertyName)))
84          {
85              Method method = meta.getWriteMethod(propertyName);
86              if (method != null)
87              {
88                  return new MethodBindingMetadata(method, attribute,
89                          this.returnTypeClass, this.params);
90              }
91          }
92              
93          return null;
94      }
95  
96      private class MethodBindingMetadata extends Metadata
97      {
98          private final Method _method;
99  
100         private final TagAttribute _attribute;
101 
102         private Class[] _paramList;
103 
104         private Class _returnType;
105 
106         public MethodBindingMetadata(Method method, TagAttribute attribute,
107                 Class returnType, Class[] paramList)
108         {
109             _method = method;
110             _attribute = attribute;
111             _paramList = paramList;
112             _returnType = returnType;
113         }
114 
115         public void applyMetadata(FaceletContext ctx, Object instance)
116         {
117             MethodExpression expr = _attribute.getMethodExpression(ctx,
118                     _returnType, _paramList);
119 
120             try
121             {
122                 _method.invoke(instance,
123                         new Object[] { new LegacyMethodBinding(expr) });
124             }
125             catch (InvocationTargetException e)
126             {
127                 throw new TagAttributeException(_attribute, e.getCause());
128             }
129             catch (Exception e)
130             {
131                 throw new TagAttributeException(_attribute, e);
132             }
133         }
134     }
135 
136     private class MethodExpressionMetadata extends Metadata
137     {
138         private final Method _method;
139 
140         private final TagAttribute _attribute;
141 
142         private Class<?>[] _paramList;
143 
144         private Class<?> _returnType;
145 
146         public MethodExpressionMetadata(Method method, TagAttribute attribute,
147                 Class<?> returnType, Class<?>[] paramList)
148         {
149             _method = method;
150             _attribute = attribute;
151             _paramList = paramList;
152             _returnType = returnType;
153         }
154 
155         public void applyMetadata(FaceletContext ctx, Object instance)
156         {
157             MethodExpression expr = _attribute.getMethodExpression(ctx,
158                     _returnType, _paramList);
159 
160             try
161             {
162                 _method.invoke(instance, new Object[] { expr });
163             }
164             catch (InvocationTargetException e)
165             {
166                 throw new TagAttributeException(_attribute, e.getCause());
167             }
168             catch (Exception e)
169             {
170                 throw new TagAttributeException(_attribute, e);
171             }
172         }
173     }
174 }