org.globus.ftp.OutputStreamDataSource.java Source code

Java tutorial

Introduction

Here is the source code for org.globus.ftp.OutputStreamDataSource.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.OutputStream;
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;

public class OutputStreamDataSource implements DataSource {

    protected CircularBuffer buffers = null;
    private DataOutputStream out;

    public OutputStreamDataSource(int size) {
        this.buffers = new CircularBuffer(5);
        this.out = new DataOutputStream(size);
    }

    // returns null if EOF
    public Buffer read() throws IOException {
        try {
            return (Buffer) this.buffers.get();
        } catch (InterruptedException e) {
            // that should not happen
            throw new InterruptedIOException();
        }
    }

    public void close() throws IOException {
        this.buffers.interruptBoth();
        this.out.setClosed();
    }

    public OutputStream getOutputStream() {
        return this.out;
    }

    public long totalSize() throws IOException {
        return -1;
    }

    // if write() is blocked, it will not be unblocked by close()
    class DataOutputStream extends OutputStream {

        protected byte[] buff;
        protected int index;
        private boolean closed = false;

        public DataOutputStream(int size) {
            this.buff = new byte[size];
            this.index = 0;
        }

        public void write(byte[] data) throws IOException {
            write(data, 0, data.length);
        }

        public synchronized void write(byte[] data, int off, int len) throws IOException {
            if (isClosed()) {
                throw new EOFException();
            }
            int max;
            while (len > 0) {
                if (this.index + len > this.buff.length) {
                    max = (this.buff.length - this.index);
                    System.arraycopy(data, off, this.buff, this.index, max);
                    this.index += max;
                    flush();
                    len -= max;
                    off += max;
                } else {
                    System.arraycopy(data, off, this.buff, this.index, len);
                    this.index += len;
                    break;
                }
            }
        }

        public synchronized void write(int b) throws IOException {
            if (isClosed()) {
                throw new EOFException();
            }
            if (this.index == this.buff.length) {
                flush();
            }

            buff[index++] = (byte) b;
        }

        public synchronized void flush() throws IOException {
            if (this.index == 0) {
                return;
            }
            byte[] data = new byte[this.index];
            System.arraycopy(this.buff, 0, data, 0, this.index);
            Buffer b = new Buffer(data, this.index);
            try {
                if (!buffers.put(b)) {
                    throw new EOFException();
                }
            } catch (InterruptedException e) {
                // that should never happen
                throw new InterruptedIOException();
            }
            this.index = 0;
        }

        public void close() throws IOException {
            flush();
            // 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();
            buffers.closePut();
        }

        protected synchronized void setClosed() {
            this.closed = true;
        }

        private synchronized boolean isClosed() {
            return this.closed;
        }

    }
}