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

de.weltraumschaf.commons.InvokableAdapter Maven / Gradle / Ivy

/*
 * LICENSE
 *
 * "THE BEER-WARE LICENSE" (Revision 43):
 * "Sven Strittmatter"  wrote this file.
 * As long as you retain this notice you can do whatever you want with
 * this stuff. If we meet some day, and you think this stuff is worth it,
 * you can buy me a non alcohol-free beer in return.
 *
 * Copyright (C) 2012 "Sven Strittmatter" 
 */
package de.weltraumschaf.commons;

import de.weltraumschaf.commons.system.DefaultExiter;
import de.weltraumschaf.commons.system.ExitCode;
import de.weltraumschaf.commons.system.Exitable;
import java.io.UnsupportedEncodingException;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * Abstract base implementation of an command line invokable.
 *
 * Extend this class in your client code.
 *
 * Example:
 * 
 *
 * public class MyApp extends InvokableAdapter {
 *
 *      public static void main(final String[] args) {
 *          InvokableAdapter.main(new MyApp(args));
 *      }
 *
 *      @Override
 *      public void execute() throws Exception {
 *          // Your application code here.
 *      }
 *
 * }
 * 
 *
 * @author Sven Strittmatter 
 */
public abstract class InvokableAdapter implements Invokable {

    /**
     * Copy of the command line arguments.
     */
    private final String[] args;

    /**
     * Container for shutdown {@link Runnable callbacks}.
     */
    private final ShutDownHook shutDownHook;

    /**
     * I/O streams.
     */
    private IOStreams ioStreams;

    /**
     * Abstraction for {@link System#exit(int)}.
     */
    private Exitable exiter = new DefaultExiter();

    /**
     * Runtime for registering callbacks.
     */
    private final Runtime runtime;

    /**
     * Copies the command line arguments.
     *
     * @param args Command line arguments.
     */
    public InvokableAdapter(final String[] args) {
        this(args, Runtime.getRuntime(), new ShutDownHook());
    }

    /**
     * Dedicated constructor.
     *
     * @param args Command line arguments.
     * @param runtime Runtime for registering callbacks.
     * @param shutDownHook Object to hold shutdown hooks.
     */
    public InvokableAdapter(final String[] args, final Runtime runtime, final ShutDownHook shutDownHook) {
        this.args = args.clone();
        this.runtime = runtime;
        this.shutDownHook = shutDownHook;
    }

    /**
     * Invokes {@link #main(de.weltraumschaf.commons.Invokable, de.weltraumschaf.commons.IOStreams)
     * invokable} with default I/O.
     *
     * @param invokable Implementation to invoke.
     */
    public static void main(final Invokable invokable) {
        try {
            main(invokable, IOStreams.newDefault());
        } catch (UnsupportedEncodingException ex) {
            Logger.getLogger(InvokableAdapter.class.getName()).log(Level.SEVERE, null, ex);
            invokable.exit(-1);
        }
    }

    /**
     * Inject the I/O streams to the invokable and then calls {@link Invokable#init()} and
     * then {@link Invokable#execute()}.
     *
     * This method handles ell thrown {@link Exception} and calls {@link System#exit(int)}.
     *
     * @param invokable Implementation to invoke.
     * @param ioStreams I/O streams.
     */
    public static void main(final Invokable invokable, final IOStreams ioStreams) {
        main(invokable, ioStreams, false);
    }

    /**
     * Inject the I/O streams to the invokable and then calls {@link Invokable#init()} and
     * then {@link Invokable#execute()}.
     *
     * This method handles ell thrown {@link Exception} and calls {@link System#exit(int)},
     * and prints stack trace if debug is true.
     *
     * @param invokable implementation to invoke
     * @param ioStreams I/O streams
     * @param debug print stack trace if true
     */
    public static void main(final Invokable invokable, final IOStreams ioStreams, final boolean debug) {
        invokable.setIoStreams(ioStreams);

        try {
            invokable.init();
            invokable.execute();
        } catch (final Exception ex) {
            ioStreams.errorln(ex.getMessage());

            if (debug) {
                ioStreams.printStackTrace(ex);
            }

            if (ex instanceof ApplicationException) { // NOPMD Don't want to duplicate code for ERR out.
                invokable.exit(((ApplicationException) ex).getExitCode());
            } else {
                invokable.exit(-1);
            }
        }

        invokable.exit(0);
    }

    /**
     * Adds shutdown hook to runtime.
     */
    @Override
    public final void init() {
        runtime.addShutdownHook(shutDownHook);
    }

    /**
     * Get the command line arguments.
     *
     * @return Returns copy of the arguments array.
     */
    public final String[] getArgs() {
        return args.clone();
    }

    @Override
    public final IOStreams getIoStreams() {
        return ioStreams;
    }

    @Override
    public final void setIoStreams(IOStreams ioStreams) {
        this.ioStreams = ioStreams;
    }

    /**
     * Register a {@link Runnable callback} as shut down hook.
     *
     * @param callback On shutdown running callback.
     */
    public final void registerShutdownHook(final Runnable callback) {
        shutDownHook.register(callback);
    }

    @Override
    public final void exit(int status) {
        exiter.exit(status);
    }

    @Override
    public final void exit(ExitCode status) {
        exiter.exit(status);
    }

    @Override
    public final void setExiter(final Exitable exiter) {
        this.exiter = exiter;
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy