All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.opencastproject.util.StreamConsumer Maven / Gradle / Ivy

There is a newer version: 16.6
Show newest version
/*
 * Licensed to The Apereo Foundation under one or more contributor license
 * agreements. See the NOTICE file distributed with this work for additional
 * information regarding copyright ownership.
 *
 *
 * The Apereo Foundation licenses this file to you under the Educational
 * Community 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://opensource.org/licenses/ecl2.txt
 *
 * 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.opencastproject.util;

import static com.entwinemedia.fn.Prelude.chuck;

import com.entwinemedia.fn.Fn;
import com.entwinemedia.fn.Fx;
import com.entwinemedia.fn.Unit;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.concurrent.CountDownLatch;

/**
 * A StreamConsumer helps to asynchronously consume a text input stream line by line.
 * The consumer guarantees the closing of the stream.
 */
public class StreamConsumer implements Runnable {
  private final CountDownLatch running = new CountDownLatch(1);
  private final CountDownLatch ready = new CountDownLatch(1);
  private final CountDownLatch finished = new CountDownLatch(1);

  private final Fn consumer;

  private boolean stopped = false;
  private InputStream stream;
  private BufferedReader reader;

  /**
   * Create a new stream consumer.
   *
   * @param consumer
   *         a predicate function that may stop reading further lines by returning false
   */
  public StreamConsumer(Fn consumer) {
    this.consumer = consumer;
  }

  @Override public void run() {
    try {
      running.countDown();
      ready.await();
      // also save a reference to the reader to able to close it in stopReading
      // otherwise the read loop may continue reading from the buffer
      reader = new BufferedReader(new InputStreamReader(stream));
      IoSupport.withResource(reader, consumeBuffered);
      finished.countDown();
    } catch (InterruptedException e) {
      chuck(e);
    }
  }

  /** Wait for the executing thread to run. */
  public void waitUntilRunning() {
    try {
      running.await();
    } catch (InterruptedException e) {
      chuck(e);
    }
  }

  /** Wait until the stream has been fully consumed. */
  public void waitUntilFinished() {
    try {
      finished.await();
    } catch (InterruptedException e) {
      chuck(e);
    }
  }

  /** Forcibly stop consuming the stream. */
  public void stopConsuming() {
    if (stream != null) {
      stopped = true;
      IoSupport.closeQuietly(stream);
      IoSupport.closeQuietly(reader);
    }
  }

  /** Start consuming stream. It is guaranteed that the stream gets closed. */
  public void consume(InputStream stream) {
    waitUntilRunning();
    this.stream = stream;
    ready.countDown();
  }

  private final Fn consumeBuffered = new Fx() {
    @Override public void apply(BufferedReader reader) {
      String line;
      try {
        while ((line = reader.readLine()) != null) {
          if (!consumer.apply(line)) {
            stopConsuming();
          }
        }
      } catch (IOException e) {
        if (!stopped) {
          chuck(e);
        }
      }
    }
  }.toFn();
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy