| /* |
| * Copyright (c) 2004, 2011, Oracle and/or its affiliates. All rights reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions |
| * are met: |
| * |
| * - Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * |
| * - Redistributions in binary form must reproduce the above copyright |
| * notice, this list of conditions and the following disclaimer in the |
| * documentation and/or other materials provided with the distribution. |
| * |
| * - Neither the name of Oracle nor the names of its |
| * contributors may be used to endorse or promote products derived |
| * from this software without specific prior written permission. |
| * |
| * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS |
| * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, |
| * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
| * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR |
| * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
| * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
| * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
| * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF |
| * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING |
| * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
| * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| */ |
| |
| /* |
| * This source code is provided to illustrate the usage of a given feature |
| * or technique and has been deliberately simplified. Additional steps |
| * required for a production-quality application, such as security checks, |
| * input validation and proper error handling, might not be present in |
| * this sample code. |
| */ |
| |
| |
| import java.io.*; |
| import java.nio.*; |
| import java.nio.channels.*; |
| |
| /** |
| * A helper class for properly sizing inbound byte buffers and |
| * redirecting I/O calls to the proper SocketChannel call. |
| * <P> |
| * Many of these calls may seem unnecessary until you consider |
| * that they are placeholders for the secure variant, which is much |
| * more involved. See ChannelIOSecure for more information. |
| * |
| * @author Brad R. Wetmore |
| * @author Mark Reinhold |
| */ |
| class ChannelIO { |
| |
| protected SocketChannel sc; |
| |
| /* |
| * All of the inbound request data lives here until we determine |
| * that we've read everything, then we pass that data back to the |
| * caller. |
| */ |
| protected ByteBuffer requestBB; |
| static private int requestBBSize = 4096; |
| |
| protected ChannelIO(SocketChannel sc, boolean blocking) |
| throws IOException { |
| this.sc = sc; |
| sc.configureBlocking(blocking); |
| } |
| |
| static ChannelIO getInstance(SocketChannel sc, boolean blocking) |
| throws IOException { |
| ChannelIO cio = new ChannelIO(sc, blocking); |
| cio.requestBB = ByteBuffer.allocate(requestBBSize); |
| |
| return cio; |
| } |
| |
| SocketChannel getSocketChannel() { |
| return sc; |
| } |
| |
| /* |
| * Return a ByteBuffer with "remaining" space to work. If you have to |
| * reallocate the ByteBuffer, copy the existing info into the new buffer. |
| */ |
| protected void resizeRequestBB(int remaining) { |
| if (requestBB.remaining() < remaining) { |
| // Expand buffer for large request |
| ByteBuffer bb = ByteBuffer.allocate(requestBB.capacity() * 2); |
| requestBB.flip(); |
| bb.put(requestBB); |
| requestBB = bb; |
| } |
| } |
| |
| /* |
| * Perform any handshaking processing. |
| * <P> |
| * This variant is for Servers without SelectionKeys (e.g. |
| * blocking). |
| * <P> |
| * return true when we're done with handshaking. |
| */ |
| boolean doHandshake() throws IOException { |
| return true; |
| } |
| |
| /* |
| * Perform any handshaking processing. |
| * <P> |
| * This variant is for Servers with SelectionKeys, so that |
| * we can register for selectable operations (e.g. selectable |
| * non-blocking). |
| * <P> |
| * return true when we're done with handshaking. |
| */ |
| boolean doHandshake(SelectionKey sk) throws IOException { |
| return true; |
| } |
| |
| /* |
| * Resize (if necessary) the inbound data buffer, and then read more |
| * data into the read buffer. |
| */ |
| int read() throws IOException { |
| /* |
| * Allocate more space if less than 5% remains |
| */ |
| resizeRequestBB(requestBBSize/20); |
| return sc.read(requestBB); |
| } |
| |
| /* |
| * All data has been read, pass back the request in one buffer. |
| */ |
| ByteBuffer getReadBuf() { |
| return requestBB; |
| } |
| |
| /* |
| * Write the src buffer into the socket channel. |
| */ |
| int write(ByteBuffer src) throws IOException { |
| return sc.write(src); |
| } |
| |
| /* |
| * Perform a FileChannel.TransferTo on the socket channel. |
| */ |
| long transferTo(FileChannel fc, long pos, long len) throws IOException { |
| return fc.transferTo(pos, len, sc); |
| } |
| |
| /* |
| * Flush any outstanding data to the network if possible. |
| * <P> |
| * This isn't really necessary for the insecure variant, but needed |
| * for the secure one where intermediate buffering must take place. |
| * <P> |
| * Return true if successful. |
| */ |
| boolean dataFlush() throws IOException { |
| return true; |
| } |
| |
| /* |
| * Start any connection shutdown processing. |
| * <P> |
| * This isn't really necessary for the insecure variant, but needed |
| * for the secure one where intermediate buffering must take place. |
| * <P> |
| * Return true if successful, and the data has been flushed. |
| */ |
| boolean shutdown() throws IOException { |
| return true; |
| } |
| |
| /* |
| * Close the underlying connection. |
| */ |
| void close() throws IOException { |
| sc.close(); |
| } |
| |
| } |