Coverage Report - javax.faces.event.MethodExpressionActionListener
 
Classes in this File Line Coverage Branch Coverage Complexity
MethodExpressionActionListener
65%
30/46
10%
1/10
1.818
 
 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  
 
 20  
 package javax.faces.event;
 21  
 
 22  
 import javax.el.ELContext;
 23  
 import javax.el.ELException;
 24  
 import javax.el.ExpressionFactory;
 25  
 import javax.el.MethodExpression;
 26  
 import javax.el.MethodNotFoundException;
 27  
 import javax.faces.component.StateHolder;
 28  
 import javax.faces.context.FacesContext;
 29  
 
 30  
 /**
 31  
  * See Javadoc of
 32  
  * <a href=
 33  
  * "https://javaserverfaces.dev.java.net/nonav/docs/2.0/javadocs/javax/faces/event/MethodExpressionActionListener.html">
 34  
  * JSF Specification</a>
 35  
  */
 36  
 public class MethodExpressionActionListener implements ActionListener, StateHolder
 37  
 {
 38  
     
 39  2
     private static final Class<?>[] EMPTY_CLASS_ARRAY = new Class<?>[0];
 40  2
     private static final Object[] EMPTY_PARAMS = new Object[0];
 41  
     
 42  
     private MethodExpression methodExpressionOneArg;
 43  
     private MethodExpression methodExpressionZeroArg;
 44  14
     private boolean isTransient = false;
 45  
 
 46  
     /** Creates a new instance of MethodExpressionActionListener */
 47  
     public MethodExpressionActionListener()
 48  4
     {
 49  
         // constructor for state-saving 
 50  4
     }
 51  
 
 52  
     public MethodExpressionActionListener(MethodExpression methodExpressionOneArg)
 53  4
     {
 54  4
         this.methodExpressionOneArg = methodExpressionOneArg;
 55  
         
 56  4
         _createZeroArgsMethodExpression(methodExpressionOneArg); 
 57  4
     }
 58  
 
 59  
     public MethodExpressionActionListener(MethodExpression methodExpressionOneArg,
 60  
                                           MethodExpression methodExpressionZeroArg)
 61  6
     {
 62  6
         this.methodExpressionOneArg = methodExpressionOneArg;
 63  6
         if (methodExpressionZeroArg != null) 
 64  
         {
 65  6
             this.methodExpressionZeroArg = methodExpressionZeroArg;
 66  
         }
 67  
         else
 68  
         {
 69  0
             _createZeroArgsMethodExpression(methodExpressionOneArg);
 70  
         }
 71  6
     }
 72  
 
 73  
     public void processAction(ActionEvent actionEvent) throws AbortProcessingException
 74  
     {
 75  
         try
 76  
         {
 77  
             try
 78  
             {
 79  
                 // call to the one argument MethodExpression
 80  4
                 Object[] params = new Object[] { actionEvent };
 81  4
                 methodExpressionOneArg.invoke(getElContext(), params);
 82  
             }
 83  2
             catch (MethodNotFoundException mnfe)
 84  
             {
 85  
                 // call to the zero argument MethodExpression
 86  2
                 methodExpressionZeroArg.invoke(getElContext(), EMPTY_PARAMS);
 87  2
             }
 88  
         }
 89  0
         catch (ELException e)
 90  
         {
 91  
             // "... If that fails for any reason, throw an AbortProcessingException,
 92  
             // including the cause of the failure ..."
 93  
             // -= Leonardo Uribe =- after discussing this topic on MYFACES-3199, the conclusion is the part is an advice
 94  
             // for the developer implementing a listener in a method expressions that could be wrapped by this class.
 95  
             // The spec wording is poor but, to keep this coherently with ExceptionHandler API,
 96  
             // the spec and code on UIViewRoot we need:
 97  
             // 2a) "exception is instance of APE or any of the causes of the exception are an APE, 
 98  
             // DON'T publish ExceptionQueuedEvent and terminate processing for current event".
 99  
             // 2b) for any other exception publish ExceptionQueuedEvent and continue broadcast processing.
 100  0
             Throwable cause = e.getCause();
 101  0
             AbortProcessingException ape = null;
 102  0
             if (cause != null)
 103  
             {
 104  
                 do
 105  
                 {
 106  0
                     if (cause instanceof AbortProcessingException)
 107  
                     {
 108  0
                         ape = (AbortProcessingException) cause;
 109  0
                         break;
 110  
                     }
 111  0
                     cause = cause.getCause();
 112  
                 }
 113  0
                 while (cause != null);
 114  
             }
 115  
             
 116  0
             if (ape != null)
 117  
             {
 118  
                 // 2a) "exception is instance of APE or any of the causes of the exception are an APE, 
 119  
                 // DON'T publish ExceptionQueuedEvent and terminate processing for current event".
 120  
                 // To do this throw an AbortProcessingException here, later on UIViewRoot.broadcastAll,
 121  
                 // this exception will be received and stored to handle later.
 122  0
                 throw ape;
 123  
             }
 124  0
             throw e;
 125  
             //Throwable cause = e.getCause();
 126  
             //if (cause == null)
 127  
             //{
 128  
             //    cause = e;
 129  
             //}
 130  
             //if (cause instanceof AbortProcessingException)
 131  
             //{
 132  
             //    throw (AbortProcessingException) cause;
 133  
             //}
 134  
             //else
 135  
             //{
 136  
             //    throw new AbortProcessingException(cause);
 137  
             //}
 138  4
         }
 139  4
     }
 140  
     
 141  
     public void restoreState(FacesContext context, Object state)
 142  
     {
 143  2
         methodExpressionOneArg = (MethodExpression) ((Object[]) state)[0];
 144  2
         methodExpressionZeroArg = (MethodExpression) ((Object[]) state)[1];
 145  2
     }
 146  
 
 147  
     public Object saveState(FacesContext context)
 148  
     {
 149  2
         return new Object[] {methodExpressionOneArg, methodExpressionZeroArg};
 150  
     }
 151  
 
 152  
     public void setTransient(boolean newTransientValue)
 153  
     {
 154  0
         isTransient = newTransientValue;
 155  0
     }
 156  
 
 157  
     public boolean isTransient()
 158  
     {
 159  0
         return isTransient;
 160  
     }
 161  
     
 162  
     private ELContext getElContext()
 163  
     {
 164  10
         return getFacesContext().getELContext();
 165  
     }
 166  
     
 167  
     private FacesContext getFacesContext()
 168  
     {
 169  14
         return FacesContext.getCurrentInstance();
 170  
     }
 171  
     
 172  
     /**
 173  
      * Creates a {@link MethodExpression} with no params and with the same Expression as 
 174  
      * param <code>methodExpression</code>
 175  
      * <b>WARNING!</b> This method creates new {@link MethodExpression} with expressionFactory.createMethodExpression.
 176  
      * That means is not decorating MethodExpression passed as parameter -
 177  
      * support for EL VariableMapper will not be available!
 178  
      * This is a problem when using facelets and <ui:decorate/> with EL params (see MYFACES-2541 for details).
 179  
      */
 180  
     private void _createZeroArgsMethodExpression(MethodExpression methodExpression)
 181  
     {
 182  4
         ExpressionFactory expressionFactory = getFacesContext().getApplication().getExpressionFactory();
 183  
 
 184  4
         this.methodExpressionZeroArg = expressionFactory.createMethodExpression(getElContext(), 
 185  
                   methodExpression.getExpressionString(), Void.class, EMPTY_CLASS_ARRAY);
 186  4
     }
 187  
 
 188  
 }