Coverage Report - com.sun.grizzly.DefaultProtocolChain
 
Classes in this File Line Coverage Branch Coverage Complexity
DefaultProtocolChain
66 %
43/65
75 %
18/24
0
DefaultProtocolChain$EventHandler
N/A
N/A
0
DefaultProtocolChain$Phase
0 %
0/1
N/A
0
 
 1  
 /*
 2  
  * 
 3  
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
 4  
  * 
 5  
  * Copyright 2007-2008 Sun Microsystems, Inc. All rights reserved.
 6  
  * 
 7  
  * The contents of this file are subject to the terms of either the GNU
 8  
  * General Public License Version 2 only ("GPL") or the Common Development
 9  
  * and Distribution License("CDDL") (collectively, the "License").  You
 10  
  * may not use this file except in compliance with the License. You can obtain
 11  
  * a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html
 12  
  * or glassfish/bootstrap/legal/LICENSE.txt.  See the License for the specific
 13  
  * language governing permissions and limitations under the License.
 14  
  * 
 15  
  * When distributing the software, include this License Header Notice in each
 16  
  * file and include the License file at glassfish/bootstrap/legal/LICENSE.txt.
 17  
  * Sun designates this particular file as subject to the "Classpath" exception
 18  
  * as provided by Sun in the GPL Version 2 section of the License file that
 19  
  * accompanied this code.  If applicable, add the following below the License
 20  
  * Header, with the fields enclosed by brackets [] replaced by your own
 21  
  * identifying information: "Portions Copyrighted [year]
 22  
  * [name of copyright owner]"
 23  
  * 
 24  
  * Contributor(s):
 25  
  * 
 26  
  * If you wish your version of this file to be governed by only the CDDL or
 27  
  * only the GPL Version 2, indicate your decision by adding "[Contributor]
 28  
  * elects to include this software in this distribution under the [CDDL or GPL
 29  
  * Version 2] license."  If you don't indicate a single choice of license, a
 30  
  * recipient has the option to distribute your version of this file under
 31  
  * either the CDDL, the GPL Version 2 or to extend the choice of license to
 32  
  * its licensees as provided above.  However, if you add GPL Version 2 code
 33  
  * and therefore, elected the GPL Version 2 license, then the option applies
 34  
  * only if the new code is made subject to such option by the copyright
 35  
  * holder.
 36  
  *
 37  
  */
 38  
 
 39  
 package com.sun.grizzly;
 40  
 
 41  
 import com.sun.grizzly.filter.ReadFilter;
 42  
 import java.util.ArrayList;
 43  
 import java.util.Collection;
 44  
 import java.util.HashSet;
 45  
 import java.util.List;
 46  
 import java.util.logging.Level;
 47  
 
 48  
 /**
 49  
  * Default ProtocolChain implementation.
 50  
  *
 51  
  * @author Jeanfrancois Arcand
 52  
  */
 53  
 public class DefaultProtocolChain implements ProtocolChain {
 54  
     
 55  0
     public enum Phase {EXECUTE, POST_EXECUTE};
 56  
     
 57  
     /**
 58  
      * The list of ProtocolFilter this chain will invoke.
 59  
      */
 60  
     protected List<ProtocolFilter> protocolFilters;
 61  
     
 62  
     /**
 63  
      * The list of {@link EventHandler}s, which will be notified about this
 64  
      * {@link ProtocolChain} events
 65  
      */
 66  
     protected Collection<EventHandler> eventHandlers;
 67  
     
 68  
     /**
 69  
      * <tt>true</tt> if a pipelined execution is required. A pipelined execution
 70  
      * occurs when a ProtocolFilter implementation set the 
 71  
      * ProtocolFilter.READ_SUCCESS as an attribute to a Context. When this 
 72  
      * attribute is present, the ProtocolChain will not release the current
 73  
      * running Thread and will re-execute all its ProtocolFilter. 
 74  
      */
 75  118
     protected boolean continousExecution = true;
 76  
     
 77  
     
 78  118
     public DefaultProtocolChain() {
 79  118
         protocolFilters = new ArrayList<ProtocolFilter>();
 80  118
         eventHandlers = new HashSet<EventHandler>();
 81  118
     }
 82  
     
 83  
     
 84  
     /**
 85  
      * Execute this ProtocolChain.
 86  
      * @param ctx {@link Context}
 87  
      * @throws java.lang.Exception 
 88  
      */
 89  
     public void execute(Context ctx) throws Exception {
 90  82619
         execute(ctx,0);
 91  82619
     }
 92  
     
 93  
     
 94  
     /**
 95  
      * Execute this ProtocolChain.
 96  
      * @param ctx {@link Context}
 97  
      * @param firstFilter The first filter to be invoked.
 98  
      * @throws java.lang.Exception 
 99  
      */
 100  
     public void execute(Context ctx, int firstFilter) throws Exception {
 101  82622
         if (protocolFilters.size() != 0){
 102  82622
             boolean reinvokeChain = true;
 103  204301
             while (reinvokeChain){
 104  121679
                 int currentPosition = executeProtocolFilter(ctx,firstFilter);
 105  121679
                 reinvokeChain = postExecuteProtocolFilter(currentPosition, ctx);
 106  121679
             }
 107  
         }
 108  82622
     }    
 109  
     
 110  
     /**
 111  
      * Execute the ProtocolFilter.execute method. If a ProtocolFilter.execute
 112  
      * return false, avoid invoking the next ProtocolFilter.
 113  
      * @param ctx {@link Context}
 114  
      * @return position of next {@link ProtocolFilter} to exexute
 115  
      */
 116  
     protected int executeProtocolFilter(Context ctx) {
 117  0
         return executeProtocolFilter(ctx,0);
 118  
     }
 119  
     
 120  
     
 121  
     /**
 122  
      * Execute the ProtocolFilter.execute method. If a ProtocolFilter.execute
 123  
      * return false, avoid invoking the next ProtocolFilter.
 124  
      * @param ctx {@link Context}
 125  
      * @param firstFilter The first filter position to be invoked. 
 126  
      * @return position of next {@link ProtocolFilter} to exexute
 127  
      */
 128  
     protected int executeProtocolFilter(Context ctx, int firstFilter) {
 129  
         boolean invokeNext;
 130  121679
         int size = protocolFilters.size();
 131  121679
         int currentPosition = 0;
 132  121679
         ProtocolFilter protocolFilter = null;
 133  
         
 134  235635
         for (int i=firstFilter; i < size; i++) {
 135  
             try {
 136  235635
                 protocolFilter = protocolFilters.get(i);
 137  235635
                 invokeNext = protocolFilter.execute(ctx);
 138  0
             } catch (Exception ex){
 139  0
                 invokeNext = false;
 140  0
                 i--;
 141  0
                 Controller.logger().log(Level.SEVERE,
 142  
                         "ProtocolChain exception",ex);
 143  0
                 notifyException(Phase.EXECUTE, protocolFilter, ex);
 144  235635
             }
 145  
             
 146  235635
             currentPosition = i;
 147  235635
             if ( !invokeNext ) break;
 148  
         }
 149  121679
         return currentPosition;
 150  
     }
 151  
     
 152  
     
 153  
     /**
 154  
      * Execute the ProtocolFilter.postExcute.
 155  
      * @param currentPosition position in list of {@link ProtocolFilter}s
 156  
      * @param ctx {@link Context}
 157  
      * @return false, always false
 158  
      */
 159  
     protected boolean postExecuteProtocolFilter(int currentPosition,Context ctx) {
 160  121679
         boolean invokeNext = true;
 161  121679
         ProtocolFilter tmpHandler = null;
 162  121678
         boolean reinvokeChain = false;
 163  357307
         for (int i = currentPosition; i > -1; i--){
 164  
             try{
 165  235636
                 tmpHandler = protocolFilters.get(i);
 166  235636
                 invokeNext = tmpHandler.postExecute(ctx);                 
 167  0
             } catch (Exception ex){
 168  0
                 Controller.logger().log(Level.SEVERE,
 169  
                         "ProtocolChain exception",ex);
 170  0
                 notifyException(Phase.POST_EXECUTE, tmpHandler, ex);
 171  235635
             }
 172  235636
             if ( !invokeNext ) {
 173  6
                break;
 174  
             }
 175  
         }
 176  
         
 177  121679
         if (continousExecution 
 178  
             && currentPosition == protocolFilters.size() -1
 179  
             && (Boolean)ctx.removeAttribute(ProtocolFilter.SUCCESSFUL_READ) 
 180  
                 == Boolean.TRUE) {
 181  39057
             reinvokeChain = true;    
 182  
         } 
 183  
 
 184  121679
         return reinvokeChain;
 185  
     }
 186  
     
 187  
     
 188  
     /**
 189  
      * Remove a ProtocolFilter.
 190  
      * @param theFilter the ProtocolFilter to remove
 191  
      * @return removed ProtocolFilter
 192  
      */
 193  
     public boolean removeFilter(ProtocolFilter theFilter) {
 194  0
         return protocolFilters.remove(theFilter);
 195  
     }
 196  
     
 197  
     
 198  
     /**
 199  
      * Add the {@link ProtocolFilter} to this {@link ProtocolChain}
 200  
      * @param protocolFilter to add
 201  
      * @return 
 202  
      */
 203  
     public boolean addFilter(ProtocolFilter protocolFilter) {
 204  182
         return protocolFilters.add(protocolFilter);
 205  
     }
 206  
     
 207  
     
 208  
     /**
 209  
      * Insert a ProtocolFilter at position pos.
 210  
      * @param pos 
 211  
      * @param protocolFilter 
 212  
      */
 213  
     public void addFilter(int pos, ProtocolFilter protocolFilter){
 214  0
         protocolFilters.add(pos,protocolFilter);
 215  0
     }
 216  
     
 217  
     
 218  
     /**
 219  
      *Insert a ProtocolFilter at position pos.
 220  
      * @param pos - position in this ProtocolChain
 221  
      * @param protocolFilter - {@link ProtocolFilter} to insert
 222  
      * @return {@link ProtocolFilter} that was set
 223  
      */
 224  
     public ProtocolFilter setProtocolFilter(int pos,
 225  
             ProtocolFilter protocolFilter) {
 226  0
         return protocolFilters.set(pos,protocolFilter);
 227  
     }
 228  
     
 229  
     
 230  
     /**
 231  
      * Set to <tt>true</tt> if the current {@link Pipeline} can 
 232  
      * re-execute its ProtocolFilter(s) after a successful execution. Enabling
 233  
      * this property is useful for protocol that needs to support pipelined
 234  
      * message requests as the ProtocolFilter are automatically re-executed, 
 235  
      * avoiding the overhead of releasing the current Thread, registering 
 236  
      * back the SelectionKey to the SelectorHandler and waiting for a new
 237  
      * NIO event. 
 238  
      * 
 239  
      * Some protocols (like http) can get the http headers in one
 240  
      * SocketChannel.read, parse the message and then get the next http message 
 241  
      * on the second SocketChannel.read(). Not having to release the Thread
 242  
      * and re-execute the ProtocolFilter greatly improve performance.
 243  
      * @param continousExecution true to enable continuous execution.
 244  
      *        (default is false).
 245  
      */
 246  
     public void setContinuousExecution(boolean continousExecution){
 247  6
         this.continousExecution = continousExecution;
 248  6
         for (ProtocolFilter filter : protocolFilters){
 249  6
             if (filter instanceof ReadFilter){
 250  6
                 ((ReadFilter)filter).setContinuousExecution(continousExecution);
 251  6
                 break;
 252  
             }
 253  
         }
 254  6
     }
 255  
     
 256  
     
 257  
     /**
 258  
      * Return <tt>true</tt> if the current {@link Pipeline} can 
 259  
      * re-execute its ProtocolFilter after a successful execution. 
 260  
      */    
 261  
     public boolean isContinuousExecution(){
 262  0
         return continousExecution;
 263  
     }
 264  
     
 265  
     
 266  
     /**
 267  
      * Add the {@link EventHandler}
 268  
      * @param eventHandler 
 269  
      * @return true, if {@link EventHandler} was added, false otherwise
 270  
      */
 271  
     public boolean addEventHandler(EventHandler eventHandler) {
 272  0
         return eventHandlers.add(eventHandler);
 273  
     }
 274  
 
 275  
     
 276  
     /**
 277  
      * Remove the {@link EventHandler}.
 278  
      * @param eventHandler the <code>ProtocolFilter<code> to remove
 279  
      * @return true, if {@link EventHandler} was removed, false otherwise
 280  
      */
 281  
     public boolean removeEventHandler(EventHandler eventHandler) {
 282  0
         return eventHandlers.remove(eventHandler);
 283  
     }
 284  
     
 285  
     /**
 286  
      * Notifies all {@link EventHandler}s about exception, which occured
 287  
      * @param phase execution <code>Phase</code>, where exception occured
 288  
      * @param filter {@link ProtocolFilter}, where exception occured
 289  
      * @param throwable actual exception
 290  
      */
 291  
     protected void notifyException(Phase phase, ProtocolFilter filter, 
 292  
             Throwable throwable) {
 293  0
         for(EventHandler eventHandler : eventHandlers) {
 294  
             try {
 295  0
                 eventHandler.onException(phase, filter, throwable);
 296  0
             } catch(Exception e) {
 297  0
                 Controller.logger().log(Level.SEVERE,
 298  
                         "ProtocolChain notifyException exception", e);
 299  
 
 300  0
             }
 301  
         }
 302  0
     }
 303  
     
 304  
     /**
 305  
      * Interface, which introduces handler, which will be notified about event,
 306  
      * happened on {@link ProtocolChain}
 307  
      */
 308  
     public interface EventHandler {
 309  
         public void onException(Phase phase, ProtocolFilter filter, 
 310  
                 Throwable throwable);
 311  
     }
 312  
 }