dev@grizzly.java.net

Re: SelectionKey attachment unification

From: Jeanfrancois Arcand <Jeanfrancois.Arcand_at_Sun.COM>
Date: Thu, 14 Feb 2008 11:03:09 -0500

Salut,

Oleksiy Stashok wrote:
> Hi,
>
>
>>> some other place, where connection info could be stored.
>>> IMHO SelectionKey attachment could be good place for it.
>>
>> Performance wise, it can cause trouble so we need to be careful here:
>>
>> http://weblogs.java.net/blog/jfarcand/archive/2006/06/tricks_and_tips.html
>>
>>
>> Unifying/improving our solution is great, we just have to make sure
>> our users knows that can have potential issues.
> Agree. But that change we will not try to inspire people to use
> SelectionKey attachments where it's possible. But if they really need to
> - we will have better order there, which will reduce possibility of
> memory leaks and other possible problems.

Great :-)


>
>>> Think, in 2.x branch we will be able to have clear and complete
>>> SelectionKey attachment implementation, which will include
>>> CallbackHandlers etc.
>>
>>
>> Like discussed at the meeting, I would propose we implement a complete
>> solution (event if we break compatibility). Let's works on the proposal!
> Ok, here it is.

OK, the SSL issue is seriuous enough to release 1.7.2, and we need to
think about wow we fix the issue in 1.0.x. A very simple fix is to use
to store the EXPIRE_TIME the SelectionKey (which is unique) inside the
SSLSession. That way we won't have to refactor the 1.0.19 code like we
are doing for 1.7.x. Once you have a chance, can you log an issue here:

https://glassfish.dev.java.net/servlets/ProjectIssues

diffs looks good :-)

Thanks

-- Jeanfrancois

>
> Thanks.
>
> WBR,
> Alexey.
>>
>
> # This patch file was generated by NetBeans IDE
> # Following Index: paths are relative to: C:\Projects\Grizzly\trunk\modules
> # This patch can be applied using context Tools: Patch action on respective folder.
> # It uses platform neutral UTF-8 encoding and \n newlines.
> # Above lines and this line are ignored by the patching process.
> Index: grizzly/src/main/java/com/sun/grizzly/async/AsyncQueueReaderContextTask.java
> --- grizzly/src/main/java/com/sun/grizzly/async/AsyncQueueReaderContextTask.java Base (BASE)
> +++ grizzly/src/main/java/com/sun/grizzly/async/AsyncQueueReaderContextTask.java Locally Modified (Based On LOCAL)
> @@ -23,7 +23,7 @@
>
> package com.sun.grizzly.async;
>
> -import com.sun.grizzly.ContextTask;
> +import com.sun.grizzly.SelectionKeyContextTask;
> import java.nio.channels.SelectionKey;
>
>
> @@ -35,11 +35,11 @@
> *
> * @author Alexey Stashok
> */
> -public class AsyncQueueReaderContextTask extends ContextTask {
> +public class AsyncQueueReaderContextTask extends SelectionKeyContextTask {
> private static final TaskPool<AsyncQueueReaderContextTask> taskPool =
> new TaskPool<AsyncQueueReaderContextTask>() {
> @Override
> - public AsyncQueueReaderContextTask newTask() {
> + public AsyncQueueReaderContextTask newInstance() {
> return new AsyncQueueReaderContextTask();
> }
> };
> @@ -55,7 +55,7 @@
> taskPool.offer(contextTask);
> }
>
> - public Object call() throws Exception {
> + public Object doCall() throws Exception {
> try {
> SelectionKey selectionKey = context.getSelectionKey();
> if (selectionKey == null) {
> Index: grizzly/src/main/java/com/sun/grizzly/async/AsyncQueueWriterContextTask.java
> --- grizzly/src/main/java/com/sun/grizzly/async/AsyncQueueWriterContextTask.java Base (BASE)
> +++ grizzly/src/main/java/com/sun/grizzly/async/AsyncQueueWriterContextTask.java Locally Modified (Based On LOCAL)
> @@ -23,7 +23,7 @@
>
> package com.sun.grizzly.async;
>
> -import com.sun.grizzly.ContextTask;
> +import com.sun.grizzly.SelectionKeyContextTask;
> import java.nio.channels.SelectionKey;
>
>
> @@ -35,11 +35,11 @@
> *
> * @author Alexey Stashok
> */
> -public class AsyncQueueWriterContextTask extends ContextTask {
> +public class AsyncQueueWriterContextTask extends SelectionKeyContextTask {
> private static final TaskPool<AsyncQueueWriterContextTask> taskPool =
> new TaskPool<AsyncQueueWriterContextTask>() {
> @Override
> - public AsyncQueueWriterContextTask newTask() {
> + public AsyncQueueWriterContextTask newInstance() {
> return new AsyncQueueWriterContextTask();
> }
> };
> @@ -55,7 +55,7 @@
> taskPool.offer(contextTask);
> }
>
> - public Object call() throws Exception {
> + protected Object doCall() throws Exception {
> try {
> SelectionKey selectionKey = context.getSelectionKey();
> if (selectionKey == null) {
> Index: grizzly/src/main/java/com/sun/grizzly/CallbackHandlerContextTask.java
> --- grizzly/src/main/java/com/sun/grizzly/CallbackHandlerContextTask.java Base (BASE)
> +++ grizzly/src/main/java/com/sun/grizzly/CallbackHandlerContextTask.java Locally Modified (Based On LOCAL)
> @@ -33,11 +33,11 @@
> *
> * @author Alexey Stashok
> */
> -public class CallbackHandlerContextTask extends ContextTask {
> +public class CallbackHandlerContextTask extends SelectionKeyContextTask {
> private static final TaskPool<CallbackHandlerContextTask> taskPool =
> new TaskPool<CallbackHandlerContextTask>() {
> @Override
> - public CallbackHandlerContextTask newTask() {
> + public CallbackHandlerContextTask newInstance() {
> return new CallbackHandlerContextTask();
> }
> };
> @@ -53,7 +53,7 @@
> taskPool.offer(contextTask);
> }
>
> - public Object call() throws Exception {
> + protected Object doCall() throws Exception {
> IOEvent ioEvent = context.getIOEvent();
> OpType currentOpType = context.getCurrentOpType();
>
> @@ -93,6 +93,4 @@
> callBackHandler = null;
> super.recycle();
> }
> -
> -
> }
> Index: grizzly/src/main/java/com/sun/grizzly/Context.java
> --- grizzly/src/main/java/com/sun/grizzly/Context.java Base (BASE)
> +++ grizzly/src/main/java/com/sun/grizzly/Context.java Locally Modified (Based On LOCAL)
> @@ -32,6 +32,7 @@
> import com.sun.grizzly.async.AsyncReadCondition;
> import com.sun.grizzly.async.AsyncWriteCallbackHandler;
> import com.sun.grizzly.util.AttributeHolder;
> +import com.sun.grizzly.util.SelectionKeyAttachment;
> import java.io.IOException;
> import java.net.SocketAddress;
> import java.nio.ByteBuffer;
> @@ -373,7 +374,7 @@
> // If a IOEvent has been defined, invoke it first and
> // let its associated CallbackHandler decide if the ProtocolChain
> // be invoked or not.
> - Object attachment = key.attachment();
> + Object attachment = SelectionKeyAttachment.getAttachment(key);
> if (ioEvent != null && (attachment instanceof CallbackHandler)) {
> CallbackHandlerContextTask task = CallbackHandlerContextTask.poll();
> task.setCallBackHandler((CallbackHandler) attachment);
> Index: grizzly/src/main/java/com/sun/grizzly/ContextTask.java
> --- grizzly/src/main/java/com/sun/grizzly/ContextTask.java Base (BASE)
> +++ grizzly/src/main/java/com/sun/grizzly/ContextTask.java Locally Modified (Based On LOCAL)
> @@ -23,6 +23,7 @@
>
> package com.sun.grizzly;
>
> +import com.sun.grizzly.util.ConcurrentLinkedQueuePool;
> import java.util.concurrent.Callable;
> import java.util.concurrent.ConcurrentLinkedQueue;
>
> @@ -47,24 +48,13 @@
> context = null;
> }
>
> - protected abstract static class TaskPool<E extends ContextTask> {
> - private ConcurrentLinkedQueue<E> pool =
> - new ConcurrentLinkedQueue<E>();
> + protected abstract static class TaskPool<E extends ContextTask>
> + extends ConcurrentLinkedQueuePool<E> {
>
> - public abstract E newTask();
> -
> - public E poll() {
> - E task = pool.poll();
> - if (task == null) {
> - task = newTask();
> - }
> -
> - return task;
> - }
> -
> + @Override
> public void offer(E task) {
> task.recycle();
> - pool.offer(task);
> + super.offer(task);
> }
> }
> }
> Index: grizzly/src/main/java/com/sun/grizzly/Controller.java
> --- grizzly/src/main/java/com/sun/grizzly/Controller.java Base (BASE)
> +++ grizzly/src/main/java/com/sun/grizzly/Controller.java Locally Modified (Based On LOCAL)
> @@ -25,6 +25,7 @@
>
> import com.sun.grizzly.util.AttributeHolder;
> import com.sun.grizzly.util.Cloner;
> +import com.sun.grizzly.util.ConcurrentLinkedQueuePool;
> import com.sun.grizzly.util.Copyable;
> import com.sun.grizzly.util.State;
> import com.sun.grizzly.util.StateHolder;
> @@ -135,7 +136,7 @@
> /**
> * A cached list of Context. Context are by default stateless.
> */
> - private ConcurrentLinkedQueue<Context> contexts;
> + private ConcurrentLinkedQueuePool<Context> contexts;
>
>
> /**
> @@ -239,7 +240,13 @@
> * Controller constructor
> */
> public Controller() {
> - contexts = new ConcurrentLinkedQueue<Context>();
> + contexts = new ConcurrentLinkedQueuePool<Context>() {
> + @Override
> + public Context newInstance() {
> + return new Context();
> + }
> + };
> +
> stateHolder = new StateHolder<State>(true);
> }
>
> @@ -262,10 +269,8 @@
> ProtocolChainInstanceHandler pciHandler = null;
> ProtocolChain protocolChain = null;
> Context serverCtx = contexts.poll();
> - if (serverCtx == null){
> - serverCtx = new Context();
> serverCtx.setController(this);
> - }
> +
> serverCtx.setSelectorHandler(selectorHandler);
>
> try {
> @@ -474,9 +479,6 @@
> */
> public Context pollContext(SelectionKey key){
> Context ctx = contexts.poll();
> - if (ctx == null){
> - ctx = new Context();
> - }
> ctx.setController(this);
> ctx.setSelectionKey(key);
> return ctx;
> Index: grizzly/src/main/java/com/sun/grizzly/DefaultSelectionKeyHandler.java
> --- grizzly/src/main/java/com/sun/grizzly/DefaultSelectionKeyHandler.java Base (BASE)
> +++ grizzly/src/main/java/com/sun/grizzly/DefaultSelectionKeyHandler.java Locally Modified (Based On LOCAL)
> @@ -23,8 +23,9 @@
>
> package com.sun.grizzly;
>
> +import com.sun.grizzly.util.SelectionKeyAttachment;
> +import com.sun.grizzly.util.SelectionKeyActionAttachment;
> import com.sun.grizzly.util.Copyable;
> -import com.sun.grizzly.util.ThreadAttachment;
> import java.io.IOException;
> import java.net.Socket;
> import java.nio.channels.ClosedChannelException;
> @@ -34,11 +35,7 @@
> import java.util.Iterator;
> import java.util.logging.Level;
> import java.util.logging.Logger;
> -import javax.net.ssl.SSLEngine;
> -import javax.net.ssl.SSLSession;
>
> -import static com.sun.grizzly.filter.SSLReadFilter.EXPIRE_TIME;
> -import com.sun.grizzly.util.WorkerThread;
> import java.nio.channels.Selector;
>
> /**
> @@ -103,6 +100,12 @@
> * {_at_inheritDoc}
> */
> public void process(SelectionKey key) {
> + Object attachment = key.attachment();
> +
> + if (attachment instanceof SelectionKeyActionAttachment) {
> + ((SelectionKeyActionAttachment) attachment).process(key);
> + }
> +
> removeExpirationStamp(key);
> }
>
> @@ -238,7 +241,11 @@
> closeChannel(key.channel());
> }
>
> - key.attach(null);
> + Object attachment = key.attach(null);
> + if (attachment instanceof SelectionKeyAttachment) {
> + ((SelectionKeyAttachment) attachment).release(key);
> + }
> +
> key.cancel();
> key = null;
> }
> @@ -309,13 +316,8 @@
> if (attachment != null) {
> if (attachment instanceof Long) {
> key.attach(null);
> - } else if (attachment instanceof ThreadAttachment) {
> - ((WorkerThread) Thread.currentThread()).attach(
> - (ThreadAttachment) attachment);
> - key.attach(null);
> - } else if (attachment instanceof SSLEngine) {
> - SSLEngine sslEngine = (SSLEngine) attachment;
> - sslEngine.getSession().removeValue(EXPIRE_TIME);
> + } else if (attachment instanceof SelectionKeyAttachment) {
> + ((SelectionKeyAttachment) attachment).setTimeout(null);
> }
> }
> }
> @@ -331,11 +333,8 @@
> Object attachment = key.attachment();
> if (attachment == null) {
> key.attach(currentTime);
> - } else if (attachment instanceof ThreadAttachment) {
> - ((ThreadAttachment) attachment).setTimeout(currentTime);
> - } else if (attachment instanceof SSLEngine) {
> - SSLEngine sslEngine = (SSLEngine) attachment;
> - sslEngine.getSession().putValue(EXPIRE_TIME,currentTime);
> + } else if (attachment instanceof SelectionKeyAttachment) {
> + ((SelectionKeyAttachment) attachment).setTimeout(currentTime);
> }
> }
>
> @@ -356,17 +355,9 @@
> // can't predict the type of the attached object.
> if (attachment instanceof Long) {
> return (Long) attachment;
> - } else if (attachment instanceof SSLEngine) {
> - SSLSession sslSession = ((SSLEngine) attachment).getSession();
> - if (sslSession != null &&
> - sslSession.getValue(EXPIRE_TIME) != null) {
> - return (Long) sslSession.getValue(EXPIRE_TIME);
> + } else if (attachment instanceof SelectionKeyAttachment) {
> + return ((SelectionKeyAttachment) attachment).getTimeout();
> }
> -
> - return null;
> - } else if (attachment instanceof ThreadAttachment) {
> - return ((ThreadAttachment) attachment).getTimeout();
> - }
> } catch (ClassCastException ex) {
> if (logger.isLoggable(Level.FINEST)) {
> logger.log(Level.FINEST,
> Index: grizzly/src/main/java/com/sun/grizzly/filter/SSLReadFilter.java
> --- grizzly/src/main/java/com/sun/grizzly/filter/SSLReadFilter.java Base (BASE)
> +++ grizzly/src/main/java/com/sun/grizzly/filter/SSLReadFilter.java Locally Modified (Based On LOCAL)
> @@ -27,7 +27,9 @@
> import com.sun.grizzly.Controller;
> import com.sun.grizzly.ProtocolFilter;
> import com.sun.grizzly.SSLConfig;
> +import com.sun.grizzly.util.SSLSelectionKeyAttachment;
> import com.sun.grizzly.util.SSLUtils;
> +import com.sun.grizzly.util.SelectionKeyAttachment;
> import com.sun.grizzly.util.WorkerThreadImpl;
> import java.io.EOFException;
> import java.io.IOException;
> @@ -49,14 +51,6 @@
> * @author Jeanfrancois Arcand
> */
> public class SSLReadFilter implements ProtocolFilter{
> -
> - public final static String HANDSHAKE = "handshake";
> - public final static String DATA_DECODED = "dataDecoded";
> - public final static String INPUT_BB_REMAINDER = "inputBBRemainder";
> - public final static String OUTPUT_BB_REMAINDER = "outputBBRemainder";
> -
> -
> -
> /**
> * The <code>SSLContext</code> associated with the SSL implementation
> * we are running on.
> @@ -95,12 +89,6 @@
>
>
> /**
> - * Session keep-alive flag.
> - */
> - public final static String EXPIRE_TIME = "expireTime";
> -
> -
> - /**
> * Has the enabled protocol configured.
> */
> private boolean isProtocolConfigured = false;
> @@ -125,7 +113,6 @@
> public boolean execute(Context ctx) throws IOException {
> boolean result = true;
> int count = 0;
> - boolean isCopied = false;
> Throwable exception = null;
> SelectionKey key = ctx.getSelectionKey();
> WorkerThreadImpl workerThread;
> @@ -137,22 +124,18 @@
>
> SSLEngine sslEngine = newSSLEngine(key);
> workerThread.setSSLEngine(sslEngine);
> - key.attach(sslEngine);
> + if (key.attachment() == null) {
> + key.attach(SSLSelectionKeyAttachment.create(key, sslEngine));
> + }
>
> - boolean hasHandshake = Boolean.TRUE.equals(
> - sslEngine.getSession().getValue(HANDSHAKE));
> -
> - restoreSecuredBufferRemainders(sslEngine);
> + boolean hasHandshake = sslEngine.getSession().isValid();
> try {
> allocateBuffers();
> - isCopied = copyByteBufferToInputBB(sslEngine,
> - workerThread.getByteBuffer(), workerThread.getInputBB());
>
> if (hasHandshake) {
> count = doRead(key);
> } else if (doHandshake(key, SSLUtils.getReadTimeout())) {
> hasHandshake = true;
> - sslEngine.getSession().putValue(HANDSHAKE, Boolean.TRUE);
>
> // set "no available data" for secured output buffer
> ByteBuffer outputBB = workerThread.getOutputBB();
> @@ -168,12 +151,6 @@
> log("SSLReadFilter.execute",ex);
> } finally {
> if (exception != null || count == -1){
> - if (isCopied) {
> - /* if some data was copied from ByteBuffer,
> - * but connection got closed - clean inputBB */
> - workerThread.getInputBB().clear();
> - }
> -
> ctx.setAttribute(Context.THROWABLE,exception);
> ctx.setKeyRegistrationState(
> Context.KeyRegistrationState.CANCEL);
> @@ -199,8 +176,7 @@
> cancel(ctx.getSelectionKey());
> } else if (ctx.getKeyRegistrationState()
> == Context.KeyRegistrationState.REGISTER){
> - SSLEngine sslEngine = (SSLEngine) ctx.getSelectionKey().attachment();
> - saveSecuredBufferRemainders(sslEngine);
> + saveSecuredBufferRemainders(ctx.getSelectionKey());
> ctx.getSelectorHandler().register(ctx.getSelectionKey(),
> SelectionKey.OP_READ);
> ctx.setKeyRegistrationState(Context.KeyRegistrationState.NONE);
> @@ -295,20 +271,20 @@
> }
>
>
> - private static int doRead(SelectionKey key){
> + private static int doRead(SelectionKey key) {
> final WorkerThreadImpl workerThread =
> - (WorkerThreadImpl)Thread.currentThread();
> + (WorkerThreadImpl) Thread.currentThread();
> ByteBuffer byteBuffer = workerThread.getByteBuffer();
> ByteBuffer outputBB = workerThread.getOutputBB();
> ByteBuffer inputBB = workerThread.getInputBB();
> SSLEngine sslEngine = workerThread.getSSLEngine();
>
> int count = -1;
> - try{
> + try {
> // Read first bytes to avoid continuing if the client
> // closed the connection.
> - count = ((SocketChannel)key.channel()).read(inputBB);
> - if (count != -1){
> + count = ((SocketChannel) key.channel()).read(inputBB);
> + if (count != -1) {
> // Decrypt the bytes we just read.
> if (Controller.logger().isLoggable(Level.FINE)) {
> Controller.logger().log(Level.FINE,
> @@ -318,21 +294,20 @@
> }
>
> byteBuffer =
> - SSLUtils.unwrapAll(byteBuffer,inputBB,sslEngine);
> + SSLUtils.unwrapAll(byteBuffer, inputBB, sslEngine);
> workerThread.setInputBB(inputBB);
> workerThread.setOutputBB(outputBB);
> workerThread.setByteBuffer(byteBuffer);
> }
> return count;
> - } catch(IOException ex){
> + } catch (IOException ex) {
> log("Exception during SSL read.", ex);
> return -1;
> } finally {
> - if (count == -1){
> - try{
> + if (count == -1) {
> + try {
> sslEngine.closeInbound();
> - } catch (SSLException ex){
> - ;
> + } catch (SSLException ex) {
> }
> }
> }
> @@ -399,13 +374,12 @@
> SSLEngine sslEngine = null;
> if (key.attachment() == null){
> sslEngine = newSSLEngine();
> - } else if (key.attachment() instanceof SSLEngine){
> - sslEngine = (SSLEngine)key.attachment();
> + } else if (key.attachment() instanceof SSLSelectionKeyAttachment){
> + sslEngine = ((SSLSelectionKeyAttachment) SelectionKeyAttachment.getAttachment(key)).getSslEngine();
> } else {
> sslEngine = newSSLEngine();
> }
> sslEngine.setWantClientAuth(wantClientAuth);
> - sslEngine.getSession().removeValue(EXPIRE_TIME);
> sslEngine.setNeedClientAuth(needClientAuth);
> return sslEngine;
> }
> @@ -613,78 +587,28 @@
> return ciphers;
> }
>
> - /**
> - * If bytebuffer is not empty it means that previous
> - * <code>ProtocolFilter</code>s has read some data already. This data
> - * should be copied to the inputBB.
> - */
> - private static boolean copyByteBufferToInputBB(SSLEngine sslEngine,
> - ByteBuffer byteBuffer, ByteBuffer inputBB) {
> - if (byteBuffer.position() > 0) {
> - Boolean isDataDecoded =
> - (Boolean) sslEngine.getSession().getValue(DATA_DECODED);
> + private void saveSecuredBufferRemainders(SelectionKey selectionKey) {
> + SSLSelectionKeyAttachment attachment =
> + (SSLSelectionKeyAttachment) selectionKey.attachment();
>
> - if (!Boolean.TRUE.equals(isDataDecoded)) {
> - byteBuffer.flip();
> - inputBB.put(byteBuffer);
> - byteBuffer.clear();
> - return true;
> - } else if (isDataDecoded != null) {
> - sslEngine.getSession().removeValue(DATA_DECODED);
> - }
> - }
> -
> - return false;
> - }
> -
> - /**
> - * Restores (if required) secure buffers, associated with <code>SSLEngine</code>,
> - * which were saved during previous SSLReadFilter execution.
> - * It makes possible data, which wasn't processed on previous cycle to be processed now
> - */
> - private void restoreSecuredBufferRemainders(SSLEngine sslEngine) {
> - WorkerThreadImpl workerThread = (WorkerThreadImpl) Thread.currentThread();
> -
> - ByteBuffer inputBBRemainder = (ByteBuffer) sslEngine.getSession().
> - getValue(INPUT_BB_REMAINDER);
> - if (inputBBRemainder != null) {
> - sslEngine.getSession().removeValue(INPUT_BB_REMAINDER);
> - workerThread.setInputBB(inputBBRemainder);
> - }
> -
> - ByteBuffer outputBBRemainder = (ByteBuffer) sslEngine.getSession().
> - getValue(OUTPUT_BB_REMAINDER);
> - if (outputBBRemainder != null) {
> - sslEngine.getSession().removeValue(OUTPUT_BB_REMAINDER);
> - workerThread.setOutputBB(outputBBRemainder);
> - }
> - }
> -
> - /**
> - * Saves (if required) secure buffers, associated with <code>SSLEngine</code>
> - * If secured data, associated with <code>SSLEngine</code>, is not completely
> - * processed now (may be additional data is required) - then it could be processed
> - * on next SSLReadFilter execution.
> - */
> - private void saveSecuredBufferRemainders(SSLEngine sslEngine) {
> - WorkerThreadImpl workerThread = (WorkerThreadImpl) Thread.currentThread();
> -
> - if (sslEngine == null) {
> + if (attachment == null) {
> Controller.logger().log(Level.FINE,
> - "SSLEngine is NULL, when saving buffers");
> + "SelectionKey attachment is NULL, when saving buffers");
> return;
> }
>
> + WorkerThreadImpl workerThread = (WorkerThreadImpl) Thread.currentThread();
> +
> ByteBuffer inputBB = workerThread.getInputBB();
> if (inputBB != null && inputBB.hasRemaining()) {
> - sslEngine.getSession().putValue(INPUT_BB_REMAINDER, inputBB);
> workerThread.setInputBB(null);
> + attachment.setInputBB(inputBB);
> }
>
> ByteBuffer outputBB = workerThread.getOutputBB();
> if (outputBB != null && outputBB.hasRemaining()) {
> - sslEngine.getSession().putValue(OUTPUT_BB_REMAINDER, outputBB);
> workerThread.setOutputBB(null);
> + attachment.setOutputBB(outputBB);
> }
> }
>
> Index: grizzly/src/main/java/com/sun/grizzly/ProtocolChainContextTask.java
> --- grizzly/src/main/java/com/sun/grizzly/ProtocolChainContextTask.java Base (BASE)
> +++ grizzly/src/main/java/com/sun/grizzly/ProtocolChainContextTask.java Locally Modified (Based On LOCAL)
> @@ -24,8 +24,6 @@
>
> package com.sun.grizzly;
>
> -import java.nio.channels.SelectionKey;
> -
> /**
> * <code>ProtocolChain</code> task, which will be executed by
> * <code>Context</code>, when Context.execute(<code>ContextTask</code>)
> @@ -33,11 +31,11 @@
> *
> * @author Alexey Stashok
> */
> -public class ProtocolChainContextTask extends ContextTask {
> +public class ProtocolChainContextTask extends SelectionKeyContextTask {
> private static final TaskPool<ProtocolChainContextTask> taskPool =
> new TaskPool<ProtocolChainContextTask>() {
> @Override
> - public ProtocolChainContextTask newTask() {
> + public ProtocolChainContextTask newInstance() {
> return new ProtocolChainContextTask();
> }
> };
> @@ -51,16 +49,10 @@
> taskPool.offer(contextTask);
> }
>
> - public Object call() throws Exception {
> - SelectionKey currentKey = context.getSelectionKey();
> - SelectionKeyHandler selectionKeyHandler = context.
> - getSelectorHandler().getSelectionKeyHandler();
> -
> - selectionKeyHandler.process(currentKey);
> + protected Object doCall() throws Exception {
> try {
> context.getProtocolChain().execute(context);
> } finally {
> - selectionKeyHandler.postProcess(currentKey);
> offer(this);
> }
>
> Index: grizzly/src/main/java/com/sun/grizzly/SelectionKeyContextTask.java
> --- grizzly/src/main/java/com/sun/grizzly/SelectionKeyContextTask.java Locally New
> +++ grizzly/src/main/java/com/sun/grizzly/SelectionKeyContextTask.java Locally New
> @@ -0,0 +1,66 @@
> +/*
> + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
> + *
> + * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
> + *
> + * The contents of this file are subject to the terms of either the GNU
> + * General Public License Version 2 only ("GPL") or the Common Development
> + * and Distribution License("CDDL") (collectively, the "License"). You
> + * may not use this file except in compliance with the License. You can obtain
> + * a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html
> + * or glassfish/bootstrap/legal/LICENSE.txt. See the License for the specific
> + * language governing permissions and limitations under the License.
> + *
> + * When distributing the software, include this License Header Notice in each
> + * file and include the License file at glassfish/bootstrap/legal/LICENSE.txt.
> + * Sun designates this particular file as subject to the "Classpath" exception
> + * as provided by Sun in the GPL Version 2 section of the License file that
> + * accompanied this code. If applicable, add the following below the License
> + * Header, with the fields enclosed by brackets [] replaced by your own
> + * identifying information: "Portions Copyrighted [year]
> + * [name of copyright owner]"
> + *
> + * Contributor(s):
> + *
> + * If you wish your version of this file to be governed by only the CDDL or
> + * only the GPL Version 2, indicate your decision by adding "[Contributor]
> + * elects to include this software in this distribution under the [CDDL or GPL
> + * Version 2] license." If you don't indicate a single choice of license, a
> + * recipient has the option to distribute your version of this file under
> + * either the CDDL, the GPL Version 2 or to extend the choice of license to
> + * its licensees as provided above. However, if you add GPL Version 2 code
> + * and therefore, elected the GPL Version 2 license, then the option applies
> + * only if the new code is made subject to such option by the copyright
> + * holder.
> + */
> +
> +package com.sun.grizzly;
> +
> +import java.nio.channels.SelectionKey;
> +
> +/**
> + * Basic class for all <code>ContextTask</code>s, which are dealing with
> + * <code>SelectionKey</code>s
> + *
> + * @author Alexey Stashok
> + */
> +public abstract class SelectionKeyContextTask extends ContextTask {
> +
> + public final Object call() throws Exception {
> + Object result = null;
> + SelectionKey currentKey = context.getSelectionKey();
> + SelectionKeyHandler selectionKeyHandler = context.
> + getSelectorHandler().getSelectionKeyHandler();
> +
> + selectionKeyHandler.process(currentKey);
> + try {
> + result = doCall();
> + } finally {
> + selectionKeyHandler.postProcess(currentKey);
> + }
> +
> + return result;
> + }
> +
> + protected abstract Object doCall() throws Exception;
> +}
> Index: grizzly/src/main/java/com/sun/grizzly/SSLConnectorHandler.java
> --- grizzly/src/main/java/com/sun/grizzly/SSLConnectorHandler.java Base (BASE)
> +++ grizzly/src/main/java/com/sun/grizzly/SSLConnectorHandler.java Locally Modified (Based On LOCAL)
> @@ -1102,7 +1102,6 @@
> */
> private void registerSelectionKeyFor(int ops) {
> SelectionKey key = getSelectionKey();
> - key.attach(this);
> selectorHandler.register(key, ops);
> }
>
> @@ -1119,7 +1118,6 @@
>
> if (securedOutputBuffer.hasRemaining()) {
> SelectionKey key = socketChannel.keyFor(selectorHandler.getSelector());
> - key.attach(callbackHandler);
> selectorHandler.register(key, SelectionKey.OP_WRITE);
>
> return false;
> Index: grizzly/src/main/java/com/sun/grizzly/TCPConnectorHandler.java
> --- grizzly/src/main/java/com/sun/grizzly/TCPConnectorHandler.java Base (BASE)
> +++ grizzly/src/main/java/com/sun/grizzly/TCPConnectorHandler.java Locally Modified (Based On LOCAL)
> @@ -366,7 +366,6 @@
> int nRead = socketChannel.read(byteBuffer);
>
> if (nRead == 0){
> - key.attach(callbackHandler);
> selectorHandler.register(key,SelectionKey.OP_READ);
> }
> return nRead;
> @@ -406,7 +405,6 @@
> }
>
> if (totalWriteBytes == 0 && byteBuffer.hasRemaining()){
> - key.attach(callbackHandler);
> selectorHandler.register(key,SelectionKey.OP_WRITE);
> }
> return totalWriteBytes;
> @@ -537,10 +535,7 @@
>
> if (key == null) return;
>
> - key.cancel();
> - key.attach(null);
> -
> - selectorHandler.closeChannel(socketChannel);
> + selectorHandler.getSelectionKeyHandler().cancel(key);
> } else {
> socketChannel.close();
> }
> Index: grizzly/src/main/java/com/sun/grizzly/TCPSelectorHandler.java
> --- grizzly/src/main/java/com/sun/grizzly/TCPSelectorHandler.java Base (BASE)
> +++ grizzly/src/main/java/com/sun/grizzly/TCPSelectorHandler.java Locally Modified (Based On LOCAL)
> @@ -29,8 +29,10 @@
> import com.sun.grizzly.async.TCPAsyncQueueWriter;
> import com.sun.grizzly.async.AsyncQueueWriterContextTask;
> import com.sun.grizzly.async.TCPAsyncQueueReader;
> +import com.sun.grizzly.util.CallbackHandlerSelectionKeyAttachment;
> import com.sun.grizzly.util.Cloner;
> import com.sun.grizzly.util.Copyable;
> +import com.sun.grizzly.util.SelectionKeyAttachment;
> import com.sun.grizzly.util.SelectionKeyOP;
> import com.sun.grizzly.util.SelectionKeyOP.ConnectSelectionKeyOP;
> import com.sun.grizzly.util.State;
> @@ -401,11 +403,22 @@
> }
>
> socketChannel.configureBlocking(false);
> - boolean isConnected = socketChannel.connect(remoteAddress);
> SelectionKey key = socketChannel.register(selector,
> - SelectionKey.OP_CONNECT, callbackHandler);
> + SelectionKey.OP_CONNECT);
> + key.attach(CallbackHandlerSelectionKeyAttachment.create(key, callbackHandler));
>
> - // if channel was connected immediately
> + boolean isConnected = false;
> + try {
> + isConnected = socketChannel.connect(remoteAddress);
> + } catch(IOException e) {
> + if (logger.isLoggable(Level.FINE)) {
> + logger.log(Level.FINE, "IOException occured when tried to connect socket", e);
> + }
> +
> + isConnected = true;
> + }
> +
> + // if channel was connected immediately or exception occured
> if (isConnected) {
> onConnectInterest(key, ctx);
> }
> @@ -610,7 +623,7 @@
> throws IOException{
> // disable OP_READ on key before doing anything else
> key.interestOps(key.interestOps() & (~SelectionKey.OP_READ));
> - Object attach = key.attachment();
> + Object attach = SelectionKeyAttachment.getAttachment(key);
>
> if (asyncQueueReader.isAsyncQueueReaderEnabledFor(key)) {
> final Context context = pollContext(ctx, key);
> @@ -646,7 +659,8 @@
> context.setCurrentOpType(Context.OpType.OP_WRITE);
> invokeAsyncQueueWriter(context);
> return false;
> - } else if ((attach = key.attachment()) instanceof CallbackHandler){
> + } else if ((attach = SelectionKeyAttachment.getAttachment(key))
> + instanceof CallbackHandler){
> final Context context = pollContext(ctx, key);
> context.setCurrentOpType(Context.OpType.OP_WRITE);
> invokeCallbackHandler((CallbackHandler) attach, context);
> @@ -671,7 +685,7 @@
> key.interestOps(key.interestOps() & (~SelectionKey.OP_WRITE));
> key.interestOps(key.interestOps() & (~SelectionKey.OP_READ));
>
> - Object attach = key.attachment();
> + Object attach = SelectionKeyAttachment.getAttachment(key);
> if (attach instanceof CallbackHandler){
> final Context context = pollContext(ctx, key);
> context.setCurrentOpType(Context.OpType.OP_CONNECT);
> Index: grizzly/src/main/java/com/sun/grizzly/UDPConnectorHandler.java
> --- grizzly/src/main/java/com/sun/grizzly/UDPConnectorHandler.java Base (BASE)
> +++ grizzly/src/main/java/com/sun/grizzly/UDPConnectorHandler.java Locally Modified (Based On LOCAL)
> @@ -60,38 +60,38 @@
> /**
> * The underlying UDPSelectorHandler used to mange SelectionKeys.
> */
> - private UDPSelectorHandler selectorHandler;
> + protected UDPSelectorHandler selectorHandler;
>
>
> /**
> * A <code>CallbackHandler</code> handler invoked by the UDPSelectorHandler
> * when a non blocking operation is ready to be processed.
> */
> - private CallbackHandler callbackHandler;
> + protected CallbackHandler callbackHandler;
>
>
> /**
> * The connection's DatagramChannel.
> */
> - private DatagramChannel datagramChannel;
> + protected DatagramChannel datagramChannel;
>
>
> /**
> * Is the connection established.
> */
> - private volatile boolean isConnected;
> + protected volatile boolean isConnected;
>
>
> /**
> * The internal Controller used (in case not specified).
> */
> - private Controller controller;
> + protected Controller controller;
>
>
> /**
> * IsConnected Latch related
> */
> - private CountDownLatch isConnectedLatch;
> + protected CountDownLatch isConnectedLatch;
>
>
> /**
> @@ -104,7 +104,7 @@
> * A blocking <code>InputStream</code> that use a pool of Selector
> * to execute a blocking read operation.
> */
> - private ByteBufferInputStream inputStream;
> + protected ByteBufferInputStream inputStream;
>
>
> /**
> @@ -192,7 +192,6 @@
> isConnectedLatch = new CountDownLatch(1);
>
> selectorHandler.connect(remoteAddress,localAddress,callbackHandler);
> - inputStream = new ByteBufferInputStream();
>
> try {
> isConnectedLatch.await(30, TimeUnit.SECONDS);
> @@ -294,6 +293,9 @@
>
> SelectionKey key = datagramChannel.keyFor(selectorHandler.getSelector());
> if (blocking){
> + if (inputStream == null) {
> + inputStream = new ByteBufferInputStream();
> + }
> inputStream.setSelectionKey(key);
> inputStream.setChannelType(
> ByteBufferInputStream.ChannelType.DatagramChannel);
> @@ -307,7 +309,6 @@
> int nRead = datagramChannel.read(byteBuffer);
>
> if (nRead == 0){
> - key.attach(callbackHandler);
> selectorHandler.register(key, SelectionKey.OP_READ);
> }
> return nRead;
> @@ -338,7 +339,6 @@
> int nWrite = datagramChannel.write(byteBuffer);
>
> if (nWrite == 0){
> - key.attach(callbackHandler);
> selectorHandler.register(key, SelectionKey.OP_WRITE);
> }
> return nWrite;
> @@ -513,10 +513,7 @@
>
> if (key == null) return;
>
> - key.cancel();
> - key.attach(null);
> -
> - selectorHandler.closeChannel(datagramChannel);
> + selectorHandler.getSelectionKeyHandler().cancel(key);
> } else {
> datagramChannel.close();
> }
> @@ -542,8 +539,10 @@
>
> datagramChannel = (DatagramChannel)key.channel();
> isConnected = datagramChannel.isConnected();
> + if (isConnectedLatch != null) {
> isConnectedLatch.countDown();
> }
> + }
>
>
> /**
> Index: grizzly/src/main/java/com/sun/grizzly/UDPSelectorHandler.java
> --- grizzly/src/main/java/com/sun/grizzly/UDPSelectorHandler.java Base (BASE)
> +++ grizzly/src/main/java/com/sun/grizzly/UDPSelectorHandler.java Locally Modified (Based On LOCAL)
> @@ -25,6 +25,7 @@
>
> import com.sun.grizzly.async.UDPAsyncQueueReader;
> import com.sun.grizzly.async.UDPAsyncQueueWriter;
> +import com.sun.grizzly.util.CallbackHandlerSelectionKeyAttachment;
> import com.sun.grizzly.util.Copyable;
> import com.sun.grizzly.util.SelectionKeyOP;
> import com.sun.grizzly.util.State;
> @@ -154,7 +155,8 @@
> datagramChannel.configureBlocking(false);
> datagramChannel.connect(remoteAddress);
> SelectionKey key = datagramChannel.register(selector,
> - SelectionKey.OP_READ | SelectionKey.OP_WRITE, callbackHandler);
> + SelectionKey.OP_READ | SelectionKey.OP_WRITE);
> + key.attach(CallbackHandlerSelectionKeyAttachment.create(key, callbackHandler));
> onConnectInterest(key, ctx);
> }
>
> Index: grizzly/src/main/java/com/sun/grizzly/util/CallbackHandlerSelectionKeyAttachment.java
> --- grizzly/src/main/java/com/sun/grizzly/util/CallbackHandlerSelectionKeyAttachment.java Locally New
> +++ grizzly/src/main/java/com/sun/grizzly/util/CallbackHandlerSelectionKeyAttachment.java Locally New
> @@ -0,0 +1,86 @@
> +/*
> + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
> + *
> + * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
> + *
> + * The contents of this file are subject to the terms of either the GNU
> + * General Public License Version 2 only ("GPL") or the Common Development
> + * and Distribution License("CDDL") (collectively, the "License"). You
> + * may not use this file except in compliance with the License. You can obtain
> + * a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html
> + * or glassfish/bootstrap/legal/LICENSE.txt. See the License for the specific
> + * language governing permissions and limitations under the License.
> + *
> + * When distributing the software, include this License Header Notice in each
> + * file and include the License file at glassfish/bootstrap/legal/LICENSE.txt.
> + * Sun designates this particular file as subject to the "Classpath" exception
> + * as provided by Sun in the GPL Version 2 section of the License file that
> + * accompanied this code. If applicable, add the following below the License
> + * Header, with the fields enclosed by brackets [] replaced by your own
> + * identifying information: "Portions Copyrighted [year]
> + * [name of copyright owner]"
> + *
> + * Contributor(s):
> + *
> + * If you wish your version of this file to be governed by only the CDDL or
> + * only the GPL Version 2, indicate your decision by adding "[Contributor]
> + * elects to include this software in this distribution under the [CDDL or GPL
> + * Version 2] license." If you don't indicate a single choice of license, a
> + * recipient has the option to distribute your version of this file under
> + * either the CDDL, the GPL Version 2 or to extend the choice of license to
> + * its licensees as provided above. However, if you add GPL Version 2 code
> + * and therefore, elected the GPL Version 2 license, then the option applies
> + * only if the new code is made subject to such option by the copyright
> + * holder.
> + */
> +
> +package com.sun.grizzly.util;
> +
> +import com.sun.grizzly.CallbackHandler;
> +import java.nio.channels.SelectionKey;
> +import java.util.concurrent.atomic.AtomicReference;
> +
> +/**
> + * <code>SelectionKey</code> attachment, which wraps <code>CallbackHandler</code>
> + *
> + * @author Alexey Stashok
> + */
> +public class CallbackHandlerSelectionKeyAttachment extends SelectionKeyAttachmentWrapper<CallbackHandler> {
> + private static ConcurrentLinkedQueuePool<CallbackHandlerSelectionKeyAttachment> pool =
> + new ConcurrentLinkedQueuePool<CallbackHandlerSelectionKeyAttachment>() {
> +
> + @Override
> + public CallbackHandlerSelectionKeyAttachment newInstance() {
> + return new CallbackHandlerSelectionKeyAttachment();
> + }
> + };
> +
> + // Is used for key pooling
> + private AtomicReference<SelectionKey> associatedKey = new AtomicReference<SelectionKey>();
> +
> +
> + /**
> + * Creates the <code>CallbackHandler</code> to the <code>SelectionKey</code>
> + * CallbackHandler will not be attached directly, but wrapped with
> + * <code>CallbackHandlerSelectionKeyAttachment</code>
> + */
> + public static CallbackHandlerSelectionKeyAttachment create(SelectionKey key,
> + CallbackHandler callbackHandler) {
> + CallbackHandlerSelectionKeyAttachment attachment = pool.poll();
> +
> + attachment.associatedKey.set(key);
> + attachment.setAttachment(callbackHandler);
> + return attachment;
> + }
> +
> + private CallbackHandlerSelectionKeyAttachment() {
> + }
> +
> + @Override
> + public void release(SelectionKey selectionKey) {
> + if (associatedKey.getAndSet(null) == selectionKey) {
> + super.release(selectionKey);
> + pool.offer(this);
> + }
> + }
> +}
> Index: grizzly/src/main/java/com/sun/grizzly/util/ConcurrentLinkedQueuePool.java
> --- grizzly/src/main/java/com/sun/grizzly/util/ConcurrentLinkedQueuePool.java Locally New
> +++ grizzly/src/main/java/com/sun/grizzly/util/ConcurrentLinkedQueuePool.java Locally New
> @@ -0,0 +1,60 @@
> +/*
> + * The contents of this file are subject to the terms
> + * of the Common Development and Distribution License
> + * (the License). You may not use this file except in
> + * compliance with the License.
> + *
> + * You can obtain a copy of the license at
> + * https://glassfish.dev.java.net/public/CDDLv1.0.html or
> + * glassfish/bootstrap/legal/CDDLv1.0.txt.
> + * See the License for the specific language governing
> + * permissions and limitations under the License.
> + *
> + * When distributing Covered Code, include this CDDL
> + * Header Notice in each file and include the License file
> + * at glassfish/bootstrap/legal/CDDLv1.0.txt.
> + * If applicable, add the following below the CDDL Header,
> + * with the fields enclosed by brackets [] replaced by
> + * you own identifying information:
> + * "Portions Copyrighted [year] [name of copyright owner]"
> + *
> + * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
> + */
> +
> +package com.sun.grizzly.util;
> +
> +import java.util.concurrent.ConcurrentLinkedQueue;
> +
> +/**
> + * <code>ObjectPool</code> implementation based on <code>ConcurrentLinkedQueue</code>
> + *
> + * @author Alexey Stashok
> + */
> +public abstract class ConcurrentLinkedQueuePool<E> implements ObjectPool<E> {
> + private volatile ConcurrentLinkedQueue<E> pool;
> +
> + public abstract E newInstance();
> +
> + public E poll() {
> + if (pool == null) {
> + synchronized(this) {
> + if (pool == null) {
> + pool = new ConcurrentLinkedQueue<E>();
> + }
> + }
> + }
> +
> + E object = pool.poll();
> + if (object == null) {
> + object = newInstance();
> + }
> +
> + return object;
> + }
> +
> + public void offer(E object) {
> + if (pool != null) {
> + pool.offer(object);
> + }
> + }
> +}
> Index: grizzly/src/main/java/com/sun/grizzly/util/ObjectPool.java
> --- grizzly/src/main/java/com/sun/grizzly/util/ObjectPool.java Locally New
> +++ grizzly/src/main/java/com/sun/grizzly/util/ObjectPool.java Locally New
> @@ -0,0 +1,35 @@
> +/*
> + * The contents of this file are subject to the terms
> + * of the Common Development and Distribution License
> + * (the License). You may not use this file except in
> + * compliance with the License.
> + *
> + * You can obtain a copy of the license at
> + * https://glassfish.dev.java.net/public/CDDLv1.0.html or
> + * glassfish/bootstrap/legal/CDDLv1.0.txt.
> + * See the License for the specific language governing
> + * permissions and limitations under the License.
> + *
> + * When distributing Covered Code, include this CDDL
> + * Header Notice in each file and include the License file
> + * at glassfish/bootstrap/legal/CDDLv1.0.txt.
> + * If applicable, add the following below the CDDL Header,
> + * with the fields enclosed by brackets [] replaced by
> + * you own identifying information:
> + * "Portions Copyrighted [year] [name of copyright owner]"
> + *
> + * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
> + */
> +
> +package com.sun.grizzly.util;
> +
> +/**
> + * Basic interface for object pool implementations
> + *
> + * @author Alexey Stashok
> + */
> +public interface ObjectPool<E> {
> + public E poll();
> +
> + public void offer(E object);
> +}
> Index: grizzly/src/main/java/com/sun/grizzly/util/SelectionKeyActionAttachment.java
> --- grizzly/src/main/java/com/sun/grizzly/util/SelectionKeyActionAttachment.java Locally New
> +++ grizzly/src/main/java/com/sun/grizzly/util/SelectionKeyActionAttachment.java Locally New
> @@ -0,0 +1,50 @@
> +/*
> + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
> + *
> + * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
> + *
> + * The contents of this file are subject to the terms of either the GNU
> + * General Public License Version 2 only ("GPL") or the Common Development
> + * and Distribution License("CDDL") (collectively, the "License"). You
> + * may not use this file except in compliance with the License. You can obtain
> + * a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html
> + * or glassfish/bootstrap/legal/LICENSE.txt. See the License for the specific
> + * language governing permissions and limitations under the License.
> + *
> + * When distributing the software, include this License Header Notice in each
> + * file and include the License file at glassfish/bootstrap/legal/LICENSE.txt.
> + * Sun designates this particular file as subject to the "Classpath" exception
> + * as provided by Sun in the GPL Version 2 section of the License file that
> + * accompanied this code. If applicable, add the following below the License
> + * Header, with the fields enclosed by brackets [] replaced by your own
> + * identifying information: "Portions Copyrighted [year]
> + * [name of copyright owner]"
> + *
> + * Contributor(s):
> + *
> + * If you wish your version of this file to be governed by only the CDDL or
> + * only the GPL Version 2, indicate your decision by adding "[Contributor]
> + * elects to include this software in this distribution under the [CDDL or GPL
> + * Version 2] license." If you don't indicate a single choice of license, a
> + * recipient has the option to distribute your version of this file under
> + * either the CDDL, the GPL Version 2 or to extend the choice of license to
> + * its licensees as provided above. However, if you add GPL Version 2 code
> + * and therefore, elected the GPL Version 2 license, then the option applies
> + * only if the new code is made subject to such option by the copyright
> + * holder.
> + */
> +
> +package com.sun.grizzly.util;
> +
> +import java.nio.channels.SelectionKey;
> +
> +/**
> + * Class represents extended version of <code>SelectionKeyAttachment</code>,
> + * and introduces process method, which will be called by framework once
> + * <code>SelectionKey</code> has some ready event, before actual event processing.
> + *
> + * @author Alexey Stashok
> + */
> +public abstract class SelectionKeyActionAttachment extends SelectionKeyAttachment {
> + public abstract void process(SelectionKey selectionKey);
> +}
> Index: grizzly/src/main/java/com/sun/grizzly/util/SelectionKeyAttachment.java
> --- grizzly/src/main/java/com/sun/grizzly/util/SelectionKeyAttachment.java Locally New
> +++ grizzly/src/main/java/com/sun/grizzly/util/SelectionKeyAttachment.java Locally New
> @@ -0,0 +1,70 @@
> +/*
> + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
> + *
> + * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
> + *
> + * The contents of this file are subject to the terms of either the GNU
> + * General Public License Version 2 only ("GPL") or the Common Development
> + * and Distribution License("CDDL") (collectively, the "License"). You
> + * may not use this file except in compliance with the License. You can obtain
> + * a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html
> + * or glassfish/bootstrap/legal/LICENSE.txt. See the License for the specific
> + * language governing permissions and limitations under the License.
> + *
> + * When distributing the software, include this License Header Notice in each
> + * file and include the License file at glassfish/bootstrap/legal/LICENSE.txt.
> + * Sun designates this particular file as subject to the "Classpath" exception
> + * as provided by Sun in the GPL Version 2 section of the License file that
> + * accompanied this code. If applicable, add the following below the License
> + * Header, with the fields enclosed by brackets [] replaced by your own
> + * identifying information: "Portions Copyrighted [year]
> + * [name of copyright owner]"
> + *
> + * Contributor(s):
> + *
> + * If you wish your version of this file to be governed by only the CDDL or
> + * only the GPL Version 2, indicate your decision by adding "[Contributor]
> + * elects to include this software in this distribution under the [CDDL or GPL
> + * Version 2] license." If you don't indicate a single choice of license, a
> + * recipient has the option to distribute your version of this file under
> + * either the CDDL, the GPL Version 2 or to extend the choice of license to
> + * its licensees as provided above. However, if you add GPL Version 2 code
> + * and therefore, elected the GPL Version 2 license, then the option applies
> + * only if the new code is made subject to such option by the copyright
> + * holder.
> + */
> +
> +package com.sun.grizzly.util;
> +
> +import java.nio.channels.SelectionKey;
> +
> +/**
> + * Basic class for all SelectionKey attachments.
> + * Custom attachments should be inherited from it.
> + *
> + * @author Alexey Stashok
> + */
> +public abstract class SelectionKeyAttachment {
> + private Long timeout;
> +
> + public static Object getAttachment(SelectionKey key) {
> + Object attachment = key.attachment();
> + if (attachment instanceof SelectionKeyAttachmentWrapper) {
> + return ((SelectionKeyAttachmentWrapper) attachment).getAttachment();
> + }
> +
> + return attachment;
> + }
> +
> + public Long getTimeout() {
> + return timeout;
> + }
> +
> + public void setTimeout(Long timeout) {
> + this.timeout = timeout;
> + }
> +
> + public void release(SelectionKey selectionKey) {
> + timeout = null;
> + }
> +}
> Index: grizzly/src/main/java/com/sun/grizzly/util/SelectionKeyAttachmentWrapper.java
> --- grizzly/src/main/java/com/sun/grizzly/util/SelectionKeyAttachmentWrapper.java Locally New
> +++ grizzly/src/main/java/com/sun/grizzly/util/SelectionKeyAttachmentWrapper.java Locally New
> @@ -0,0 +1,70 @@
> +/*
> + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
> + *
> + * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
> + *
> + * The contents of this file are subject to the terms of either the GNU
> + * General Public License Version 2 only ("GPL") or the Common Development
> + * and Distribution License("CDDL") (collectively, the "License"). You
> + * may not use this file except in compliance with the License. You can obtain
> + * a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html
> + * or glassfish/bootstrap/legal/LICENSE.txt. See the License for the specific
> + * language governing permissions and limitations under the License.
> + *
> + * When distributing the software, include this License Header Notice in each
> + * file and include the License file at glassfish/bootstrap/legal/LICENSE.txt.
> + * Sun designates this particular file as subject to the "Classpath" exception
> + * as provided by Sun in the GPL Version 2 section of the License file that
> + * accompanied this code. If applicable, add the following below the License
> + * Header, with the fields enclosed by brackets [] replaced by your own
> + * identifying information: "Portions Copyrighted [year]
> + * [name of copyright owner]"
> + *
> + * Contributor(s):
> + *
> + * If you wish your version of this file to be governed by only the CDDL or
> + * only the GPL Version 2, indicate your decision by adding "[Contributor]
> + * elects to include this software in this distribution under the [CDDL or GPL
> + * Version 2] license." If you don't indicate a single choice of license, a
> + * recipient has the option to distribute your version of this file under
> + * either the CDDL, the GPL Version 2 or to extend the choice of license to
> + * its licensees as provided above. However, if you add GPL Version 2 code
> + * and therefore, elected the GPL Version 2 license, then the option applies
> + * only if the new code is made subject to such option by the copyright
> + * holder.
> + */
> +
> +package com.sun.grizzly.util;
> +
> +import java.nio.channels.SelectionKey;
> +
> +/**
> + * <code>SelectionKey</code> attachment utility class.
> + * This class could be used as wrapper for custom <code>SelectionKey</code>
> + * attachments, which are not subclasses of <code>SelectionKeyAttachment</code>
> + * class.
> + *
> + * @author Alexey Stashok
> + */
> +public class SelectionKeyAttachmentWrapper<E> extends SelectionKeyActionAttachment {
> + private E attachment;
> +
> + public E getAttachment() {
> + return attachment;
> + }
> +
> + public void setAttachment(E attachment) {
> + this.attachment = attachment;
> + }
> +
> + @Override
> + public void process(SelectionKey selectionKey) {
> + // Do nothing by default
> + }
> +
> + @Override
> + public void release(SelectionKey selectionKey) {
> + attachment = null;
> + super.release(selectionKey);
> + }
> +}
> Index: grizzly/src/main/java/com/sun/grizzly/util/SelectionKeyOP.java
> --- grizzly/src/main/java/com/sun/grizzly/util/SelectionKeyOP.java Base (BASE)
> +++ grizzly/src/main/java/com/sun/grizzly/util/SelectionKeyOP.java Locally Modified (Based On LOCAL)
> @@ -27,7 +27,6 @@
> import java.net.SocketAddress;
> import java.nio.channels.SelectableChannel;
> import java.nio.channels.SelectionKey;
> -import java.util.concurrent.ConcurrentLinkedQueue;
>
> /**
> *
> @@ -38,27 +37,29 @@
> private SelectionKey key;
> private SelectableChannel channel;
>
> - private static ConcurrentLinkedQueue<SelectionKeyOP> readWritePool =
> - new ConcurrentLinkedQueue<SelectionKeyOP>();
> + private static ConcurrentLinkedQueuePool<SelectionKeyOP> readWritePool =
> + new ConcurrentLinkedQueuePool<SelectionKeyOP>() {
> + @Override
> + public SelectionKeyOP newInstance() {
> + return new SelectionKeyOP();
> + }
> + };
>
> - private static ConcurrentLinkedQueue<SelectionKeyOP> connectPool =
> - new ConcurrentLinkedQueue<SelectionKeyOP>();
> + private static ConcurrentLinkedQueuePool<SelectionKeyOP> connectPool =
> + new ConcurrentLinkedQueuePool<SelectionKeyOP>() {
> + @Override
> + public SelectionKeyOP newInstance() {
> + return new ConnectSelectionKeyOP();
> + }
> + };
>
> public static SelectionKeyOP aquireSelectionKeyOP(int op) {
> if (op == SelectionKey.OP_READ || op == SelectionKey.OP_WRITE ||
> op == (SelectionKey.OP_WRITE | SelectionKey.OP_READ)) {
> SelectionKeyOP operation = readWritePool.poll();
> - if (operation == null) {
> - operation = new SelectionKeyOP();
> - }
> -
> return operation;
> } else if (op == SelectionKey.OP_CONNECT) {
> SelectionKeyOP operation = connectPool.poll();
> - if (operation == null) {
> - operation = new ConnectSelectionKeyOP();
> - }
> -
> \ No newline at end of file
> return operation;
> }
>
> Index: grizzly/src/main/java/com/sun/grizzly/util/SSLSelectionKeyAttachment.java
> --- grizzly/src/main/java/com/sun/grizzly/util/SSLSelectionKeyAttachment.java Locally New
> +++ grizzly/src/main/java/com/sun/grizzly/util/SSLSelectionKeyAttachment.java Locally New
> @@ -0,0 +1,150 @@
> +/*
> + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
> + *
> + * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
> + *
> + * The contents of this file are subject to the terms of either the GNU
> + * General Public License Version 2 only ("GPL") or the Common Development
> + * and Distribution License("CDDL") (collectively, the "License"). You
> + * may not use this file except in compliance with the License. You can obtain
> + * a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html
> + * or glassfish/bootstrap/legal/LICENSE.txt. See the License for the specific
> + * language governing permissions and limitations under the License.
> + *
> + * When distributing the software, include this License Header Notice in each
> + * file and include the License file at glassfish/bootstrap/legal/LICENSE.txt.
> + * Sun designates this particular file as subject to the "Classpath" exception
> + * as provided by Sun in the GPL Version 2 section of the License file that
> + * accompanied this code. If applicable, add the following below the License
> + * Header, with the fields enclosed by brackets [] replaced by your own
> + * identifying information: "Portions Copyrighted [year]
> + * [name of copyright owner]"
> + *
> + * Contributor(s):
> + *
> + * If you wish your version of this file to be governed by only the CDDL or
> + * only the GPL Version 2, indicate your decision by adding "[Contributor]
> + * elects to include this software in this distribution under the [CDDL or GPL
> + * Version 2] license." If you don't indicate a single choice of license, a
> + * recipient has the option to distribute your version of this file under
> + * either the CDDL, the GPL Version 2 or to extend the choice of license to
> + * its licensees as provided above. However, if you add GPL Version 2 code
> + * and therefore, elected the GPL Version 2 license, then the option applies
> + * only if the new code is made subject to such option by the copyright
> + * holder.
> + */
> +package com.sun.grizzly.util;
> +
> +import java.nio.ByteBuffer;
> +import java.nio.channels.SelectionKey;
> +import java.util.concurrent.atomic.AtomicReference;
> +import javax.net.ssl.SSLEngine;
> +
> +/**
> + * <code>SelectionKeyAttachment</code> implementation, which is targeted for SSL
> + * support.
> + *
> + * @author Alexey Stashok
> + */
> +public class SSLSelectionKeyAttachment extends SelectionKeyActionAttachment {
> +
> + private static ConcurrentLinkedQueuePool<SSLSelectionKeyAttachment> pool =
> + new ConcurrentLinkedQueuePool<SSLSelectionKeyAttachment>() {
> +
> + @Override
> + public SSLSelectionKeyAttachment newInstance() {
> + return new SSLSelectionKeyAttachment();
> + }
> + };
> +
> + private SSLEngine sslEngine;
> + private ByteBuffer inputBB;
> + private ByteBuffer outputBB;
> +
> + // Is used for key pooling
> + private AtomicReference<SelectionKey> associatedKey = new AtomicReference<SelectionKey>();
> +
> +
> + /**
> + * Saves (if required) secure buffers, associated with <code>SSLEngine</code>
> + * If secured data, associated with <code>SSLEngine</code>, is not completely
> + * processed now (may be additional data is required) - then it could be processed
> + * on next SSLReadFilter execution.
> + */
> + public static SSLSelectionKeyAttachment create(SelectionKey key,
> + SSLEngine sslEngine) {
> + SSLSelectionKeyAttachment attachment = pool.poll();
> +
> + attachment.associatedKey.set(key);
> + attachment.setInputBB(null);
> + attachment.setOutputBB(null);
> +
> + attachment.setSslEngine(sslEngine);
> + return attachment;
> + }
> +
> + private SSLSelectionKeyAttachment() {
> + }
> +
> + public ByteBuffer getInputBB() {
> + return inputBB;
> + }
> +
> + public void setInputBB(ByteBuffer inputBB) {
> + this.inputBB = inputBB;
> + }
> +
> + public ByteBuffer getOutputBB() {
> + return outputBB;
> + }
> +
> + public void setOutputBB(ByteBuffer outputBB) {
> + this.outputBB = outputBB;
> + }
> +
> + public SSLEngine getSslEngine() {
> + return sslEngine;
> + }
> +
> + public void setSslEngine(SSLEngine sslEngine) {
> + this.sslEngine = sslEngine;
> + }
> +
> + /**
> + * Restores (if required) secure buffers, associated with <code>SSLEngine</code>,
> + * which were saved during previous SSLReadFilter execution.
> + * It makes possible data, which wasn't processed on previous cycle to be processed now
> + */
> + @Override
> + public void process(SelectionKey selectionKey) {
> + WorkerThreadImpl workerThread;
> + try {
> + workerThread = (WorkerThreadImpl) Thread.currentThread();
> + } catch (ClassCastException ex) {
> + throw new IllegalStateException(ex.getMessage());
> + }
> +
> + if (inputBB != null) {
> + workerThread.setInputBB(inputBB);
> + inputBB = null;
> + }
> +
> + if (outputBB != null) {
> + workerThread.setOutputBB(outputBB);
> + outputBB = null;
> + }
> +
> + workerThread.setSSLEngine(sslEngine);
> + }
> +
> + @Override
> + public void release(SelectionKey selectionKey) {
> + if (associatedKey.getAndSet(null) == selectionKey) {
> + sslEngine = null;
> + inputBB = null;
> + outputBB = null;
> + super.release(selectionKey);
> + pool.offer(this);
> + }
> + }
> +}
> \ No newline at end of file
> Index: grizzly/src/main/java/com/sun/grizzly/util/ThreadAttachment.java
> --- grizzly/src/main/java/com/sun/grizzly/util/ThreadAttachment.java Base (BASE)
> +++ grizzly/src/main/java/com/sun/grizzly/util/ThreadAttachment.java Locally Modified (Based On LOCAL)
> @@ -23,6 +23,7 @@
> package com.sun.grizzly.util;
>
> import java.nio.ByteBuffer;
> +import java.nio.channels.SelectionKey;
> import java.util.WeakHashMap;
> import javax.net.ssl.SSLEngine;
>
> @@ -32,12 +33,9 @@
> *
> * @author Jeanfrancois Arcand
> */
> -public class ThreadAttachment {
> +public class ThreadAttachment extends SelectionKeyActionAttachment {
>
>
> - private long timeout;
> -
> -
> private String threadId;
>
>
> @@ -169,22 +167,13 @@
> this.threadId = threadId;
> }
>
> -
> /**
> - * Set the timeout used by the SelectionKeyHandler to times out an idle
> - * connection.
> + * SelectionKey attachment processing
> + * @param selectionKey
> */
> - public void setTimeout(long timeout){
> - this.timeout = timeout;
> + public void process(SelectionKey selectionKey) {
> + ((WorkerThread) Thread.currentThread()).attach(
> + (ThreadAttachment) this);
> + selectionKey.attach(null);
> }
> -
> -
> - /**
> - * Return the timeout used by the SelectionKeyHandler to times out an idle
> - * connection.
> - */
> - public long getTimeout(){
> - return timeout;
> }
> -
> -}
> Index: grizzly/src/main/java/com/sun/grizzly/util/WorkerThreadImpl.java
> --- grizzly/src/main/java/com/sun/grizzly/util/WorkerThreadImpl.java Base (BASE)
> +++ grizzly/src/main/java/com/sun/grizzly/util/WorkerThreadImpl.java Locally Modified (Based On LOCAL)
> @@ -294,11 +294,11 @@
> * @return a new ThreadAttachment
> */
> public ThreadAttachment detach(boolean copyState) {
> - if (threadAttachment == null){
> + if (threadAttachment == null) {
> threadAttachment = new ThreadAttachment();
> }
>
> - try{
> + try {
> threadAttachment.setByteBuffer(byteBuffer);
> threadAttachment.setSSLEngine(sslEngine);
> threadAttachment.setInputBB(inputBB);
> @@ -308,7 +308,7 @@
> } finally {
> // We cannot cache/re-use this object as it might be referenced
> // by more than one thread.
> - if (copyState){
> + if (copyState) {
> // Re-create a new ByteBuffer
> byteBuffer = ByteBufferFactory.allocate(byteBufferType,
> initialByteBufferSize);
> Index: grizzly/src/test/java/com/sun/grizzly/ClientCacheTest.java
> --- grizzly/src/test/java/com/sun/grizzly/ClientCacheTest.java Base (BASE)
> +++ grizzly/src/test/java/com/sun/grizzly/ClientCacheTest.java Locally Modified (Based On LOCAL)
> @@ -131,6 +131,7 @@
>
> controller.setProtocolChainInstanceHandler(
> new DefaultProtocolChainInstanceHandler(){
> + @Override
> public ProtocolChain poll() {
> ProtocolChain protocolChain = protocolChains.poll();
> if (protocolChain == null){
> @@ -175,10 +176,8 @@
> try {
> int nRead = socketChannel.read(readBB);
> if (nRead == 0 && readTry++ < 2){
> - key.attach(callbackHandler);
> - controller.registerKey(key,
> - SelectionKey.OP_READ,
> - Controller.Protocol.TCP);
> + ioEvent.attachment().getSelectorHandler().register(key,
> + SelectionKey.OP_READ);
> } else {
> responseArrivedLatchHolder[0].countDown();
> }
> @@ -196,10 +195,8 @@
> int nWrite = socketChannel.write(writeBB);
>
> if (nWrite == 0){
> - key.attach(callbackHandler);
> - controller.registerKey(key,
> - SelectionKey.OP_WRITE,
> - Controller.Protocol.TCP);
> + ioEvent.attachment().getSelectorHandler().register(key,
> + SelectionKey.OP_WRITE);
> return;
> }
> }
> Index: grizzly/src/test/java/com/sun/grizzly/TCPAsyncQueueWriterTest.java
> --- grizzly/src/test/java/com/sun/grizzly/TCPAsyncQueueWriterTest.java Base (BASE)
> +++ grizzly/src/test/java/com/sun/grizzly/TCPAsyncQueueWriterTest.java Locally Modified (Based On LOCAL)
> @@ -214,7 +214,6 @@
> try {
> int nRead = socketChannel.read(readBB);
> if (readBB.hasRemaining()){
> - key.attach(callbackHandler);
> selectorHandler.register(key, SelectionKey.OP_READ);
> } else {
> responseArrivedLatchHolder[0].countDown();
> Index: grizzly/src/test/java/com/sun/grizzly/TCPConnectorHandlerTest.java
> --- grizzly/src/test/java/com/sun/grizzly/TCPConnectorHandlerTest.java Base (BASE)
> +++ grizzly/src/test/java/com/sun/grizzly/TCPConnectorHandlerTest.java Locally Modified (Based On LOCAL)
> @@ -278,7 +278,6 @@
> try {
> int nRead = socketChannel.read(readBB);
> if (nRead == 0 && readTry++ < 2){
> - key.attach(callbackHandler);
> selectorHandler.register(key, SelectionKey.OP_READ);
> } else {
> responseArrivedLatchHolder[0].countDown();
> @@ -299,7 +298,6 @@
> int nWrite = socketChannel.write(writeBB);
>
> if (nWrite == 0){
> - key.attach(callbackHandler);
> selectorHandler.register(key, SelectionKey.OP_WRITE);
> return;
> }
> Index: grizzly/src/test/java/com/sun/grizzly/UDPAsyncQueueWriterTest.java
> --- grizzly/src/test/java/com/sun/grizzly/UDPAsyncQueueWriterTest.java Base (BASE)
> +++ grizzly/src/test/java/com/sun/grizzly/UDPAsyncQueueWriterTest.java Locally Modified (Based On LOCAL)
> @@ -214,7 +214,6 @@
> try {
> int nRead = socketChannel.read(readBB);
> if (readBB.hasRemaining()){
> - key.attach(callbackHandler);
> selectorHandler.register(key, SelectionKey.OP_READ);
> } else {
> responseArrivedLatchHolder[0].countDown();
> Index: portunif/src/main/java/com/sun/grizzly/portunif/TLSPUPreProcessor.java
> --- portunif/src/main/java/com/sun/grizzly/portunif/TLSPUPreProcessor.java Base (BASE)
> +++ portunif/src/main/java/com/sun/grizzly/portunif/TLSPUPreProcessor.java Locally Modified (Based On LOCAL)
> @@ -26,8 +26,9 @@
> import com.sun.grizzly.Context;
> import com.sun.grizzly.Controller;
> import com.sun.grizzly.SSLConfig;
> -import com.sun.grizzly.filter.SSLReadFilter;
> +import com.sun.grizzly.util.SSLSelectionKeyAttachment;
> import com.sun.grizzly.util.SSLUtils;
> +import com.sun.grizzly.util.SelectionKeyAttachment;
> import java.io.EOFException;
> import java.io.IOException;
> import java.nio.ByteBuffer;
> @@ -50,12 +51,7 @@
>
> private static final String TMP_DECODED_BUFFER ="TMP_DECODED_BUFFER";
>
> - /**
> - * Decrypted ByteBuffer default size.
> - */
> - private final static int appBBSize = 5 * 4096;
>
> -
> /**
> * The <code>SSLContext</code> associated with the SSL implementation
> * we are running on.
> @@ -108,14 +104,14 @@
>
>
> SSLEngine sslEngine = null;
> - Object attachment = key.attachment();
> - if (attachment == null || !(attachment instanceof SSLEngine)) {
> + Object attachment = SelectionKeyAttachment.getAttachment(key);
> + if (attachment == null || !(attachment instanceof SSLSelectionKeyAttachment)) {
> sslEngine = sslContext.createSSLEngine();
> sslEngine.setUseClientMode(false);
> sslEngine.setNeedClientAuth(needClientAuth);
> sslEngine.setWantClientAuth(wantClientAuth);
> } else {
> - sslEngine = (SSLEngine) attachment;
> + sslEngine = ((SSLSelectionKeyAttachment) attachment).getSslEngine();
> }
>
> ByteBuffer inputBB = protocolRequest.getSecuredInputByteBuffer();
> @@ -146,8 +142,7 @@
> inputBB.put((ByteBuffer) byteBuffer.flip());
> byteBuffer.clear();
>
> - boolean OK = Boolean.TRUE.equals(
> - sslEngine.getSession().getValue(SSLReadFilter.HANDSHAKE));
> + boolean OK = sslEngine.getSession().isValid();
>
> if (!OK) { // Handshake wasn't completed on prev step
> HandshakeStatus handshakeStatus = HandshakeStatus.NEED_UNWRAP;
> @@ -156,8 +151,7 @@
> byteBuffer = SSLUtils.doHandshake(channel, byteBuffer,
> inputBB, outputBB, sslEngine, handshakeStatus,
> SSLUtils.getReadTimeout(), inputBB.position() > 0);
> - sslEngine.getSession().putValue(SSLReadFilter.HANDSHAKE, true);
> - key.attach(sslEngine);
> + key.attach(SSLSelectionKeyAttachment.create(key, sslEngine));
> protocolRequest.setSSLEngine(sslEngine);
> // set "no available data" for secured output buffer
> outputBB.limit(outputBB.position());
> @@ -196,8 +190,6 @@
> if (byteRead > -1) {
> byteBuffer = SSLUtils.unwrapAll(byteBuffer, inputBB, sslEngine);
> protocolRequest.setByteBuffer(byteBuffer);
> - sslEngine.getSession().putValue(SSLReadFilter.DATA_DECODED,
> - Boolean.TRUE);
> } else {
> throw new EOFException();
> }
> Index: portunif/src/test/java/com/sun/grizzly/portunif/SimpleProtocolHandler.java
> --- portunif/src/test/java/com/sun/grizzly/portunif/SimpleProtocolHandler.java Base (BASE)
> +++ portunif/src/test/java/com/sun/grizzly/portunif/SimpleProtocolHandler.java Locally Modified (Based On LOCAL)
> @@ -25,13 +25,14 @@
>
> import com.sun.grizzly.Context;
> import com.sun.grizzly.Controller;
> +import com.sun.grizzly.util.SSLSelectionKeyAttachment;
> import com.sun.grizzly.util.OutputWriter;
> import com.sun.grizzly.util.SSLOutputWriter;
> +import com.sun.grizzly.util.SelectionKeyAttachment;
> import java.io.IOException;
> import java.nio.ByteBuffer;
> import java.nio.channels.SelectionKey;
> import java.util.logging.Level;
> -import javax.net.ssl.SSLEngine;
>
> /**
> * @author Alexey Stashok
> @@ -78,9 +79,9 @@
> buffer.position(pos);
> }
>
> - Object attachment = protocolRequest.getSelectionKey().attachment();
> - if (attachment instanceof SSLEngine) {
> - protocolRequest.setSSLEngine((SSLEngine) attachment);
> + Object attachment = SelectionKeyAttachment.getAttachment(protocolRequest.getSelectionKey());
> + if (attachment instanceof SSLSelectionKeyAttachment) {
> + protocolRequest.setSSLEngine(((SSLSelectionKeyAttachment) attachment).getSslEngine());
> allocateBuffers(protocolRequest);
> } else {
> protocolRequest.setSSLEngine(null);
>
>
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: dev-unsubscribe_at_grizzly.dev.java.net
> For additional commands, e-mail: