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

com.carrotsearch.ant.tasks.junit4.LocalSlaveStreamHandler Maven / Gradle / Ivy

The newest version!
package com.carrotsearch.ant.tasks.junit4;

import java.io.*;
import java.lang.Thread.UncaughtExceptionHandler;
import java.util.List;

import org.apache.tools.ant.taskdefs.ExecuteStreamHandler;
import org.apache.tools.ant.taskdefs.StreamPumper;

import com.carrotsearch.ant.tasks.junit4.events.*;
import com.google.common.base.Charsets;
import com.google.common.collect.Lists;
import com.google.common.eventbus.EventBus;

/**
 * Establish event passing with a subprocess and pump events to the bus.
 */
public class LocalSlaveStreamHandler implements ExecuteStreamHandler {
  private final ClassLoader classLoader;
  private final EventBus eventBus;
  private BootstrapEvent bootstrapPacket;

  private InputStream stdout;
  private InputStream stderr;
  private final PrintStream warnStream;

  private ByteArrayOutputStream stderrBuffered = new ByteArrayOutputStream();
  private List pumpers = Lists.newArrayList();

  public LocalSlaveStreamHandler(EventBus eventBus, ClassLoader classLoader, PrintStream warnStream) {
    this.eventBus = eventBus;
    this.warnStream = warnStream;
    this.classLoader = classLoader;
  }

  @Override
  public void setProcessErrorStream(InputStream is) throws IOException {
    this.stderr = is;
  }
  
  @Override
  public void setProcessOutputStream(InputStream is) throws IOException {
    this.stdout = is;
  }

  @Override
  public void setProcessInputStream(OutputStream os) throws IOException {
    // close os immediately?
  }
  
  @Override
  public void start() throws IOException {
    // Establish event stream first.
    Deserializer deserializer = null;

    // Receive bootstrap event on stdout.
    try {
      deserializer = new Deserializer(stdout, classLoader);
      BootstrapEvent bootstrap = (BootstrapEvent) deserializer.deserialize();
      this.bootstrapPacket = bootstrap;

      switch (bootstrap.getEventChannel()) {
        case SOCKET:
          throw new IOException("Slave requested socket communication?");
        case STDERR:
          // Swap stderr/stdout.
          InputStream tmp = stdout;
          stdout = stderr;
          stderr = tmp;
          break;
        case STDOUT:
          // Don't do anything.
          break;
      }
      eventBus.post(bootstrap);

      pumpers.add(new Thread(new StreamPumper(stderr, stderrBuffered), "pumper-stderr"));
      pumpers.add(new Thread(new Runnable() {
        public void run() {
          pumpEvents();
        }
      }, "pumper-events"));
    } catch (IOException e) {
      warnStream.println("Couldn't establish event communication with the slave: " + e.toString());
      if (!(e instanceof EOFException)) {
        e.printStackTrace(warnStream);
      }
      pumpers.add(new Thread(new StreamPumper(stderr, stderrBuffered), "pumper-stderr"));
    }
    
    // Start all pumper threads.
    UncaughtExceptionHandler handler = new UncaughtExceptionHandler() {
      public void uncaughtException(Thread t, Throwable e) {
        warnStream.println("Unhandled exception in thread: " + t);
        e.printStackTrace(warnStream);
      }
    };
    for (Thread t : pumpers) {
      t.setUncaughtExceptionHandler(handler);
      t.setDaemon(true);
      t.start();
    }
  }

  /**
   * Size of the error stream.
   */
  public boolean isErrorStreamNonEmpty() {
    return stderrBuffered.size() > 0;
  }

  /**
   * "error" stream from the forked process.
   */
  public String getErrorStreamAsString() {
    try {
      if (bootstrapPacket != null) {
        return new String(stderrBuffered.toByteArray(), bootstrapPacket.getDefaultCharsetName());
      }
    } catch (UnsupportedEncodingException e) {
      // Ignore.
    }
    return new String(stderrBuffered.toByteArray(), Charsets.US_ASCII);
  }

  /**
   * Pump events from event stream.
   */
  void pumpEvents() {
    try {
      Deserializer deserializer = new Deserializer(stdout, classLoader);
      while (true) {
        IEvent event = deserializer.deserialize();
        try {
          eventBus.post(event);
        } catch (Throwable t) {
          warnStream.println("Event bus dispatch error: " + t.toString());
          t.printStackTrace(warnStream);
        }
      }
    } catch (EOFException e) {
      // EOF.
    } catch (IOException e) {
      warnStream.println("Event stream error: " + e.toString());
      e.printStackTrace(warnStream);
    }
  }
  
  @Override
  public void stop() {
    try {
      for (Thread t : pumpers) {
        t.join();
      }
    } catch (InterruptedException e) {
      // Don't wait.
    }
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy