Coverage Report - com.sun.grizzly.connectioncache.client.CacheableConnectorHandler
 
Classes in this File Line Coverage Branch Coverage Complexity
CacheableConnectorHandler
47 %
43/92
25 %
7/28
0
CacheableConnectorHandler$1
0 %
0/7
N/A
0
CacheableConnectorHandler$ConnectExecutor
58 %
22/38
14 %
1/7
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.connectioncache.client;
 40  
 
 41  
 import com.sun.grizzly.CallbackHandler;
 42  
 import com.sun.grizzly.ConnectorHandler;
 43  
 import com.sun.grizzly.Context;
 44  
 import com.sun.grizzly.Controller;
 45  
 import com.sun.grizzly.Controller.Protocol;
 46  
 import com.sun.grizzly.IOEvent;
 47  
 import com.sun.grizzly.SelectorHandler;
 48  
 import com.sun.grizzly.connectioncache.spi.transport.ContactInfo;
 49  
 import java.io.IOException;
 50  
 import java.net.SocketAddress;
 51  
 import java.nio.ByteBuffer;
 52  
 import java.nio.channels.ClosedChannelException;
 53  
 import java.nio.channels.SelectableChannel;
 54  
 import java.nio.channels.SelectionKey;
 55  
 import java.nio.channels.Selector;
 56  
 
 57  
 /**
 58  
  * Extended implementation of the DefaultSelectionKeyHandler with
 59  
  * ConnectionManagement integrated in it
 60  
  *
 61  
  * @author Alexey Stashok
 62  
  */
 63  2
 public class CacheableConnectorHandler implements ConnectorHandler<SelectorHandler, CallbackHandler>,
 64  
         ContactInfo<ConnectorHandler>, CallbackHandler {
 65  
     private SocketAddress targetAddress;
 66  
     private Protocol protocol;
 67  
     private SelectorHandler selectorHandler;
 68  
     
 69  
     private CacheableConnectorHandlerPool parentPool;
 70  
     private ConnectorHandler underlyingConnectorHandler;
 71  
     private CallbackHandler underlyingCallbackHandler;
 72  
     
 73  
     private ConnectExecutor connectExecutor;
 74  
     
 75  1
     public CacheableConnectorHandler(CacheableConnectorHandlerPool parentPool) {
 76  1
         this.parentPool = parentPool;
 77  1
         connectExecutor = new ConnectExecutor();
 78  1
     }
 79  
     
 80  
     void setProtocol(Protocol protocol) {
 81  10
         this.protocol = protocol;
 82  10
     }
 83  
     
 84  
     public Protocol protocol() {
 85  0
         return protocol;
 86  
     }
 87  
     
 88  
     // connect method #1
 89  
     public void connect(SocketAddress remoteAddress, CallbackHandler callbackHandler, SelectorHandler selectorHandler) throws IOException {
 90  0
         connectExecutor.setParameters(remoteAddress, callbackHandler, selectorHandler);
 91  0
         doConnect(remoteAddress);
 92  0
     }
 93  
     
 94  
     // connect method #2
 95  
     public void connect(SocketAddress remoteAddress, CallbackHandler callbackHandler) throws IOException {
 96  10
         connectExecutor.setParameters(remoteAddress, callbackHandler);
 97  10
         doConnect(remoteAddress);
 98  10
     }
 99  
     
 100  
     // connect method #3
 101  
     public void connect(SocketAddress remoteAddress) throws IOException {
 102  0
         connectExecutor.setParameters(remoteAddress);
 103  0
         doConnect(remoteAddress);
 104  0
     }
 105  
     
 106  
     // connect method #4
 107  
     public void connect(SocketAddress remoteAddress, SocketAddress localAddress,
 108  
             CallbackHandler callbackHandler, SelectorHandler selectorHandler) throws IOException {
 109  0
         connectExecutor.setParameters(remoteAddress, localAddress, callbackHandler, selectorHandler);
 110  0
         doConnect(remoteAddress);
 111  0
     }
 112  
     
 113  
     // connect method #5
 114  
     public void connect(SocketAddress remoteAddress, SocketAddress localAddress, CallbackHandler callbackHandler) throws IOException {
 115  0
         connectExecutor.setParameters(remoteAddress, localAddress, callbackHandler);
 116  0
         doConnect(remoteAddress);
 117  0
     }
 118  
     
 119  
     // connect method #6
 120  
     public void connect(SocketAddress remoteAddress, SocketAddress localAddress) throws IOException {
 121  0
         connectExecutor.setParameters(remoteAddress, localAddress);
 122  0
         doConnect(remoteAddress);
 123  0
     }
 124  
     
 125  
     
 126  
     /**
 127  
      * Releases underlying connection, which means it could be reused for writing
 128  
      * by other <code>CacheableConnectorHandler</code>, however this 
 129  
      * <code>CacheableConnectorHandler</code> will be still interested in getting 
 130  
      * expectedResponseCount responses on it.
 131  
      * 
 132  
      * @param expectedResponseCount number of reponses expected on the connection
 133  
      */
 134  
     public void release(int expectedResponseCount) {
 135  0
         parentPool.getOutboundConnectionCache().release(underlyingConnectorHandler, expectedResponseCount);
 136  0
     }
 137  
 
 138  
     /**
 139  
      * Notifies connection cache, that response was received. And connection cache
 140  
      * could decrease expected response counter by 1
 141  
      */
 142  
     public void responseReceived() {
 143  0
         parentPool.getOutboundConnectionCache().responseReceived(underlyingConnectorHandler);
 144  0
     }
 145  
 
 146  
     /**
 147  
      * @param targetAddress target connection address
 148  
      * @throws java.io.IOException if IO error happened
 149  
      */
 150  
     private void doConnect(SocketAddress targetAddress) throws IOException {
 151  10
         this.targetAddress = targetAddress;
 152  10
         selectorHandler = connectExecutor.selectorHandler;
 153  10
         underlyingCallbackHandler = connectExecutor.callbackHandler;
 154  10
         underlyingConnectorHandler = parentPool.
 155  
                 getOutboundConnectionCache().get(this, parentPool.getConnectionFinder());
 156  
         
 157  
         /* check whether NEW connection was created, or taken from cache */
 158  10
         if (!connectExecutor.wasCalled()) { // if taken from cache
 159  
             //if connection is taken from cache - explicitly notify callback handler
 160  9
             underlyingConnectorHandler.setCallbackHandler(this);
 161  9
             notifyCallbackHandlerPseudoConnect();
 162  
         }
 163  10
     }
 164  
     
 165  
     
 166  
     public void close() throws IOException {
 167  10
         parentPool.getOutboundConnectionCache().release(underlyingConnectorHandler, 0);
 168  10
     }
 169  
     
 170  
     public long read(ByteBuffer byteBuffer, boolean blocking) throws IOException {
 171  1000
         return underlyingConnectorHandler.read(byteBuffer, blocking);
 172  
     }
 173  
     
 174  
     public long write(ByteBuffer byteBuffer, boolean blocking) throws IOException {
 175  1000
         return underlyingConnectorHandler.write(byteBuffer, blocking);
 176  
     }
 177  
     
 178  
     public void finishConnect(SelectionKey key) {
 179  
         // Call underlying finishConnect only if connection was just established
 180  10
         if (connectExecutor.wasCalled()) {
 181  
             try{
 182  1
                 underlyingConnectorHandler.finishConnect(key);
 183  0
             } catch (IOException ex){
 184  0
                 Controller.logger().severe(ex.getMessage());
 185  1
             }
 186  
         }
 187  10
     }
 188  
     
 189  
     public void setController(Controller controller) {
 190  0
         underlyingConnectorHandler.setController(controller);
 191  0
     }
 192  
     
 193  
     public Controller getController() {
 194  0
         return underlyingConnectorHandler.getController();
 195  
     }
 196  
     
 197  
     public SelectableChannel getUnderlyingChannel() {
 198  0
         return underlyingConnectorHandler.getUnderlyingChannel();
 199  
     }
 200  
     
 201  
     public CallbackHandler getCallbackHandler() {
 202  0
         return underlyingConnectorHandler.getCallbackHandler();
 203  
     }
 204  
     
 205  
     public void setCallbackHandler(CallbackHandler callbackHandler) {
 206  0
         underlyingConnectorHandler.setCallbackHandler(callbackHandler);
 207  0
     }
 208  
     
 209  
     public SelectorHandler getSelectorHandler() {
 210  0
         return underlyingConnectorHandler.getSelectorHandler();
 211  
     }
 212  
     
 213  
     
 214  
     //---------------------- ContactInfo implementation --------------------------------
 215  
     public ConnectorHandler createConnection() throws IOException {
 216  1
         underlyingConnectorHandler = parentPool.getProtocolConnectorHandlerPool().acquireConnectorHandler(protocol);
 217  
         
 218  1
         connectExecutor.setConnectorHandler(underlyingConnectorHandler);
 219  1
         connectExecutor.invokeProtocolConnect();
 220  1
         return underlyingConnectorHandler;
 221  
     }
 222  
     
 223  
     @Override
 224  
     public String toString() {
 225  0
         StringBuffer sb = new StringBuffer();
 226  0
         sb.append(getClass().getName());
 227  0
         sb.append(" targetAddress: ");
 228  0
         sb.append(targetAddress);
 229  0
         sb.append(" protocol: ");
 230  0
         sb.append(protocol);
 231  0
         sb.append(" hashCode: ");
 232  0
         sb.append(super.hashCode());
 233  0
         return sb.toString();
 234  
     }
 235  
     
 236  
     //----- Override hashCode(), equals() as part of ContactInfo implementation -----------
 237  
     @Override
 238  
     public int hashCode() {
 239  11
         return targetAddress.hashCode() ^ protocol.hashCode();
 240  
     }
 241  
     
 242  
     @Override
 243  
     public boolean equals(Object o) {
 244  0
         if (o instanceof CacheableConnectorHandler) {
 245  0
             CacheableConnectorHandler handler = (CacheableConnectorHandler) o;
 246  0
             if (selectorHandler == null || handler.selectorHandler == null) {
 247  0
                 return targetAddress.equals(handler.targetAddress) &&
 248  
                         protocol.equals(handler.protocol);
 249  
             } else {
 250  0
                 return targetAddress.equals(handler.targetAddress) &&
 251  
                         protocol.equals(handler.protocol) &&
 252  
                         selectorHandler == handler.selectorHandler;
 253  
             }
 254  
         }
 255  
         
 256  0
         return false;
 257  
     }
 258  
     
 259  
     
 260  
     private void notifyCallbackHandlerPseudoConnect() throws ClosedChannelException {
 261  9
         Selector protocolSelector = underlyingConnectorHandler.getSelectorHandler().getSelector();
 262  9
         SelectionKey key = underlyingConnectorHandler.getUnderlyingChannel().keyFor(protocolSelector);
 263  9
         if (key == null) {
 264  
             // Register channel on selector
 265  0
             key = underlyingConnectorHandler.getUnderlyingChannel().
 266  
                     register(protocolSelector, SelectionKey.OP_CONNECT);
 267  
         }
 268  
         
 269  9
         assert key != null;
 270  
         
 271  9
         final Context context = parentPool.getController().pollContext(key);
 272  9
         onConnect(new IOEvent.DefaultIOEvent<Context>(context));
 273  9
     }
 274  
     
 275  
     //---------------------- CallbackHandler implementation --------------------------------
 276  
     public void onConnect(IOEvent ioEvent) {
 277  10
         if (underlyingCallbackHandler == null) {
 278  0
             underlyingCallbackHandler = new CallbackHandler<Context>(){
 279  
                 public void onConnect(IOEvent<Context> ioEvent) {
 280  0
                     SelectionKey key = ioEvent.attachment().getSelectionKey();
 281  0
                     finishConnect(key);
 282  0
                     getController().registerKey(key,SelectionKey.OP_WRITE,
 283  
                             protocol);
 284  0
                 }
 285  0
                 public void onRead(IOEvent<Context> ioEvent) {}
 286  0
                 public void onWrite(IOEvent<Context> ioEvent) {}
 287  
             };
 288  
         }
 289  
         
 290  10
         underlyingCallbackHandler.onConnect(ioEvent);
 291  10
     }
 292  
     
 293  
     public void onRead(IOEvent ioEvent) {
 294  793
         underlyingCallbackHandler.onRead(ioEvent);
 295  793
     }
 296  
     
 297  
     public void onWrite(IOEvent ioEvent) {
 298  0
         underlyingCallbackHandler.onWrite(ioEvent);
 299  0
     }
 300  
     
 301  
     /**
 302  
      * Class is responsible for execution corresponding
 303  
      * underlying {@link ConnectorHandler} connect method
 304  
      */
 305  22
     private class ConnectExecutor {
 306  
         private int methodNumber;
 307  
         private ConnectorHandler connectorHandler;
 308  
         private SocketAddress remoteAddress;
 309  
         private SocketAddress localAddress;
 310  
         private SelectorHandler selectorHandler;
 311  
         private CallbackHandler callbackHandler;
 312  
         private boolean wasCalled;
 313  
         
 314  
         public void setConnectorHandler(ConnectorHandler connectorHandler) {
 315  1
             this.connectorHandler = connectorHandler;
 316  1
         }
 317  
         
 318  
         public void setParameters(SocketAddress remoteAddress, CallbackHandler callbackHandler, SelectorHandler selectorHandler) {
 319  0
             setParameters(remoteAddress, null, callbackHandler, selectorHandler);
 320  0
             methodNumber = 1;
 321  0
         }
 322  
         
 323  
         public void setParameters(SocketAddress remoteAddress, CallbackHandler callbackHandler) {
 324  10
             setParameters(remoteAddress, null, callbackHandler);
 325  10
             methodNumber = 2;
 326  10
         }
 327  
         
 328  
         public void setParameters(SocketAddress remoteAddress) {
 329  0
             setParameters(remoteAddress, (SocketAddress) null);
 330  0
             methodNumber = 3;
 331  0
         }
 332  
         
 333  
         public void setParameters(SocketAddress remoteAddress, SocketAddress localAddress, CallbackHandler callbackHandler,SelectorHandler selectorHandler) {
 334  10
             wasCalled = false;
 335  10
             this.remoteAddress = remoteAddress;
 336  10
             this.localAddress = localAddress;
 337  10
             this.callbackHandler = callbackHandler;
 338  10
             this.selectorHandler = selectorHandler;
 339  10
             methodNumber = 4;
 340  10
         }
 341  
         
 342  
         public void setParameters(SocketAddress remoteAddress, SocketAddress localAddress, CallbackHandler callbackHandler) {
 343  10
             setParameters(remoteAddress, localAddress, callbackHandler , null);
 344  10
             methodNumber = 5;
 345  10
         }
 346  
         
 347  
         public void setParameters(SocketAddress remoteAddress, SocketAddress localAddress) {
 348  0
             setParameters(remoteAddress, localAddress, null);
 349  0
             methodNumber = 6;
 350  0
         }
 351  
         
 352  
         public boolean wasCalled() {
 353  20
             return wasCalled;
 354  
         }
 355  
         
 356  
         public void invokeProtocolConnect() throws IOException {
 357  1
             wasCalled = true;
 358  1
             switch(methodNumber) {
 359  0
             case 1: connectorHandler.connect(remoteAddress, CacheableConnectorHandler.this, selectorHandler);
 360  0
             break;
 361  
             case 2:
 362  1
             case 3: connectorHandler.connect(remoteAddress, CacheableConnectorHandler.this);
 363  1
             break;
 364  0
             case 4: connectorHandler.connect(remoteAddress, localAddress, CacheableConnectorHandler.this, selectorHandler);
 365  0
             break;
 366  
             case 5:
 367  0
             case 6: connectorHandler.connect(remoteAddress, localAddress, CacheableConnectorHandler.this);
 368  0
             break;
 369  0
             default: throw new IllegalStateException("Can not find appropriate connect method: " + methodNumber);
 370  
             }
 371  1
         }
 372  
     }
 373  
 }