View Javadoc
1   /*
2    * Copyright (c) 2011-2024 PrimeFaces Extensions
3    *
4    *  Permission is hereby granted, free of charge, to any person obtaining a copy
5    *  of this software and associated documentation files (the "Software"), to deal
6    *  in the Software without restriction, including without limitation the rights
7    *  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8    *  copies of the Software, and to permit persons to whom the Software is
9    *  furnished to do so, subject to the following conditions:
10   *
11   *  The above copyright notice and this permission notice shall be included in
12   *  all copies or substantial portions of the Software.
13   *
14   *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15   *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16   *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17   *  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18   *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19   *  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20   *  THE SOFTWARE.
21   */
22  package org.primefaces.extensions.component.remotecommand;
23  
24  import java.lang.reflect.InvocationTargetException;
25  import java.lang.reflect.Method;
26  
27  import javax.el.MethodExpression;
28  import javax.faces.view.facelets.*;
29  
30  import org.primefaces.extensions.component.parameters.MethodParameter;
31  import org.primefaces.extensions.component.parameters.MethodSignatureTagHandler;
32  
33  /**
34   * {@link ComponentHandler} for the {@link RemoteCommand} component.
35   *
36   * @author Thomas Andraschko / last modified by $Author$
37   * @version $Revision$
38   * @since 0.5
39   */
40  public class RemoteCommandHandler extends ComponentHandler {
41  
42      /**
43       * {@link MetaRule} for the <code>actionListener</code> of the {@link RemoteCommand}. This extra {@link MetaRule} is required if {@link MethodParameter}s
44       * are used.
45       *
46       * @author Thomas Andraschko / last modified by $Author$
47       * @version $Revision$
48       */
49      private static final class RemoteCommandMetaRule extends MetaRule {
50  
51          private final Class<?>[] parameters;
52  
53          public RemoteCommandMetaRule(final Class<?>[] parameters) {
54              this.parameters = parameters;
55          }
56  
57          @Override
58          public Metadata applyRule(final String name, final TagAttribute attribute, final MetadataTarget meta) {
59              if (meta.isTargetInstanceOf(RemoteCommand.class) && RemoteCommand.PropertyKeys.actionListener.toString().equals(name)) {
60                  final Method method = meta.getWriteMethod("actionListenerMethodExpression");
61  
62                  return new ActionListenerMetadata(attribute, method, parameters);
63              }
64  
65              return null;
66          }
67      }
68  
69      /**
70       * {@link Metadata} for the <code>actionListener</code> of the {@link RemoteCommand}. This extra {@link Metadata} is required if {@link MethodParameter}s
71       * are used.
72       *
73       * @author Thomas Andraschko / last modified by $Author$
74       * @version $Revision$
75       */
76      private static final class ActionListenerMetadata extends Metadata {
77  
78          private final TagAttribute attribute;
79          private final Method method;
80          private final Class<?>[] parameters;
81  
82          public ActionListenerMetadata(final TagAttribute attribute, final Method method, final Class<?>[] parameters) {
83              this.attribute = attribute;
84              this.method = method;
85              this.parameters = parameters;
86          }
87  
88          @Override
89          public void applyMetadata(final FaceletContext context, final Object instance) {
90              final MethodExpression expression = attribute.getMethodExpression(context, null, parameters);
91  
92              // invoke setAction with MethodExpression
93              try {
94                  method.invoke(instance, expression);
95              }
96              catch (final InvocationTargetException e) {
97                  throw new TagAttributeException(attribute, e.getCause());
98              }
99              catch (final Exception e) {
100                 throw new TagAttributeException(attribute, e);
101             }
102         }
103     }
104 
105     public RemoteCommandHandler(final ComponentConfig config) {
106         super(config);
107     }
108 
109     @Override
110     protected MetaRuleset createMetaRuleset(final Class type) {
111         final MetaRuleset metaRuleset = super.createMetaRuleset(type);
112         metaRuleset.addRule(new RemoteCommandMetaRule(getParameterTypes()));
113 
114         return metaRuleset;
115     }
116 
117     private Class<?>[] getParameterTypes() {
118         // try to get next MethodSignatureTagHandler
119         MethodSignatureTagHandler signatureTagHandler = null;
120 
121         if (nextHandler instanceof CompositeFaceletHandler) {
122             final CompositeFaceletHandler handler = (CompositeFaceletHandler) nextHandler;
123             if (handler.getHandlers().length > 0 && handler.getHandlers()[0] instanceof MethodSignatureTagHandler) {
124                 signatureTagHandler = (MethodSignatureTagHandler) handler.getHandlers()[0];
125             }
126         }
127 
128         if (signatureTagHandler == null) {
129             return new Class<?>[] {};
130         }
131 
132         return signatureTagHandler.getParameterTypes();
133     }
134 }