org.jclouds.util.InputStreamChain.java Source code

Java tutorial

Introduction

Here is the source code for org.jclouds.util.InputStreamChain.java

Source

/**
 *
 * Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
 *
 * ====================================================================
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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.jclouds.util;

import java.io.IOException;
import java.io.InputStream;
import java.util.LinkedList;

import org.apache.commons.io.IOUtils;

/**
 * {@link InputStream} implementation that allows chaining of various streams for seamless
 * sequential reading
 * 
 * @author Adrian Cole
 * @author Tomas Varaneckas <tomas.varaneckas@gmail.com>
 */
public class InputStreamChain extends InputStream {

    /**
     * Input stream chain
     */
    private final LinkedList<InputStream> streams = new LinkedList<InputStream>();

    /**
     * Currently active stream
     */
    private InputStream current;

    /**
     * Constructor with an initial stream
     * 
     * @param first
     *           Initial InputStream
     */
    public InputStreamChain(InputStream... inputStreams) {
        for (InputStream stream : inputStreams) {
            addInputStream(stream);
        }
    }

    /**
     * Adds input stream to the end of chain
     * 
     * @param stream
     *           InputStream to add to chain
     * @return instance of self (for fluent calls)
     */
    public InputStreamChain addInputStream(final InputStream stream) {
        streams.addLast(stream);
        if (current == null) {
            current = streams.removeFirst();
        }
        return this;
    }

    /**
     * Adds a String to the end of chain
     * 
     * @param value
     *           String to add to the chain
     * @return instance of self (for fluent calls)
     */
    public InputStreamChain addAsInputStream(final String value) {
        return addInputStream(IOUtils.toInputStream(value));
    }

    @Override
    public int read() throws IOException {
        int bit = current.read();
        if (bit == -1 && streams.size() > 0) {
            try {
                current.close();
            } catch (final IOException e) {
                // replace this with a call to logging facility
                e.printStackTrace();
            }
            current = streams.removeFirst();
            bit = read();
        }
        return bit;
    }

    @Override
    public int available() throws IOException {
        int available = current.available();
        for (InputStream stream : streams) {
            available += stream.available();
        }
        return available;
    }

    @Override
    public void close() throws IOException {
        current.close();
    }

    @Override
    public boolean markSupported() {
        return current.markSupported();
    }

    @Override
    public synchronized void mark(int i) {
        current.mark(i);
    }

    @Override
    public synchronized void reset() throws IOException {
        current.reset();
    }

    @Override
    public long skip(long l) throws IOException {
        return current.skip(l);
    }

}