org.globus.ftp.InputStreamDataSink.java Source code

Java tutorial

Introduction

Here is the source code for org.globus.ftp.InputStreamDataSink.java

Source

/*
 * 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;
        }

    }
}