Coverage Report - com.sun.grizzly.Context
 
Classes in this File Line Coverage Branch Coverage Complexity
Context
57 %
89/156
47 %
24/51
0
Context$1
100 %
1/1
N/A
0
Context$AsyncQueueReadableContextWrapper
0 %
0/7
N/A
0
Context$AsyncQueueWritableContextWrapper
29 %
5/17
N/A
0
Context$AttributeScope
100 %
5/5
N/A
0
Context$KeyRegistrationState
100 %
4/4
N/A
0
Context$OpType
100 %
5/5
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.async.AsyncQueueDataProcessor;
 42  
 import com.sun.grizzly.async.AsyncQueueReadable;
 43  
 import com.sun.grizzly.async.AsyncQueueReader;
 44  
 import com.sun.grizzly.async.AsyncQueueWritable;
 45  
 import com.sun.grizzly.async.AsyncQueueWriter;
 46  
 import com.sun.grizzly.async.AsyncReadCallbackHandler;
 47  
 import com.sun.grizzly.async.AsyncReadCondition;
 48  
 import com.sun.grizzly.async.AsyncWriteCallbackHandler;
 49  
 import com.sun.grizzly.util.AttributeHolder;
 50  
 import com.sun.grizzly.util.Copyable;
 51  
 import com.sun.grizzly.util.SelectionKeyAttachment;
 52  
 import com.sun.grizzly.util.WorkerThread;
 53  
 import java.io.IOException;
 54  
 import java.net.SocketAddress;
 55  
 import java.nio.ByteBuffer;
 56  
 import java.nio.channels.SelectionKey;
 57  
 import java.util.HashMap;
 58  
 import java.util.Map;
 59  
 import java.util.concurrent.atomic.AtomicInteger;
 60  
 import java.util.logging.Level;
 61  
 
 62  
 /**
 63  
  * This Object is used to share information between the Grizzly Framework
 64  
  * classes and {@link ProtocolFilter} implementation. Since {@link Context}
 65  
  * is a pooled resource 
 66  
  * {@link Controller#pollContext(java.nio.channels.SelectionKey)} 
 67  
  * transactions using {@link Context} outside its {@link ProtocolChain}
 68  
  * must invoke {@link #incrementRefCount()} and
 69  
  * {@link Controller#returnContext(com.sun.grizzly.Context)} to keep its pooling
 70  
  * intact.
 71  
  * @author Jeanfrancois Arcand
 72  
  */
 73  173324
 public class Context implements AttributeHolder, Copyable {
 74  
 
 75  
 
 76  6
     public enum AttributeScope {
 77  1
         REQUEST,
 78  1
         CONNECTION,
 79  1
         SELECTOR,
 80  1
         CONTROLLER
 81  
     }
 82  
     
 83  
     /**
 84  
      * A {@link SelectionKey}'s registration state.
 85  
      */
 86  4
     public enum KeyRegistrationState {
 87  
         /** A cancelled {@link SelectionKey} registration state. */
 88  1
         CANCEL,
 89  
         /** A registered {@link SelectionKey} registration state. */
 90  1
         REGISTER,
 91  
         /** A {@link SelectionKey} with no registration state. */
 92  1
         NONE }
 93  
     
 94  
     
 95  
     /**
 96  
      * The list of possible {@link SelectionKey}.OP_XXXX.
 97  
      */
 98  7
     public enum OpType { OP_READ,
 99  1
         OP_WRITE,
 100  1
         OP_CONNECT,
 101  1
         OP_READ_WRITE,
 102  1
         OP_ACCEPT
 103  
     }
 104  
     
 105  
     
 106  
     /**
 107  
      * The current {@link SelectionKey} interest ops this Context is processing.
 108  
      */
 109  
     private OpType currentOpType;
 110  
     
 111  
     
 112  
     /**
 113  
      * The {@link ProtocolChain} used to execute this {@link Context}
 114  
      */
 115  
     private ProtocolChain protocolChain;
 116  
     
 117  
     
 118  
     /**
 119  
      * Constant 'throwable' String
 120  
      */
 121  
     public final static String THROWABLE ="throwable";
 122  
     
 123  
     
 124  
     /**
 125  
      * Used to share object between {@link ProtocolFilter}.
 126  
      * WARNING: Attributes which are added are never removed automatically
 127  
      * The removal operation must be done explicitly inside a  {@link ProtocolFilter}.
 128  
      */
 129  261
     private Map<String,Object> attributes = null;
 130  
     
 131  
     
 132  
     /**
 133  
      * The current connection (@link SelectionKey}.
 134  
      */
 135  
     private SelectionKey key;
 136  
     
 137  
     
 138  
     /**
 139  
      * The {@link SelectorHandler} associated with this Context.
 140  
      */
 141  
     private SelectorHandler selectorHandler;
 142  
 
 143  
     
 144  
     /**
 145  
      * The {@link Controller} associated with this Context.
 146  
      */
 147  
     private Controller controller;
 148  
     
 149  
     
 150  
     /**
 151  
      * The state's of the key registration.
 152  
      */
 153  261
     private KeyRegistrationState keyRegistrationState
 154  
             = KeyRegistrationState.REGISTER;
 155  
     
 156  
     
 157  
     /**
 158  
      * The current {@linl Pipeline} that execute this object.
 159  
      */
 160  
     private Pipeline pipeline;
 161  
     
 162  
     
 163  
     /**
 164  
      * An optional {@link IOEvent} that can be invoked
 165  
      * before the {@link ProtocolChain} is invoked.
 166  
      */
 167  
     private IOEvent<Context> ioEvent;
 168  
     
 169  
     
 170  
     /**
 171  
      * {@link AsyncQueueReader}
 172  
      */
 173  
     private AsyncQueueReader asyncQueueReader;
 174  
 
 175  
     /**
 176  
      * {@link AsyncQueueWriter}
 177  
      */
 178  
     private AsyncQueueWriter asyncQueueWriter;
 179  
     
 180  
     /**
 181  
      * {@link AsyncQueueReadable}
 182  
      */
 183  
     private AsyncQueueReadable asyncQueueReadable;
 184  
 
 185  
     /**
 186  
      * {@link AsyncQueueWritable}
 187  
      */
 188  
     private AsyncQueueWritable asyncQueueWritable;
 189  
     
 190  
     
 191  
     /**
 192  
      * Is this context suspended.
 193  
      */
 194  261
     private boolean isSuspended = false;
 195  
     
 196  
      /**
 197  
      *  Reference Counter indicating how many Threads share this Context.
 198  
      *  Starts at one already counting {@link WorkerThread}.
 199  
      */
 200  261
     private AtomicInteger refCounter=new AtomicInteger(1);
 201  
     
 202  
     
 203  
     /**
 204  
      * Constructor
 205  
      */
 206  261
     public Context() {
 207  261
     }
 208  
     
 209  
     
 210  
     public void copyTo(Copyable copy) {
 211  0
         Context copyContext = (Context) copy;
 212  0
         copyContext.currentOpType = currentOpType;
 213  0
         copyContext.protocolChain = protocolChain;
 214  0
         if (attributes != null) {
 215  0
             copyContext.attributes = new HashMap<String, Object>(attributes);
 216  
         }
 217  0
         copyContext.key = key;
 218  0
         copyContext.selectorHandler = selectorHandler;
 219  0
         copyContext.controller = controller;
 220  0
         copyContext.keyRegistrationState = keyRegistrationState;
 221  0
         copyContext.pipeline = pipeline;
 222  0
         copyContext.ioEvent = ioEvent;
 223  0
         copyContext.asyncQueueReader = asyncQueueReader;
 224  0
         copyContext.asyncQueueWriter = asyncQueueWriter;
 225  0
     }
 226  
 
 227  
     /**
 228  
      * Remove a key/value object.
 229  
      * @param key - name of an attribute
 230  
      * @return  attribute which has been removed
 231  
      */
 232  
     public Object removeAttribute(String key){
 233  165998
         if (attributes == null){
 234  56606
             return null;
 235  
         }
 236  109392
         return attributes.remove(key);
 237  
     }
 238  
     
 239  
     
 240  
     /**
 241  
      * Set a key/value object.
 242  
      * @param key - name of an attribute
 243  
      * @param value - value of named attribute
 244  
      */
 245  
     public void setAttribute(String key,Object value){
 246  21124
         if (attributes == null){
 247  41
             attributes = new HashMap<String,Object>();
 248  
         }
 249  21124
         attributes.put(key,value);
 250  21124
     }
 251  
     
 252  
     
 253  
     /**
 254  
      * Return an object based on a key.
 255  
      * @param key - name of an attribute
 256  
      * @return - attribute value for the <tt>key</tt>, null if <tt>key</tt>
 257  
      *           does not exist in <tt>attributes</tt>
 258  
      */
 259  
     public Object getAttribute(String key){
 260  21006
         if (attributes == null){
 261  1
             return null;
 262  
         }
 263  21005
         return attributes.get(key);
 264  
     }
 265  
     
 266  
     
 267  
     /**
 268  
      * Return {@link AttributeHolder}, which corresponds to the 
 269  
      * given {@link AttributeScope}>
 270  
      * 
 271  
      * @param scope - {@link AttributeScope}>
 272  
      * @return - {@link AttributeHolder} instance, which contains
 273  
      *           {@link AttributeScope}> attributes
 274  
      */
 275  
     public AttributeHolder getAttributeHolderByScope(AttributeScope scope){
 276  52743
         AttributeHolder holder = null;
 277  1
         switch(scope) {
 278  
             case REQUEST: 
 279  0
                 holder = this;
 280  0
                 break;
 281  
             case CONNECTION:
 282  52743
                 Object attachment = getSelectionKey().attachment();
 283  52743
                 if (attachment instanceof AttributeHolder) {
 284  52742
                     holder = (AttributeHolder) attachment;
 285  
                 }
 286  
                 break;
 287  
             case SELECTOR:
 288  0
                 holder = selectorHandler;
 289  0
                 break;
 290  
             case CONTROLLER:
 291  0
                 holder = controller;
 292  
                 break;
 293  
         }
 294  
         
 295  52743
         return holder;
 296  
     }
 297  
 
 298  
     
 299  
     /**
 300  
      * Set a {@link Map} of attribute name/value pairs.
 301  
      * Old {@link AttributeHolder} values will not be available.
 302  
      * Later changes of this {@link Map} will lead to changes to the current
 303  
      * {@link AttributeHolder}.
 304  
      * 
 305  
      * @param attributes - map of name/value pairs
 306  
      */
 307  
     public void setAttributes(Map<String, Object> attributes) {
 308  0
         this.attributes = attributes;
 309  0
     }
 310  
 
 311  
     
 312  
     /**
 313  
      * Return a {@link Map} of attribute name/value pairs.
 314  
      * Updates, performed on the returned {@link Map} will be reflected in
 315  
      * this {@link AttributeHolder}
 316  
      * 
 317  
      * @return - {@link Map} of attribute name/value pairs
 318  
      */
 319  
     public Map<String, Object> getAttributes() {
 320  0
         return attributes;
 321  
     }
 322  
 
 323  
     
 324  
     /**
 325  
      * Return the current {@link SelectionKey}.
 326  
      * @return - this Context's SelectionKey
 327  
      */
 328  
     public SelectionKey getSelectionKey() {
 329  619960
         return key;
 330  
     }
 331  
     
 332  
     
 333  
     /**
 334  
      * Set the connection {@link SelectionKey}.
 335  
      * @param key - set this Context's SelectionKey
 336  
      */
 337  
     public void setSelectionKey(SelectionKey key) {
 338  231945
         this.key = key;
 339  231945
     }
 340  
     
 341  
     
 342  
     /**
 343  
      * Return the current {@link Controller}.
 344  
      * @return - this Context's current {@link Controller}
 345  
      */
 346  
     public Controller getController() {
 347  302630
         return controller;
 348  
     }
 349  
     
 350  
     
 351  
     /**
 352  
      * Set the current {@link Controller}.
 353  
      * @param {@link Controller}
 354  
      */
 355  
     public void setController(Controller controller) {
 356  427668
         this.controller = controller;
 357  427668
     }
 358  
 
 359  
 
 360  
     /**
 361  
      * Recycle this instance. 
 362  
      */
 363  
     public void recycle(){        
 364  161370
         if (isSuspended){
 365  0
             throw new IllegalStateException("The Context has been marked as " +
 366  
                     "suspended and cannot be recycled");
 367  
         }
 368  
                 
 369  161370
         getProtocolChainInstanceHandler().offer(protocolChain);            
 370  161370
         key = null;
 371  161370
         keyRegistrationState = KeyRegistrationState.REGISTER;
 372  161370
         currentOpType = null;
 373  161369
         protocolChain = null;
 374  161368
         ioEvent = null;
 375  161370
         asyncQueueReader = null;
 376  161370
         asyncQueueWriter = null;
 377  161370
         if (attributes != null) {
 378  128305
             attributes.clear();
 379  
         }
 380  161370
         isSuspended = false;
 381  161370
         refCounter.set(1);
 382  161370
     }
 383  
     
 384  
     
 385  
     /**
 386  
      * Return {@link SelectionKey}'s next registration state.
 387  
      * @return this Context's SelectionKey registration state
 388  
      */
 389  
     public KeyRegistrationState getKeyRegistrationState() {
 390  143908
         return keyRegistrationState;
 391  
     }
 392  
     
 393  
     
 394  
     /**
 395  
      * Set the {@link SelectionKey}'s next registration state
 396  
      * @param {@link keyRegistrationState} - set this Context's SelectionKey
 397  
      *        registration state
 398  
      */
 399  
     public void setKeyRegistrationState(KeyRegistrationState keyRegistrationState) {
 400  53253
         this.keyRegistrationState = keyRegistrationState;
 401  53253
     }
 402  
     
 403  
     
 404  
     /**
 405  
      * Return {@link ProtocolChain} executed by this instance.
 406  
      * @return {@link ProtocolChain} instance
 407  
      */
 408  
     public ProtocolChain getProtocolChain() {
 409  107406
         return protocolChain;
 410  
     }
 411  
     
 412  
     
 413  
     /**
 414  
      * Set the {@link ProtocolChain} used by this {@link Context}.
 415  
      * @param protocolChain instance of {@link ProtocolChain} to be used by the Context
 416  
      */
 417  
     public void setProtocolChain(ProtocolChain protocolChain) {
 418  70566
         this.protocolChain = protocolChain;
 419  70566
     }
 420  
     
 421  
     
 422  
     /**
 423  
      * Get the current {@link SelectionKey} interest ops this instance is executing.
 424  
      * @return OpType the currentOpType.
 425  
      */
 426  
     public OpType getCurrentOpType() {
 427  96226
         return currentOpType;
 428  
     }
 429  
     
 430  
     
 431  
     /**
 432  
      * Set the current OpType value.
 433  
      * @param currentOpType sets current operation type
 434  
      */
 435  
     public void setCurrentOpType(OpType currentOpType) {
 436  161367
         this.currentOpType = currentOpType;
 437  161367
     }
 438  
 
 439  
     
 440  
     /**
 441  
      * Configure the {@link #currentOpType} based on the 
 442  
      * {@link SelectionKey#readyOps()} values.
 443  
      * @param key
 444  
      */
 445  
     protected void configureOpType(SelectionKey key) {
 446  12
         int readyOps = key.readyOps();   
 447  12
         switch (readyOps){
 448  
             case SelectionKey.OP_CONNECT:
 449  0
                 currentOpType = OpType.OP_CONNECT;
 450  0
                 break;
 451  
             case SelectionKey.OP_READ:
 452  12
                 currentOpType = OpType.OP_READ;
 453  12
                 break; 
 454  
             case SelectionKey.OP_WRITE:
 455  0
                 currentOpType = OpType.OP_WRITE;
 456  0
                 break; 
 457  
             case (SelectionKey.OP_WRITE | SelectionKey.OP_READ):
 458  0
                 currentOpType = OpType.OP_READ_WRITE;
 459  0
                 break;  
 460  
              case (SelectionKey.OP_ACCEPT):
 461  0
                 currentOpType = OpType.OP_ACCEPT;
 462  0
                 break;       
 463  
             /**
 464  
              * Fallback to an upcoming OP_CONNECT ops. This happens
 465  
              * because the {@link SocketChannel#finishConnect()} has not yet
 466  
              * been invoked.
 467  
              * 
 468  
              */
 469  
             default:
 470  0
                 currentOpType = OpType.OP_CONNECT;
 471  
                 break;
 472  
                 
 473  
         } 
 474  12
     }
 475  
     
 476  
         
 477  
     
 478  
     /**
 479  
      * Execute this Context using the Controller's Pipeline
 480  
      * @throws {@link PipelineFullException}
 481  
      * @deprecated
 482  
      */
 483  
     public void execute() throws PipelineFullException {
 484  
         // If a IOEvent has been defined, invoke it first and
 485  
         // let its associated CallbackHandler decide if the ProtocolChain
 486  
         // be invoked or not.
 487  0
         Object attachment = SelectionKeyAttachment.getAttachment(key);
 488  0
         if (ioEvent != null && (attachment instanceof CallbackHandler)) {
 489  0
             CallbackHandlerContextTask task = CallbackHandlerContextTask.poll();
 490  0
             task.setCallBackHandler((CallbackHandler) attachment);
 491  0
             execute(task);
 492  0
         } else {
 493  0
             execute(ProtocolChainContextTask.poll());
 494  
         }
 495  0
     }
 496  
 
 497  
     
 498  
     /**
 499  
      * Execute this Context using the Controller's Pipeline
 500  
      * @param contextTask {@link ContextTask}, which will be 
 501  
      *                    executed by {@link Pipeline}
 502  
      * @throws {@link PipelineFullException}
 503  
      */
 504  
     public void execute(ContextTask contextTask) throws PipelineFullException {
 505  102744
         execute(contextTask, true);
 506  102744
     }
 507  
     
 508  
     
 509  
     /**
 510  
      * Execute this Context using either Controller's Pipeline or current thread
 511  
      * @param contextTask {@link ContextTask}, which will be 
 512  
      *                    executed by {@link Pipeline}
 513  
      * @param runInSeparateThread if true - {@link ContextTask} will
 514  
      *      be executed in separate thread, false - in current thread.
 515  
      * @throws {@link PipelineFullException}
 516  
      */
 517  
     @SuppressWarnings("unchecked")
 518  
     public void execute(ContextTask contextTask, boolean runInSeparateThread) throws PipelineFullException {       
 519  161370
         if (protocolChain == null){
 520  
             ProtocolChainInstanceHandler 
 521  90804
                     pciHandler = getProtocolChainInstanceHandler();
 522  90804
             protocolChain = pciHandler.poll();
 523  
         }
 524  
         
 525  161370
         if (contextTask != null) {
 526  161370
             contextTask.setContext(this);
 527  161370
             if (runInSeparateThread) {
 528  161370
                 getPipeline().execute(contextTask);
 529  
             } else {
 530  
                 try {
 531  0
                     contextTask.call();
 532  0
                 } catch(Exception e) {
 533  0
                     Controller.logger().log(Level.SEVERE,
 534  
                             "Unexpected exception occured, when executing task: " + 
 535  
                             contextTask, e);
 536  0
                 }
 537  
             }
 538  
         }
 539  161370
     }
 540  
 
 541  
 
 542  
     /**
 543  
      * Return the {@link ProtocolChainInstanceListener} associated with this
 544  
      * {@link Context}
 545  
      * @return ProtocolChainInstanceListener
 546  
      */
 547  
     public ProtocolChainInstanceHandler getProtocolChainInstanceHandler() {
 548  252174
         ProtocolChainInstanceHandler protocolChainInstanceHandler =
 549  
                selectorHandler.getProtocolChainInstanceHandler();
 550  252173
         return protocolChainInstanceHandler != null ?
 551  
            protocolChainInstanceHandler :
 552  
            controller.getProtocolChainInstanceHandler();
 553  
     } 
 554  
     
 555  
     
 556  
     /**
 557  
      * Return the {@link Pipeline} executing this instance.
 558  
      * @return {@link Pipeline}
 559  
      */
 560  
     public Pipeline getPipeline() {
 561  161370
         if (pipeline == null && controller != null){
 562  90874
             pipeline = controller.getPipeline();
 563  
         }
 564  161370
         return pipeline;
 565  
     }
 566  
     
 567  
     
 568  
     /**
 569  
      * Set the {@link Pipeline} that will execute this instance.
 570  
      * @param pipeline  the {@link Pipeline} to set
 571  
      */
 572  
     public void setPipeline(Pipeline pipeline) {
 573  90804
         this.pipeline = pipeline;
 574  90804
     }
 575  
     
 576  
     
 577  
     /**
 578  
      * Set an optional CallbackHandler.
 579  
      * @param ioEvent  the {@link IOEvent} to set
 580  
      */
 581  
     protected void setIOEvent(IOEvent<Context> ioEvent){
 582  58626
         this.ioEvent = ioEvent;
 583  58626
     }
 584  
     
 585  
     /**
 586  
      * Return the current {@link IOEvent} associated with this
 587  
      * instance.
 588  
      * @return IOEvent the current {@link IOEvent} associated with this
 589  
      * instance.
 590  
      */
 591  
     protected IOEvent getIOEvent(){
 592  58626
         return ioEvent;
 593  
     }
 594  
     
 595  
     
 596  
     /**
 597  
      * Return the current {@link Controller#Protocol} this instance is executing.
 598  
      * @return the current Controller.Protocol this instance is executing.
 599  
      */
 600  
     public Controller.Protocol getProtocol() {
 601  133799
         return selectorHandler.protocol();
 602  
     }
 603  
     
 604  
     
 605  
     /**
 606  
      * @Deprecated
 607  
      *
 608  
      * Set the current {@link Controller#Protocol} this instance is executing.
 609  
      * @param protocol The current protocol.
 610  
      */
 611  
     public void setProtocol(Controller.Protocol protocol) {
 612  0
     }
 613  
     
 614  
     
 615  
     /**
 616  
      * Return the current {@link SelectorHandler} this instance is executing.
 617  
      * @return the current {@link SelectorHandler} this instance is executing.
 618  
      */
 619  
     public SelectorHandler getSelectorHandler() {
 620  426589
         return selectorHandler;
 621  
     }
 622  
     
 623  
     /**
 624  
      * Set the current {@link SelectorHandler} this instance is executing.
 625  
      * @param selectorHandler {@link SelectorHandler}
 626  
      */
 627  
     public void setSelectorHandler(SelectorHandler selectorHandler) {
 628  486285
         this.selectorHandler = selectorHandler;
 629  486285
     }
 630  
 
 631  
 
 632  
     /**
 633  
      * Returns {@link AsyncQueueReadable}, assciated with the current
 634  
      * {@link Context}. This method is not threadsafe.
 635  
      * 
 636  
      * @return {@link AsyncQueueReadable}
 637  
      */
 638  
     public AsyncQueueReadable getAsyncQueueReadable() {
 639  0
         if (asyncQueueReadable == null) {
 640  0
             asyncQueueReadable = new AsyncQueueReadableContextWrapper();
 641  
         }
 642  
         
 643  0
         return asyncQueueReadable;
 644  
     }
 645  
 
 646  
     /**
 647  
      * Returns {@link AsyncQueueWritable}, assciated with the current
 648  
      * {@link Context}. This method is not threadsafe.
 649  
      * 
 650  
      * @return {@link AsyncQueueWritable}
 651  
      */
 652  
     public AsyncQueueWritable getAsyncQueueWritable() {
 653  86662
         if (asyncQueueWritable == null) {
 654  41
             asyncQueueWritable = new AsyncQueueWritableContextWrapper();
 655  
         }
 656  
         
 657  86662
         return asyncQueueWritable;
 658  
     }
 659  
 
 660  
     /**
 661  
      * Return the {@linkAsyncQueueReader}
 662  
      * @return the {@linkAsyncQueueReader}
 663  
      */
 664  
     protected AsyncQueueReader getAsyncQueueReader() {
 665  0
         return asyncQueueReader;
 666  
     }
 667  
 
 668  
     /**
 669  
      * Set the {@linkAsyncQueueReader}
 670  
      * @param asyncQueueReader {@linkAsyncQueueReader}
 671  
      */
 672  
     protected void setAsyncQueueReader(AsyncQueueReader asyncQueueReader) {
 673  161370
         this.asyncQueueReader = asyncQueueReader;
 674  161370
     }
 675  
 
 676  
     /**
 677  
      * Return the {@linkAsyncQueueWriter}
 678  
      * @return the {@linkAsyncQueueWriter}
 679  
      */
 680  
     protected AsyncQueueWriter getAsyncQueueWriter() {
 681  0
         return asyncQueueWriter;
 682  
     }
 683  
 
 684  
     /**
 685  
      * Set the {@linkAsyncQueueWriter}
 686  
      * @param asyncQueueWriter {@linkAsyncQueueWriter}
 687  
      */
 688  
     protected void setAsyncQueueWriter(AsyncQueueWriter asyncQueueWriter) {
 689  161370
         this.asyncQueueWriter = asyncQueueWriter;
 690  161370
     }
 691  
     
 692  82
     private class AsyncQueueWritableContextWrapper implements AsyncQueueWritable {
 693  
         /**
 694  
         * {@inheritDoc}
 695  
         */
 696  
         public void writeToAsyncQueue(ByteBuffer buffer) throws IOException {
 697  0
             asyncQueueWriter.write(key, buffer);
 698  0
         }
 699  
 
 700  
         /**
 701  
          * {@inheritDoc}
 702  
          */
 703  
         public void writeToAsyncQueue(ByteBuffer buffer, 
 704  
                 AsyncWriteCallbackHandler callbackHandler) throws IOException {
 705  0
             asyncQueueWriter.write(key, buffer, callbackHandler);
 706  0
         }
 707  
 
 708  
         /**
 709  
          * {@inheritDoc}
 710  
          */
 711  
         public void writeToAsyncQueue(ByteBuffer buffer, 
 712  
                 AsyncWriteCallbackHandler callbackHandler,
 713  
                 AsyncQueueDataProcessor writePreProcessor) throws IOException {
 714  0
             asyncQueueWriter.write(key, buffer, callbackHandler, writePreProcessor);
 715  0
         }
 716  
 
 717  
         /**
 718  
          * {@inheritDoc}
 719  
          */
 720  
         public void writeToAsyncQueue(ByteBuffer buffer,
 721  
                 AsyncWriteCallbackHandler callbackHandler,
 722  
                 AsyncQueueDataProcessor writePreProcessor,
 723  
                 boolean isCloneByteBuffer) throws IOException {
 724  66662
             asyncQueueWriter.write(key, buffer, callbackHandler,
 725  
                     writePreProcessor, isCloneByteBuffer);
 726  66662
         }
 727  
         
 728  
         /**
 729  
         * {@inheritDoc}
 730  
         */
 731  
         public void writeToAsyncQueue(SocketAddress dstAddress, ByteBuffer buffer)
 732  
                 throws IOException {
 733  0
             asyncQueueWriter.write(key, dstAddress, buffer);
 734  0
         }
 735  
 
 736  
         /**
 737  
         * {@inheritDoc}
 738  
         */
 739  
         public void writeToAsyncQueue(SocketAddress dstAddress, ByteBuffer buffer,
 740  
                 AsyncWriteCallbackHandler callbackHandler) throws IOException {
 741  0
             asyncQueueWriter.write(key, dstAddress, buffer, 
 742  
                     callbackHandler);
 743  0
         }
 744  
 
 745  
         /**
 746  
         * {@inheritDoc}
 747  
         */
 748  
         public void writeToAsyncQueue(SocketAddress dstAddress, ByteBuffer buffer,
 749  
                 AsyncWriteCallbackHandler callbackHandler, 
 750  
                 AsyncQueueDataProcessor writePreProcessor) throws IOException {
 751  0
             asyncQueueWriter.write(key, dstAddress, buffer, 
 752  
                     callbackHandler, writePreProcessor);
 753  0
         }
 754  
 
 755  
         /**
 756  
         * {@inheritDoc}
 757  
         */
 758  
         public void writeToAsyncQueue(SocketAddress dstAddress, ByteBuffer buffer,
 759  
                 AsyncWriteCallbackHandler callbackHandler, 
 760  
                 AsyncQueueDataProcessor writePreProcessor, boolean isCloneByteBuffer)
 761  
                 throws IOException {
 762  20000
             asyncQueueWriter.write(key, dstAddress, buffer, 
 763  
                     callbackHandler, writePreProcessor, isCloneByteBuffer);
 764  20000
         }
 765  
     }
 766  
     
 767  0
     private class AsyncQueueReadableContextWrapper implements AsyncQueueReadable {
 768  
         /**
 769  
         * {@inheritDoc}
 770  
         */
 771  
         public void readFromAsyncQueue(ByteBuffer buffer, 
 772  
                 AsyncReadCallbackHandler callbackHandler) throws IOException {
 773  0
             asyncQueueReader.read(key, buffer, callbackHandler);
 774  0
         }
 775  
 
 776  
         /**
 777  
         * {@inheritDoc}
 778  
         */
 779  
         public void readFromAsyncQueue(ByteBuffer buffer, 
 780  
                 AsyncReadCallbackHandler callbackHandler, 
 781  
                 AsyncReadCondition condition) throws IOException {
 782  0
             asyncQueueReader.read(key, buffer, callbackHandler, condition);
 783  0
         }
 784  
 
 785  
         /**
 786  
         * {@inheritDoc}
 787  
         */
 788  
         public void readFromAsyncQueue(ByteBuffer buffer, 
 789  
                 AsyncReadCallbackHandler callbackHandler, 
 790  
                 AsyncReadCondition condition, 
 791  
                 AsyncQueueDataProcessor readPostProcessor) throws IOException {
 792  0
             asyncQueueReader.read(key, buffer, callbackHandler, 
 793  
                     condition, readPostProcessor);
 794  0
         }
 795  
     }
 796  
     
 797  
     
 798  
     /**
 799  
      * Suspend the execution of this {@link Context}. Suspending the execution
 800  
      * allow application to store the current instance, and re-use it later
 801  
      * by not only the  Thread used when called suspend, but also from any other Thread.
 802  
      * A suspended Context will not be re-used by any other transaction and Thread. 
 803  
      * A suspended Context will keep its current state intact, meaning its
 804  
      * SelectionKey, attributes, SelectorHandler, etc, will not change. Internally,
 805  
      * The Context will not be recyled and will not be re-used by any Thread.
 806  
      * 
 807  
      * When invoked this method will automatically set the 
 808  
      * {@link Context#setKeyRegistrationState} to {@link KeyRegistrationState}
 809  
      * to KeyRegistrationState.NONE.
 810  
      * 
 811  
      * Invoking this method many times as not effect once suspended. 
 812  
      */
 813  
     public void suspend(){
 814  0
         if (isSuspended) return;
 815  0
         isSuspended = true;
 816  0
         incrementRefCount();
 817  0
         setKeyRegistrationState(keyRegistrationState.NONE);               
 818  0
     }
 819  
     
 820  
     
 821  
     /**
 822  
      * Return <tt>true</tt> if this Context has been suspended by
 823  
      * invoking {@link suspend}. When suspended, invoking {@link Context#recycle}
 824  
      * will throw an {@link IllegalStateException}
 825  
      * @return <tt>true</tt> if this Context has been suspended
 826  
      */
 827  
     public boolean isSuspended(){
 828  0
         return isSuspended;
 829  
     }
 830  
     
 831  
     
 832  
     /**
 833  
      * Resume a {@link #suspend}ed {@link Context}. 
 834  
      *  <strong>Resume will not call {@link Context#recycle}</strong>. So
 835  
      * after the caller is finished using Context caller must
 836  
      * call {@link  Controller#returnContext(com.sun.grizzly.Context)}
 837  
      * to  mark it as a candidate  for being re-used by another Thread and connection.
 838  
      * 
 839  
      * <strong>Important. When resumed, all operations done on this
 840  
      * object are not thread-safe and there is probability that another
 841  
      * thread is already using this object. Never use this object once resumed.</strong>
 842  
      * 
 843  
      * When invoked this method will automatically set the 
 844  
      * {@link Context#setKeyRegistrationState} to {@link KeyRegistrationState}
 845  
      * to KeyRegistrationState.REGISTER and automatically re-enable read and 
 846  
      * write operations. 
 847  
      * 
 848  
      * If the Context hasn't been suspended, calling that method has no effet.
 849  
      */
 850  
     public void resume(){
 851  0
         if (!isSuspended) return;
 852  0
         isSuspended = false;
 853  0
         selectorHandler.register(key, SelectionKey.OP_READ);
 854  0
     }
 855  
     
 856  
     
 857  
     /**
 858  
      * Cancel a {@link #suspend}ed {@link Context}. Invoking this method will
 859  
      * automatically clean the state of this Context and mark it as a candidate
 860  
      * for being re-used by another Thread and connection. 
 861  
      * 
 862  
      * <strong>Important. When cancelled, all operations done on this
 863  
      * object are not thread-safe and there is probability that another
 864  
      * thread is already using this object. Never use this object once cancelled.</strong>
 865  
      * 
 866  
      * 
 867  
      * When invoked this method will automatically close the underlying 
 868  
      * connection (represented by its {@link SelectionKey}.
 869  
      * 
 870  
      * If the Context hasn't been suspended, calling that method has no effet.
 871  
      */
 872  
     public void cancel(){
 873  0
         if (!isSuspended) return;
 874  0
         isSuspended = false;
 875  0
         selectorHandler.getSelectionKeyHandler().cancel(key);
 876  0
         getController().returnContext(this);
 877  0
     }   
 878  
     /**
 879  
      * Called by outer Threads that are not instances of {@link WorkerThread} to
 880  
      * indicate that this {@link Context} should not be
 881  
      * {@link #recycle()} or offered back to its pool.
 882  
      * 
 883  
      * When a outer Thread is done with {@link Context} it must call
 884  
      * {@link Controller#returnContext(com.sun.grizzly.Context) to
 885  
      * ensure that {@link Context} will be properly recycled.
 886  
      * 
 887  
      * @return Current Thread reference count
 888  
      */
 889  
     public void incrementRefCount(){
 890  0
          refCounter.incrementAndGet();
 891  0
     } 
 892  
     
 893  
     /**
 894  
      * Decrements the reference count of this {@link Context}.
 895  
      * Threads wanting to release {@link Context} should not call
 896  
      * this method but instead use 
 897  
      * {@link Controller#returnContext(com.sun.grizzly.Context)}
 898  
      * @return return decremented reference count
 899  
      */
 900  
     public int  decrementRefCount(){
 901  161370
         return  refCounter.decrementAndGet();
 902  
 }
 903  
     
 904  
 }