Coverage Report - org.apache.myfaces.shared.context.ExceptionHandlerImpl
 
Classes in this File Line Coverage Branch Coverage Complexity
ExceptionHandlerImpl
0%
0/49
0%
0/36
3.182
 
 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.shared.context;
 20  
 
 21  
 import java.util.Collections;
 22  
 import java.util.LinkedList;
 23  
 import java.util.Queue;
 24  
 import java.util.logging.Level;
 25  
 import java.util.logging.Logger;
 26  
 
 27  
 import javax.el.ELException;
 28  
 import javax.faces.FacesException;
 29  
 import javax.faces.context.ExceptionHandler;
 30  
 import javax.faces.event.AbortProcessingException;
 31  
 import javax.faces.event.ExceptionQueuedEvent;
 32  
 import javax.faces.event.ExceptionQueuedEventContext;
 33  
 import javax.faces.event.SystemEvent;
 34  
 
 35  
 /**
 36  
  * DOCUMENT ME!
 37  
  * 
 38  
  * @since 2.0
 39  
  */
 40  
 public class ExceptionHandlerImpl extends ExceptionHandler
 41  
 {
 42  
     /*
 43  
      * PLEASE NOTE!!!
 44  
      * javax.faces.webapp.PreJsf2ExceptionHandlerFactory uses most parts of this implementation
 45  
      * for its private static inner class, only the handle method differs a bit.
 46  
      * Thus, any changes made here should also be applied to PreJsf2ExceptionHandlerFactory
 47  
      * in the right way (you can copy everything except handle(), this method needs special treatment).
 48  
      */
 49  
     
 50  0
     private static final Logger log = Logger.getLogger(ExceptionHandlerImpl.class.getName());
 51  
     
 52  
     private Queue<ExceptionQueuedEvent> handled;
 53  
     private Queue<ExceptionQueuedEvent> unhandled;
 54  
     private ExceptionQueuedEvent handledAndThrown;
 55  
 
 56  
     public ExceptionHandlerImpl()
 57  0
     {
 58  
         
 59  0
     }
 60  
     
 61  
     /**
 62  
      * {@inheritDoc}
 63  
      */
 64  
     @Override
 65  
     public ExceptionQueuedEvent getHandledExceptionQueuedEvent()
 66  
     {
 67  0
         return handledAndThrown;
 68  
     }
 69  
 
 70  
     /**
 71  
      * {@inheritDoc}
 72  
      */
 73  
     @Override
 74  
     public Iterable<ExceptionQueuedEvent> getHandledExceptionQueuedEvents()
 75  
     {
 76  0
         return handled == null ? Collections.<ExceptionQueuedEvent>emptyList() : handled;
 77  
     }
 78  
 
 79  
     /**
 80  
      * {@inheritDoc}
 81  
      */
 82  
     @Override
 83  
     public Throwable getRootCause(Throwable t)
 84  
     {
 85  0
         if (t == null)
 86  
         {
 87  0
             throw new NullPointerException("t");
 88  
         }
 89  
         
 90  0
         while (t != null)
 91  
         {
 92  0
             Class<?> clazz = t.getClass();
 93  0
             if (!clazz.equals(FacesException.class) && !clazz.equals(ELException.class))
 94  
             {
 95  0
                 return t;
 96  
             }
 97  
             
 98  0
             t = t.getCause();
 99  0
         }
 100  
         
 101  0
         return null;
 102  
     }
 103  
 
 104  
     /**
 105  
      * {@inheritDoc}
 106  
      */
 107  
     @Override
 108  
     public Iterable<ExceptionQueuedEvent> getUnhandledExceptionQueuedEvents()
 109  
     {
 110  0
         return unhandled == null ? Collections.<ExceptionQueuedEvent>emptyList() : unhandled;
 111  
     }
 112  
 
 113  
     /**
 114  
      * {@inheritDoc}
 115  
      */
 116  
     @Override
 117  
     public void handle() throws FacesException
 118  
     {
 119  0
         if (unhandled != null && !unhandled.isEmpty())
 120  
         {
 121  0
             if (handled == null)
 122  
             {
 123  0
                 handled = new LinkedList<ExceptionQueuedEvent>();
 124  
             }
 125  
             
 126  0
             FacesException toThrow = null;
 127  
             
 128  
             do
 129  
             {
 130  
                 // For each ExceptionEvent in the list
 131  
                 
 132  
                 // get the event to handle
 133  0
                 ExceptionQueuedEvent event = unhandled.peek();
 134  
                 try
 135  
                 {
 136  
                     // call its getContext() method
 137  0
                     ExceptionQueuedEventContext context = event.getContext();
 138  
                     
 139  
                     // and call getException() on the returned result
 140  0
                     Throwable exception = context.getException();
 141  
                     
 142  
                     // Upon encountering the first such Exception that is not an instance of
 143  
                     // javax.faces.event.AbortProcessingException
 144  0
                     if (!shouldSkip(exception))
 145  
                     {
 146  
                         // set handledAndThrown so that getHandledExceptionQueuedEvent() returns this event
 147  0
                         handledAndThrown = event;
 148  
                         
 149  
                         // Re-wrap toThrow in a ServletException or (PortletException, if in a portlet environment) 
 150  
                         // and throw it
 151  
                         // FIXME: The spec says to NOT use a FacesException to propagate the exception, but I see
 152  
                         //        no other way as ServletException is not a RuntimeException
 153  0
                         toThrow = wrap(getRethrownException(exception));
 154  
                         break;
 155  
                     }
 156  
                     else
 157  
                     {
 158  
                         // Testing mojarra it logs a message and the exception
 159  
                         // however, this behaviour is not mentioned in the spec
 160  0
                         log.log(Level.SEVERE, exception.getClass().getName() + " occured while processing " +
 161  
                                 (context.inBeforePhase() ? "beforePhase() of " : 
 162  
                                         (context.inAfterPhase() ? "afterPhase() of " : "")) + 
 163  
                                 "phase " + context.getPhaseId() + ": " +
 164  
                                 "UIComponent-ClientId=" + 
 165  
                                 (context.getComponent() != null ? 
 166  
                                         context.getComponent().getClientId(context.getContext()) : "") + ", " +
 167  
                                 "Message=" + exception.getMessage());
 168  
                         
 169  0
                         log.log(Level.SEVERE, exception.getMessage(), exception);
 170  
                         
 171  
                     }
 172  
                 }
 173  0
                 catch (Throwable t)
 174  
                 {
 175  
                     // A FacesException must be thrown if a problem occurs while performing
 176  
                     // the algorithm to handle the exception
 177  0
                     throw new FacesException("Could not perform the algorithm to handle the Exception", t);
 178  
                 }
 179  
                 finally
 180  
                 {
 181  
                     // if we will throw the Exception or if we just logged it,
 182  
                     // we handled it in either way --> add to handled
 183  0
                     handled.add(event);
 184  0
                     unhandled.remove(event);
 185  0
                 }
 186  0
             } while (!unhandled.isEmpty());
 187  
             
 188  
             // do we have to throw an Exception?
 189  0
             if (toThrow != null)
 190  
             {
 191  0
                 throw toThrow;
 192  
             }
 193  
         }
 194  0
     }
 195  
 
 196  
     /**
 197  
      * {@inheritDoc}
 198  
      */
 199  
     @Override
 200  
     public boolean isListenerForSource(Object source)
 201  
     {
 202  0
         return source instanceof ExceptionQueuedEventContext;
 203  
     }
 204  
 
 205  
     /**
 206  
      * {@inheritDoc}
 207  
      */
 208  
     @Override
 209  
     public void processEvent(SystemEvent exceptionQueuedEvent) throws AbortProcessingException
 210  
     {
 211  0
         if (unhandled == null)
 212  
         {
 213  0
             unhandled = new LinkedList<ExceptionQueuedEvent>();
 214  
         }
 215  
         
 216  0
         unhandled.add((ExceptionQueuedEvent)exceptionQueuedEvent);
 217  0
     }
 218  
     
 219  
     protected Throwable getRethrownException(Throwable exception)
 220  
     {
 221  
         // Let toRethrow be either the result of calling getRootCause() on the Exception, 
 222  
         // or the Exception itself, whichever is non-null
 223  0
         Throwable toRethrow = getRootCause(exception);
 224  0
         if (toRethrow == null)
 225  
         {
 226  0
             toRethrow = exception;
 227  
         }
 228  
         
 229  0
         return toRethrow;
 230  
     }
 231  
     
 232  
     protected FacesException wrap(Throwable exception)
 233  
     {
 234  0
         if (exception instanceof FacesException)
 235  
         {
 236  0
             return (FacesException) exception;
 237  
         }
 238  0
         return new FacesException(exception);
 239  
     }
 240  
     
 241  
     protected boolean shouldSkip(Throwable exception)
 242  
     {
 243  0
         return exception instanceof AbortProcessingException;
 244  
     }
 245  
 }