/* * JacORB - a free Java ORB * * Copyright (C) 1997-2014 Gerald Brose / The JacORB Team. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ package org.jacorb.orb.iiop; import java.io.IOException; import java.io.InputStream; /** * @author Kevin Conner (Kevin.Conner@arjuna.com) */ class IIOPLoopbackInputStream extends InputStream { private static final int BUF_SIZE = 2048 ; private final byte[] buf = new byte[BUF_SIZE] ; private boolean connected ; private boolean closed ; private int writerIndex ; private int readerIndex ; public IIOPLoopbackInputStream() { super(); } public IIOPLoopbackInputStream(final IIOPLoopbackOutputStream los) throws IOException { this(); connect(los) ; } synchronized void connect(final IIOPLoopbackOutputStream los) throws IOException { if (connected) { throw new IOException("Alread connected") ; } connected = true ; los.connect(this) ; } public synchronized int read() throws IOException { checkConnect() ; return internalRead() ; } public synchronized int read(final byte[] b, final int off, final int len) throws IOException { checkConnect() ; checkBuffer(b, off, len) ; int returnCount = 0 ; while(returnCount < len) { final int val = internalRead() ; if (val == -1) { break ; } b[off + returnCount] = (byte)val ; returnCount++ ; } return (returnCount > 0 ? returnCount : -1) ; } public synchronized int available() throws IOException { checkConnect() ; if (writerIndex > readerIndex) { return (writerIndex - readerIndex) ; } else if (readerIndex > writerIndex) { return BUF_SIZE + writerIndex - readerIndex ; } else { checkClosed() ; return 0 ; } } public synchronized void close() throws IOException { checkConnect() ; closed = true ; notifyAll() ; } synchronized void writerClose() throws IOException { checkConnect() ; closed = true ; notifyAll() ; } synchronized void writeIntoBuffer(final int b) throws IOException { checkConnect() ; internalWrite((byte)b) ; } synchronized void writeIntoBuffer(final byte[] b, final int off, final int len) throws IOException { checkConnect() ; checkBuffer(b, off, len) ; for(int count= 0 ; count < len ; count++) { internalWrite(b[off + count]) ; } } private int internalRead() { while(bufferEmpty()) { if (closed) { return -1 ; } try { wait() ; } catch (final InterruptedException ie) {} // Ignore } final boolean shouldNotify = bufferFull() ; final int val = buf[readerIndex] & 0xff ; readerIndex = nextIndex(readerIndex) ; if (shouldNotify) { notifyAll() ; } return val ; } private void internalWrite(final byte b) throws IOException { while(bufferFull()) { checkClosed() ; try { wait() ; } catch (final InterruptedException ie) {} // Ignore } checkClosed() ; final boolean shouldNotify = bufferEmpty() ; buf[writerIndex] = b ; writerIndex = nextIndex(writerIndex) ; if (shouldNotify) { notifyAll() ; } } private void checkConnect() throws IOException { if (!connected) { throw new IOException("IIOPLoopbackInputStream not connected") ; } } private void checkClosed() throws IOException { if (closed) { throw new IOException("IIOPLoopbackInputStream closed") ; } } private void checkBuffer(final byte[] b, final int off, final int len) { if (b == null) { throw new NullPointerException("Null buffer") ; } final int bufLen = b.length ; if ((off < 0) || (off >= bufLen) || (len < 0) || (len > bufLen) || (off + len > bufLen)) { throw new IndexOutOfBoundsException("Invalid offset/length") ; } } private boolean bufferEmpty() { return (readerIndex == writerIndex) ; } private boolean bufferFull() { return (readerIndex == nextIndex(writerIndex)) ; } private int nextIndex(final int index) { final int nextIndex = index+1 ; return (nextIndex == BUF_SIZE ? 0 : nextIndex) ; } }