Java tutorial
/* * Copyright 1999-2006 University of Chicago * * Licensed 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.globus.ftp; import java.io.IOException; import java.io.InputStream; import java.io.EOFException; import java.io.InterruptedIOException; import org.globus.util.CircularBuffer; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; // if write() blocked, it will not be unblocked by close public class InputStreamDataSink implements DataSink { protected CircularBuffer buffers = null; private DataInputStream in; private boolean closed = false; public InputStreamDataSink() { this.buffers = new CircularBuffer(5); this.in = new DataInputStream(); } public void write(Buffer buffer) throws IOException { if (isClosed()) { throw new EOFException(); } try { if (!buffers.put(buffer)) { throw new EOFException(); } } catch (InterruptedException e) { throw new InterruptedIOException(); } } public void close() throws IOException { // will let get run until it returns null // and will throe EOFException on next put call // but existing put calls will not be interrupted setClosed(); this.buffers.closePut(); } private synchronized void setClosed() { this.closed = true; } private synchronized boolean isClosed() { return this.closed; } public InputStream getInputStream() { return this.in; } class DataInputStream extends InputStream { protected byte[] buff; protected int index; protected int length; public synchronized int read(byte[] data) throws IOException { return read(data, 0, data.length); } public synchronized int read(byte[] data, int off, int len) throws IOException { if (!ensureData()) { return -1; } int max = (index + len > length) ? length - index : len; System.arraycopy(buff, index, data, off, max); index += max; return max; } public synchronized int read() throws IOException { if (!ensureData()) { return -1; } return buff[index++] & 0xff; } public void close() throws IOException { buffers.interruptBoth(); } protected synchronized boolean ensureData() throws IOException { if (buffers.isGetInterrupted()) { return false; } if (this.length == this.index) { try { Buffer buf = (Buffer) buffers.get(); if (buf == null) { return false; } this.index = 0; this.length = buf.getLength(); this.buff = buf.getBuffer(); } catch (InterruptedException e) { // that should never happen throw new InterruptedIOException(); } } return true; } } }