com.kolich.common.util.runtime.RuntimeClosure.java Source code

Java tutorial

Introduction

Here is the source code for com.kolich.common.util.runtime.RuntimeClosure.java

Source

/**
 * Copyright (c) 2015 Mark S. Kolich
 * http://mark.koli.ch
 *
 * Permission is hereby granted, free of charge, to any person
 * obtaining a copy of this software and associated documentation
 * files (the "Software"), to deal in the Software without
 * restriction, including without limitation the rights to use,
 * copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following
 * conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 * OTHER DEALINGS IN THE SOFTWARE.
 */

package com.kolich.common.util.runtime;

import com.kolich.common.functional.either.Either;
import com.kolich.common.functional.either.Left;
import com.kolich.common.functional.either.Right;

import java.io.File;

import static org.apache.commons.io.IOUtils.closeQuietly;

public abstract class RuntimeClosure<T> {

    private final Runtime runtime_;

    public RuntimeClosure(final Runtime runtime) {
        runtime_ = runtime;
    }

    public RuntimeClosure() {
        this(Runtime.getRuntime());
    }

    public abstract T run(final Process process) throws Exception;

    /**
     * Success callback, called only if and only if the {@link#run}
     * method completed without exception.  Default behavior is do
     * nothing, consumers should override in their closures as needed.
     * @param process the {@link Process} object associated with this
     * runtime operation. May be null.
     */
    public void success(final Process process) throws Exception {
        // Default, do nothing.
    }

    /**
     * Post execution callback, called after the {@link#run} method
     * is complete, on success or failure.  This method is called even
     * if {@link#run} throws an exception.
     * @param process the {@link Process} object associated with this
     * runtime operation. May be null.
     */
    public void after(final Process process) {
        // Default, do nothing.
    }

    public final Either<Exception, T> exec(final String command) {
        Process p = null;
        try {
            return doit(p = runtime_.exec(command));
        } catch (Exception e) {
            return Left.left(e);
        } finally {
            after(p);
        }
    }

    public final Either<Exception, T> exec(final String[] cmdArray) {
        Process p = null;
        try {
            return doit(p = runtime_.exec(cmdArray));
        } catch (Exception e) {
            return Left.left(e);
        } finally {
            after(p);
        }
    }

    public final Either<Exception, T> exec(final String command, final String[] envp) {
        Process p = null;
        try {
            return doit(p = runtime_.exec(command, envp));
        } catch (Exception e) {
            return Left.left(e);
        } finally {
            after(p);
        }
    }

    public final Either<Exception, T> exec(final String command, final String[] envp, final File dir) {
        Process p = null;
        try {
            return doit(p = runtime_.exec(command, envp, dir));
        } catch (Exception e) {
            return Left.left(e);
        } finally {
            after(p);
        }
    }

    public final Either<Exception, T> exec(final String[] cmdArray, final String[] envp, final File dir) {
        Process p = null;
        try {
            return doit(p = runtime_.exec(cmdArray, envp, dir));
        } catch (Exception e) {
            return Left.left(e);
        } finally {
            after(p);
        }
    }

    private final Either<Exception, T> doit(final Process process) {
        Either<Exception, T> result = null;
        try {
            result = Right.right(run(process));
            success(process);
        } catch (Exception e) {
            result = Left.left(e);
        } finally {
            if (process != null) {
                closeQuietly(process.getInputStream());
                closeQuietly(process.getOutputStream());
                closeQuietly(process.getErrorStream());
            }
        }
        return result;
    }

}