qpid-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ritch...@apache.org
Subject svn commit: r711822 - in /incubator/qpid/trunk/qpid/java/client/src: main/java/org/apache/qpid/client/protocol/ test/java/org/apache/qpid/client/ test/java/org/apache/qpid/client/protocol/
Date Thu, 06 Nov 2008 09:56:59 GMT
Author: ritchiem
Date: Thu Nov  6 01:56:56 2008
New Revision: 711822

URL: http://svn.apache.org/viewvc?rev=711822&view=rev
Log:
QPID-1431 : Prevent listeners being added to _frameListeners when an exception state has occured
due to connection closure. This adds additional synchronisation to the error handling condition.
It also removes the need for a CopyOnWriteArrayList that was perhaps the wrong data structure
for this list.

Added:
    incubator/qpid/trunk/qpid/java/client/src/test/java/org/apache/qpid/client/MockAMQConnection.java
    incubator/qpid/trunk/qpid/java/client/src/test/java/org/apache/qpid/client/protocol/
    incubator/qpid/trunk/qpid/java/client/src/test/java/org/apache/qpid/client/protocol/AMQProtocolHandlerTest.java
    incubator/qpid/trunk/qpid/java/client/src/test/java/org/apache/qpid/client/protocol/MockIoSession.java
Modified:
    incubator/qpid/trunk/qpid/java/client/src/main/java/org/apache/qpid/client/protocol/AMQProtocolHandler.java

Modified: incubator/qpid/trunk/qpid/java/client/src/main/java/org/apache/qpid/client/protocol/AMQProtocolHandler.java
URL: http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/java/client/src/main/java/org/apache/qpid/client/protocol/AMQProtocolHandler.java?rev=711822&r1=711821&r2=711822&view=diff
==============================================================================
--- incubator/qpid/trunk/qpid/java/client/src/main/java/org/apache/qpid/client/protocol/AMQProtocolHandler.java
(original)
+++ incubator/qpid/trunk/qpid/java/client/src/main/java/org/apache/qpid/client/protocol/AMQProtocolHandler.java
Thu Nov  6 01:56:56 2008
@@ -452,13 +452,16 @@
      */
     public void propagateExceptionToFrameListeners(Exception e)
     {
-        if (!_frameListeners.isEmpty())
+        synchronized (_frameListeners)
         {
-            final Iterator it = _frameListeners.iterator();
-            while (it.hasNext())
+            if (!_frameListeners.isEmpty())
             {
-                final AMQMethodListener ml = (AMQMethodListener) it.next();
-                ml.error(e);
+                final Iterator it = _frameListeners.iterator();
+                while (it.hasNext())
+                {
+                    final AMQMethodListener ml = (AMQMethodListener) it.next();
+                    ml.error(e);
+                }
             }
         }
     }
@@ -558,18 +561,20 @@
         {
 
             boolean wasAnyoneInterested = getStateManager().methodReceived(evt);
-            if (!_frameListeners.isEmpty())
+            synchronized (_frameListeners)
             {
-                //This iterator is safe from the error state as the frame listeners always
add before they send so their
-                // will be ready and waiting for this response.
-                Iterator it = _frameListeners.iterator();
-                while (it.hasNext())
+                if (!_frameListeners.isEmpty())
                 {
-                    final AMQMethodListener listener = (AMQMethodListener) it.next();
-                    wasAnyoneInterested = listener.methodReceived(evt) || wasAnyoneInterested;
+                    //This iterator is safe from the error state as the frame listeners always
add before they send so their
+                    // will be ready and waiting for this response.
+                    Iterator it = _frameListeners.iterator();
+                    while (it.hasNext())
+                    {
+                        final AMQMethodListener listener = (AMQMethodListener) it.next();
+                        wasAnyoneInterested = listener.methodReceived(evt) || wasAnyoneInterested;
+                    }
                 }
             }
-
             if (!wasAnyoneInterested)
             {
                 throw new AMQException(null, "AMQMethodEvent " + evt + " was not processed
by any listener.  Listeners:"
@@ -659,6 +664,24 @@
                     throw _lastFailoverException;
                 }
 
+                if(_stateManager.getCurrentState() == AMQState.CONNECTION_CLOSED)
+                {
+                    Exception e = _stateManager.getLastException();
+                    if (e != null)
+                    {
+                        if (e instanceof AMQException)
+                        {
+                            AMQException amqe = (AMQException) e;
+
+                            amqe.rethrow();
+                        }
+                        else
+                        {
+                            throw new AMQException(AMQConstant.INTERNAL_ERROR, e.getMessage(),
e);
+                        }
+                    }
+                }
+
                 _frameListeners.add(listener);
                 //FIXME: At this point here we should check or before add we should check
_stateManager is in an open
                 // state so as we don't check we are likely just to time out here as I believe
is being seen in QPID-1255 

Added: incubator/qpid/trunk/qpid/java/client/src/test/java/org/apache/qpid/client/MockAMQConnection.java
URL: http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/java/client/src/test/java/org/apache/qpid/client/MockAMQConnection.java?rev=711822&view=auto
==============================================================================
--- incubator/qpid/trunk/qpid/java/client/src/test/java/org/apache/qpid/client/MockAMQConnection.java
(added)
+++ incubator/qpid/trunk/qpid/java/client/src/test/java/org/apache/qpid/client/MockAMQConnection.java
Thu Nov  6 01:56:56 2008
@@ -0,0 +1,94 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.client;
+
+import org.apache.qpid.AMQException;
+import org.apache.qpid.client.state.AMQState;
+import org.apache.qpid.framing.ProtocolVersion;
+import org.apache.qpid.jms.ConnectionURL;
+import org.apache.qpid.jms.BrokerDetails;
+import org.apache.qpid.url.URLSyntaxException;
+
+import java.io.IOException;
+
+public class MockAMQConnection extends AMQConnection
+{
+    public MockAMQConnection(String broker, String username, String password, String clientName,
String virtualHost)
+            throws AMQException, URLSyntaxException
+    {
+        super(broker, username, password, clientName, virtualHost);
+    }
+
+    public MockAMQConnection(String broker, String username, String password, String clientName,
String virtualHost, SSLConfiguration sslConfig)
+            throws AMQException, URLSyntaxException
+    {
+        super(broker, username, password, clientName, virtualHost, sslConfig);
+    }
+
+    public MockAMQConnection(String host, int port, String username, String password, String
clientName, String virtualHost)
+            throws AMQException, URLSyntaxException
+    {
+        super(host, port, username, password, clientName, virtualHost);
+    }
+
+    public MockAMQConnection(String host, int port, String username, String password, String
clientName, String virtualHost, SSLConfiguration sslConfig)
+            throws AMQException, URLSyntaxException
+    {
+        super(host, port, username, password, clientName, virtualHost, sslConfig);
+    }
+
+    public MockAMQConnection(String host, int port, boolean useSSL, String username, String
password, String clientName, String virtualHost, SSLConfiguration sslConfig)
+            throws AMQException, URLSyntaxException
+    {
+        super(host, port, useSSL, username, password, clientName, virtualHost, sslConfig);
+    }
+
+    public MockAMQConnection(String connection)
+            throws AMQException, URLSyntaxException
+    {
+        super(connection);
+    }
+
+    public MockAMQConnection(String connection, SSLConfiguration sslConfig)
+            throws AMQException, URLSyntaxException
+    {
+        super(connection, sslConfig);
+    }
+
+    public MockAMQConnection(ConnectionURL connectionURL, SSLConfiguration sslConfig)
+            throws AMQException
+    {
+        super(connectionURL, sslConfig);
+    }
+
+    protected MockAMQConnection(String username, String password, String clientName, String
virtualHost)
+    {
+        super(username, password, clientName, virtualHost);
+    }
+
+    @Override
+    public ProtocolVersion makeBrokerConnection(BrokerDetails brokerDetail) throws IOException,
AMQException
+    {
+        _connected = true;
+        _protocolHandler.getStateManager().changeState(AMQState.CONNECTION_OPEN);
+        return null;
+    }
+}

Added: incubator/qpid/trunk/qpid/java/client/src/test/java/org/apache/qpid/client/protocol/AMQProtocolHandlerTest.java
URL: http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/java/client/src/test/java/org/apache/qpid/client/protocol/AMQProtocolHandlerTest.java?rev=711822&view=auto
==============================================================================
--- incubator/qpid/trunk/qpid/java/client/src/test/java/org/apache/qpid/client/protocol/AMQProtocolHandlerTest.java
(added)
+++ incubator/qpid/trunk/qpid/java/client/src/test/java/org/apache/qpid/client/protocol/AMQProtocolHandlerTest.java
Thu Nov  6 01:56:56 2008
@@ -0,0 +1,297 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.client.protocol;
+
+import junit.framework.TestCase;
+import org.apache.qpid.framing.AMQFrame;
+import org.apache.qpid.framing.AMQBody;
+import org.apache.qpid.framing.AMQMethodBody;
+import org.apache.qpid.framing.amqp_8_0.BasicRecoverOkBodyImpl;
+import org.apache.qpid.AMQException;
+import org.apache.qpid.protocol.AMQConstant;
+import org.apache.qpid.client.MockAMQConnection;
+import org.apache.qpid.client.AMQAuthenticationException;
+import org.apache.qpid.client.state.AMQState;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * This is a test address QPID-1431 where frame listeners would fail to be notified of an
incomming exception.
+ *
+ * Currently we do checks at the Session level to ensure that the connection/session are
open. However, it is possible
+ * for the connection to close AFTER this check has been performed.
+ *
+ * Performing a similar check at the frameListener level in AMQProtocolHandler makes most
sence as this will prevent
+ * listening when there can be no returning frames.
+ *
+ * With the correction in place it also means that the new listener will either make it on
to the list for notification
+ * or it will be notified of any existing exception due to the connection being closed.
+ *
+ * There may still be an issue in this space if the client utilises a second thread to close
the session as there will
+ * be no exception set to throw and so the wait will occur. That said when the session is
closed the framelisteners
+ * should be notified. Not sure this is tested.
+ */
+public class AMQProtocolHandlerTest extends TestCase
+{
+    private static final Logger _logger = LoggerFactory.getLogger(AMQProtocolHandlerTest.class);
+
+    // The handler to test
+    AMQProtocolHandler _handler;
+
+    // A frame to block upon whilst waiting the exception
+    AMQFrame _blockFrame;
+
+    // Latch to know when the listener receives an exception
+    private CountDownLatch _handleCountDown;
+    // The listener that will receive an exception
+    BlockToAccessFrameListener _listener;
+
+    @Override
+    public void setUp() throws Exception
+    {
+        //Create a new ProtocolHandler with a fake connection.
+        _handler = new AMQProtocolHandler(new MockAMQConnection("amqp://guest:guest@client/test?brokerlist='vm://:1'"));
+
+        _handler.sessionCreated(new MockIoSession());
+
+         AMQBody body = BasicRecoverOkBodyImpl.getFactory().newInstance(null, 1);
+        _blockFrame = new AMQFrame(0, body);
+
+        _handleCountDown = new CountDownLatch(1);
+
+        _logger.info("Creating _Listener that should also receive the thrown exception.");
+        _listener = new BlockToAccessFrameListener(1);
+    }
+
+    /**
+     * There are two paths based on the type of exception thrown.
+     *
+     * This tests that when an AMQException is thrown we get the same type of AMQException
back with the real exception
+     * wrapped as the cause.
+     *
+     * @throws InterruptedException  - if we are unable to wait for the test signals
+     */
+    public void testFrameListenerUpdateWithAMQException() throws InterruptedException
+    {
+        AMQException trigger = new AMQAuthenticationException(AMQConstant.ACCESS_REFUSED,
+                                                              "AMQPHTest", new RuntimeException());
+
+        performWithException(trigger);
+
+
+        AMQException receivedException = (AMQException) _listener.getReceivedException();
+
+        assertEquals("Return exception was not the expected type",
+                     AMQAuthenticationException.class, receivedException.getClass());
+
+        assertEquals("The _Listener did not receive the correct error code",
+                     trigger.getErrorCode(), receivedException.getErrorCode());
+    }
+
+    /**
+     * There are two paths based on the type of exception thrown.
+     *
+     * This tests that when a generic Exception is thrown we get the exception back wrapped
in a AMQException
+     * as the cause.
+     * @throws InterruptedException  - if we are unable to wait for the test signals
+     */
+    public void testFrameListenerUpdateWithException() throws InterruptedException
+    {
+
+        Exception trigger = new Exception(new RuntimeException());
+
+        performWithException(trigger);
+
+        assertEquals("The _Listener did not receive the correct error code",
+                     AMQConstant.INTERNAL_ERROR,  ((AMQException)_listener.getReceivedException()).getErrorCode());
+    }
+
+    /**
+     * This is the main test method for both test cases.
+     *
+     * What occurs is that we create a new thread that will block (<30s[DEFAULT]) for
a frame or exception to occur .
+     *
+     * We use a CountDownLatch to ensure that the new thread is running before we then yield
and sleep to help ensure
+     * the new thread has entered the synchronized block in the writeCommandFrameAndWaitForReply.
+     *
+     * We can then ack like an the incomming exception handler in (ConnectionCloseMethodHandler).
+     *
+     * We fire the error to the stateManager, which in this case will recored the error as
there are no state listeners.
+     *
+     * We then set the connection to be closed, as we would normally close the socket at
this point.
+     *
+     * Then fire the exception in to any frameListeners.
+     *
+     * The blocked listener (created above) when receiving the error simulates the user by
creating a new request to
+     * block for a frame.
+     *
+     * This request should fail. Prior to the fix this will fail with a NPE as we are attempting
to use a null listener
+     * in the writeCommand.... call L:268.
+     *
+     * This highlights that the listener would be added dispite there being a pending error
state that the listener will
+     * miss as it is not currently part of the _frameListeners set that is being notified
by the iterator.
+     *
+     * The method waits to ensure that an exception is received before returning.
+     *
+     * The calling methods validate that exception that was received based on the one they
sent in.
+     *
+     * @param trigger The exception to throw through the handler
+     */
+    private void performWithException(Exception trigger) throws InterruptedException
+    {
+
+        final CountDownLatch callingWriteCommand = new CountDownLatch(1);
+
+        //Set an initial listener that will allow us to create a new blocking method
+        new Thread(new Runnable()
+        {
+            public void run()
+            {
+
+                try
+                {
+
+                    _logger.info("At initial block, signalling to fire new exception");
+                    callingWriteCommand.countDown();
+
+                    _handler.writeCommandFrameAndWaitForReply(_blockFrame, _listener);
+                }
+                catch (Exception e)
+                {
+                    e.printStackTrace();
+                    fail(e.getMessage());
+                }
+            }
+        }).start();
+
+        _logger.info("Waiting for 'initial block' to start ");
+        if (!callingWriteCommand.await(1000, TimeUnit.MILLISECONDS))
+        {
+            fail("Failed to start new thread to block for frame");
+        }
+
+        // Do what we can to ensure that this thread does not continue before the above thread
has hit the synchronized
+        // block in the writeCommandFrameAndWaitForReply
+        Thread.yield();
+        Thread.sleep(1000);
+
+        _logger.info("Firing Erorr through state manager. There should be not state waiters
here.");
+        _handler.getStateManager().error(trigger);
+
+        _logger.info("Setting state to be CONNECTION_CLOSED.");
+        try
+        {
+            _handler.getStateManager().changeState(AMQState.CONNECTION_CLOSED);
+        }
+        catch (AMQException e)
+        {
+            _logger.error("Unable to change the state to closed.", e);
+            fail("Unable to change the state to closed due to :"+e.getMessage());
+        }
+
+        _logger.info("Firing exception");
+        _handler.propagateExceptionToFrameListeners(trigger);
+
+        _logger.info("Awaiting notifcation from handler that exception arrived.");
+
+        if (!_handleCountDown.await(2000, TimeUnit.MILLISECONDS))
+        {
+            fail("Failed to handle exception and timeout has not occured");
+        }
+
+
+        assertNotNull("The _Listener did not receive the exception", _listener.getReceivedException());
+
+        assertTrue("Received exception not an AMQException",
+                      _listener.getReceivedException() instanceof AMQException);
+
+        AMQException receivedException = (AMQException) _listener.getReceivedException();
+
+        assertTrue("The _Listener did not receive the correct message",
+                   receivedException.getMessage().startsWith(trigger.getMessage()));
+
+
+        assertEquals("The _Listener did not receive the correct cause",
+                     trigger, receivedException.getCause());
+
+        assertEquals("The _Listener did not receive the correct sub cause",
+                     trigger.getCause(), receivedException.getCause().getCause());
+
+    }
+
+    class BlockToAccessFrameListener extends BlockingMethodFrameListener
+    {
+        private Exception _receivedException = null;
+
+        /**
+         * Creates a new method listener, that filters incoming method to just those that
match the specified channel id.
+         *
+         * @param channelId The channel id to filter incoming methods with.
+         */
+        public BlockToAccessFrameListener(int channelId)
+        {
+            super(channelId);
+            _logger.info("Creating a listener:" + this);
+        }
+
+        public boolean processMethod(int channelId, AMQMethodBody frame)
+        {
+            return true;
+        }
+
+        @Override
+        public void error(Exception e)
+        {
+            _logger.info("Exception(" + e + ") Received by:" + this);
+            // Create a new Thread to start the blocking registration.
+            new Thread(new Runnable()
+            {
+
+                public void run()
+                {
+                    //Set an initial listener that will allow us to create a new blocking
method
+                    try
+                    {
+                        _handler.writeCommandFrameAndWaitForReply(_blockFrame, null, 2000L);
+                        _logger.info("listener(" + this + ") Wait completed");
+                    }
+                    catch (Exception e)
+                    {
+                        _logger.info("listener(" + this + ") threw exception:" + e.getMessage());
+                        _receivedException = e;
+                    }
+
+                    _logger.info("listener(" + this + ") completed");
+                    _handleCountDown.countDown();
+                }
+            }).start();
+        }
+
+        public Exception getReceivedException()
+        {
+            return _receivedException;
+        }
+    }
+
+}

Added: incubator/qpid/trunk/qpid/java/client/src/test/java/org/apache/qpid/client/protocol/MockIoSession.java
URL: http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/java/client/src/test/java/org/apache/qpid/client/protocol/MockIoSession.java?rev=711822&view=auto
==============================================================================
--- incubator/qpid/trunk/qpid/java/client/src/test/java/org/apache/qpid/client/protocol/MockIoSession.java
(added)
+++ incubator/qpid/trunk/qpid/java/client/src/test/java/org/apache/qpid/client/protocol/MockIoSession.java
Thu Nov  6 01:56:56 2008
@@ -0,0 +1,312 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.client.protocol;
+
+import org.apache.mina.common.*;
+import org.apache.mina.common.support.DefaultCloseFuture;
+import org.apache.mina.common.support.DefaultWriteFuture;
+import org.apache.mina.common.support.AbstractIoFilterChain;
+import org.apache.qpid.client.protocol.AMQProtocolSession;
+
+import java.net.SocketAddress;
+import java.net.InetSocketAddress;
+import java.util.Set;
+
+public class MockIoSession implements IoSession
+{
+    private AMQProtocolSession _protocolSession;
+
+    /**
+     * Stores the last response written
+     */
+    private Object _lastWrittenObject;
+
+    private boolean _closing;
+    private IoFilterChain _filterChain;
+
+    public MockIoSession()
+    {
+        _filterChain = new AbstractIoFilterChain(this)
+        {
+            protected void doWrite(IoSession ioSession, IoFilter.WriteRequest writeRequest)
throws Exception
+            {
+
+            }
+
+            protected void doClose(IoSession ioSession) throws Exception
+            {
+
+            }
+        };
+    }
+
+    public Object getLastWrittenObject()
+    {
+        return _lastWrittenObject;
+    }
+
+    public IoService getService()
+    {
+        return null;  //To change body of implemented methods use File | Settings | File
Templates.
+    }
+
+    public IoServiceConfig getServiceConfig()
+    {
+        return null;
+    }
+
+    public IoHandler getHandler()
+    {
+        return null;  //To change body of implemented methods use File | Settings | File
Templates.
+    }
+
+    public IoSessionConfig getConfig()
+    {
+        return null;  //To change body of implemented methods use File | Settings | File
Templates.
+    }
+
+    public IoFilterChain getFilterChain()
+    {
+        return _filterChain;
+    }
+
+    public WriteFuture write(Object message)
+    {
+        WriteFuture wf = new DefaultWriteFuture(null);
+        _lastWrittenObject = message;
+        return wf;
+    }
+
+    public CloseFuture close()
+    {
+        _closing = true;
+        CloseFuture cf = new DefaultCloseFuture(null);
+        cf.setClosed();
+        return cf;
+    }
+
+    public Object getAttachment()
+    {
+        return _protocolSession;
+    }
+
+    public Object setAttachment(Object attachment)
+    {
+        Object current = _protocolSession;
+        _protocolSession = (AMQProtocolSession) attachment;
+        return current;
+    }
+
+    public Object getAttribute(String key)
+    {
+        return null;  //To change body of implemented methods use File | Settings | File
Templates.
+    }
+
+    public Object setAttribute(String key, Object value)
+    {
+        return null;  //To change body of implemented methods use File | Settings | File
Templates.
+    }
+
+    public Object setAttribute(String key)
+    {
+        return null;  //To change body of implemented methods use File | Settings | File
Templates.
+    }
+
+    public Object removeAttribute(String key)
+    {
+        return null;  //To change body of implemented methods use File | Settings | File
Templates.
+    }
+
+    public boolean containsAttribute(String key)
+    {
+        return false;  //To change body of implemented methods use File | Settings | File
Templates.
+    }
+
+    public Set getAttributeKeys()
+    {
+        return null;  //To change body of implemented methods use File | Settings | File
Templates.
+    }
+
+    public TransportType getTransportType()
+    {
+        return null;  //To change body of implemented methods use File | Settings | File
Templates.
+    }
+
+    public boolean isConnected()
+    {
+        return false;  //To change body of implemented methods use File | Settings | File
Templates.
+    }
+
+    public boolean isClosing()
+    {
+        return _closing;
+    }
+
+    public CloseFuture getCloseFuture()
+    {
+        return null;  //To change body of implemented methods use File | Settings | File
Templates.
+    }
+
+    public SocketAddress getRemoteAddress()
+    {
+        return new InetSocketAddress("127.0.0.1", 1234);  //To change body of implemented
methods use File | Settings | File Templates.
+    }
+
+    public SocketAddress getLocalAddress()
+    {
+        return null;  //To change body of implemented methods use File | Settings | File
Templates.
+    }
+
+    public SocketAddress getServiceAddress()
+    {
+        return null;  //To change body of implemented methods use File | Settings | File
Templates.
+    }
+
+    public int getIdleTime(IdleStatus status)
+    {
+        return 0;  //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    public long getIdleTimeInMillis(IdleStatus status)
+    {
+        return 0;  //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    public void setIdleTime(IdleStatus status, int idleTime)
+    {
+        //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    public int getWriteTimeout()
+    {
+        return 0;  //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    public long getWriteTimeoutInMillis()
+    {
+        return 0;  //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    public void setWriteTimeout(int writeTimeout)
+    {
+        //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    public TrafficMask getTrafficMask()
+    {
+        return null;  //To change body of implemented methods use File | Settings | File
Templates.
+    }
+
+    public void setTrafficMask(TrafficMask trafficMask)
+    {
+        //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    public void suspendRead()
+    {
+        //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    public void suspendWrite()
+    {
+        //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    public void resumeRead()
+    {
+        //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    public void resumeWrite()
+    {
+        //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    public long getReadBytes()
+    {
+        return 0;  //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    public long getWrittenBytes()
+    {
+        return 0;  //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    public long getReadMessages()
+    {
+        return 0L;
+    }
+
+    public long getWrittenMessages()
+    {
+        return 0L;
+    }
+
+    public long getWrittenWriteRequests()
+    {
+        return 0;  //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    public int getScheduledWriteRequests()
+    {
+        return 0;  //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    public int getScheduledWriteBytes()
+    {
+        return 0;  //TODO
+    }
+
+    public long getCreationTime()
+    {
+        return 0;  //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    public long getLastIoTime()
+    {
+        return 0;  //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    public long getLastReadTime()
+    {
+        return 0;  //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    public long getLastWriteTime()
+    {
+        return 0;  //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    public boolean isIdle(IdleStatus status)
+    {
+        return false;  //To change body of implemented methods use File | Settings | File
Templates.
+    }
+
+    public int getIdleCount(IdleStatus status)
+    {
+        return 0;  //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    public long getLastIdleTime(IdleStatus status)
+    {
+        return 0;  //To change body of implemented methods use File | Settings | File Templates.
+    }
+}



Mime
View raw message