com.opengamma.integration.regression.ServerProcess.java Source code

Java tutorial

Introduction

Here is the source code for com.opengamma.integration.regression.ServerProcess.java

Source

/**
 * Copyright (C) 2013 - present by OpenGamma Inc. and the OpenGamma group of companies
 *
 * Please see distribution for license.
 */
package com.opengamma.integration.regression;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;

import com.google.common.collect.ImmutableList;
import com.opengamma.OpenGammaRuntimeException;
import com.opengamma.component.OpenGammaComponentServer;

/**
 * Runs {@link OpenGammaComponentServer} in a new process
. */
public final class ServerProcess implements AutoCloseable {

    /** The server process. */
    private final Process _process;

    private ServerProcess(Process process) {
        _process = process;
    }

    // TODO memory options

    /**
     * Creates a new process that runs {@link OpenGammaComponentServer}.
     * @param workingDir The working directory for the process
     * @param classpath The classpath argument for the process
     * @param configFile The location of the server configuration file
     * @param propertyOverrides Properties to override values in the configuration
     * @param logbackConfig Property to set the logback configuration
     * @return The process
     */
    public static ServerProcess start(String workingDir, String classpath, String configFile,
            Properties propertyOverrides, String logbackConfig) {
        ImmutableList.Builder<String> commandBuilder = ImmutableList.builder();
        commandBuilder.add("java", logbackConfig, "-cp", classpath, "-Xmx2g", "-XX:MaxPermSize=256M",
                "com.opengamma.component.OpenGammaComponentServer", configFile);
        // can override properties in the config on the command line with prop1=value1 prop2=value2 ...
        for (Map.Entry<Object, Object> entry : propertyOverrides.entrySet()) {
            commandBuilder.add(entry.getKey() + "=" + entry.getValue());
        }
        ProcessBuilder processBuilder = new ProcessBuilder(commandBuilder.build()).directory(new File(workingDir));
        Process process;
        try {
            process = processBuilder.start();
        } catch (IOException e) {
            throw new OpenGammaRuntimeException("Failed to start server process", e);
        }
        BlockingQueue<Boolean> startupQueue = new ArrayBlockingQueue<>(1);
        consumeStream(process.getInputStream(), OpenGammaComponentServer.STARTUP_COMPLETE_MESSAGE, startupQueue,
                true, System.out);
        consumeStream(process.getErrorStream(), OpenGammaComponentServer.STARTUP_FAILED_MESSAGE, startupQueue,
                false, System.err);
        Boolean startupSuccess;
        try {
            // TODO timeout mechanism in case the server dies and doesn't log correctly. timer task that interrupts this thread?
            startupSuccess = startupQueue.take();
        } catch (InterruptedException e) {
            // not going to happen
            throw new OpenGammaRuntimeException("unexpected exception", e);
        }

        if (!startupSuccess) {
            throw new OpenGammaRuntimeException("startup failed, aborting");
        }
        return new ServerProcess(process);
    }

    /**
     * Starts a thread which consumes a stream line by line and puts a value onto a queue when it encounters
     * a line starting with a particular value. If an exception occurs a value of false it put onto the queue.
     * Every line read from the stream is written to a {@link PrintStream}.
     * @param stream The stream to consume
     * @param value The trigger value - the stream line must <em>startWith</em> this string
     * @param queue The queue
     * @param signalValue The value to put onto the queue when line is encountered in the stream
     * @param output Every line read from the stream is written to this print stream
     */
    private static void consumeStream(final InputStream stream, final String value,
            final BlockingQueue<Boolean> queue, final Boolean signalValue, final PrintStream output) {
        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                try (BufferedReader reader = new BufferedReader(new InputStreamReader(stream))) {
                    String nextLine;
                    while ((nextLine = reader.readLine()) != null) {
                        output.println(nextLine);
                        if (nextLine.startsWith(value)) {
                            queue.put(signalValue);
                        }
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                    try {
                        queue.put(false);
                    } catch (InterruptedException e1) {
                        // not going to happen
                    }
                } catch (InterruptedException e) {
                    // not going to happen
                }
            }
        });
        thread.setDaemon(true);
        thread.start();
    }

    @Override
    public void close() {
        _process.destroy();
    }
}