Package gov.nasa.arc.mct.identitymgr.mcc

Source Code of gov.nasa.arc.mct.identitymgr.mcc.ShiftChangeReporter$ExpirationTask$StopTask

/*******************************************************************************
* Mission Control Technologies, Copyright (c) 2009-2012, United States Government
* as represented by the Administrator of the National Aeronautics and Space
* Administration. All rights reserved.
*
* The MCT platform is licensed under the Apache 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://www.apache.org/licenses/LICENSE-2.0.
*
* 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.
*
* MCT includes source code licensed under additional open source licenses. See
* the MCT Open Source Licenses file included with this distribution or the About
* MCT Licenses dialog available at runtime from the MCT Help menu for additional
* information.
*******************************************************************************/
/**
* ShiftChangeReporter.java
* This code is property of the National Aeronautics and Space Administration
* and was produced for the Mission Control Technologies (MCT) Project.
*/

package gov.nasa.arc.mct.identitymgr.mcc;

import gov.nasa.arc.mct.util.StringUtil;
import gov.nasa.arc.mct.util.exception.MCTException;
import gov.nasa.arc.mct.util.logging.MCTLogger;
import gov.nasa.arc.mct.util.property.MCTProperties;

import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.ConnectException;
import java.net.Socket;
import java.util.Timer;
import java.util.TimerTask;

/**
*
* Reporter of shift change events.
*
*/
public class ShiftChangeReporter {
    private static MCTLogger logger = MCTLogger.getLogger(ShiftChangeReporter.class);
    private volatile boolean mayRun = false;

    enum ConnectionStatus {
        STATUS_CONNECTED, STATUS_DISCONNECTED
    };

    ConnectionStatus connectionStatus = ConnectionStatus.STATUS_DISCONNECTED;
    private int monitorPort = -1;
    private int interval;
    static final int DEFAULT_INTERVAL = 20;
    static final int DEFAULT_EXPIRATION = 0;
    private String execCommand = null;
    private String currentUser;
    private int reporterExpirationSeconds = 0;

    /**
     * Creates a shift change reporter.
     * @param initialUser the current user ID
     * @throws MCTException
     * @throws IOException
     */
    public ShiftChangeReporter(String initialUser) throws MCTException, IOException {
        final MCTProperties mctProperties = MCTProperties.DEFAULT_MCT_PROPERTIES;

        if (StringUtil.isEmpty(initialUser))
            throw new MCTException("empty or null initial user");
        currentUser = initialUser;

        String portProp = mctProperties.getProperty("mcc.monitor.port");
        if (StringUtil.isEmpty(portProp)) {
            throw new MCTException("property mcc.monitor.port is not set or empty.");
        }
        try {
            this.monitorPort = new Integer(portProp);
        } catch (NumberFormatException e) {
            throw new MCTException(
                    "Could not convert mcc.monitor.port to a valid port. Check that mcc.monitor.port is set.", e);
        }

        reporterExpirationSeconds = DEFAULT_EXPIRATION;
        String expire = mctProperties.getProperty("mcc.reporter.expiration", "0");
        try {
            reporterExpirationSeconds = new Integer(expire);
        } catch (NumberFormatException e) {
            logger.warn("Could not convert mcc.reporter.expiration; using default");
        }

        interval = DEFAULT_INTERVAL;
        String intervalProp = mctProperties.getProperty("mcc.monitor.interval");
        if (!StringUtil.isEmpty(intervalProp)) {
            try {
                this.interval = new Integer(intervalProp);
            } catch (NumberFormatException e) {
                logger.warn("Could not convert mcc.monitor.interval; using default");
            }
        }

        execCommand = mctProperties.getProperty("mcc.monitor.command");
        if (StringUtil.isEmpty(execCommand)) {
            throw new MCTException("property mcc.monitor.command is not set or invalid.");
        }
    }

    private Socket openMonitor() throws MCTException {
        Socket s = null;
        boolean stopTrying = false;
        int connectCounter = 1;

        while (!stopTrying && connectionStatus == ConnectionStatus.STATUS_DISCONNECTED) {
            try {
                s = new Socket("localhost", monitorPort);
                connectionStatus = ConnectionStatus.STATUS_CONNECTED;
                stopTrying = true;
            } catch (ConnectException e) {
                if (connectCounter >= 5) {
                    stopTrying = true;
                    throw new MCTException("Could not open socket to port (gave up):" + monitorPort, e);
                } else {
                    logger.debug("retry {0}", connectionStatus);
                    connectCounter++;
                    try {
                        Thread.sleep(10000);
                    } catch (InterruptedException e1) {
                    }
                }
            } catch (IOException e) {
                stopTrying = true;
                throw new MCTException("Exception trying to open socket to port:" + monitorPort, e);
            }
        }
        logger.info("connectionStatus: {0}", connectionStatus);
        return s;
    }

    void closeMonitor(Socket s) {
        if (s != null)
            try {
                s.close();
            } catch (IOException e) {
            }
        connectionStatus = ConnectionStatus.STATUS_DISCONNECTED;
    }

    /*
     * Continually look for a change in user. If detected, report it to shift
     * change monitor.
     */
    void detectShiftChange() throws MCTException {

        if (this.reporterExpirationSeconds > 0) {
            logger.info("Shift change reporter expiration (seconds):{0}", this.reporterExpirationSeconds);
            new ExpirationTask(this.reporterExpirationSeconds);
        }

        mayRun = true;
        while (mayRun) {

            Runtime rt = Runtime.getRuntime();

            Process proc = null;
            try {
                proc = rt.exec(execCommand);
            } catch (IOException e1) {
                throw new MCTException("Could not execute command: " + execCommand);
            }

            // any error message?
            StreamGobbler errorGobbler = new StreamGobbler(proc.getErrorStream(), "ERR");

            // output from stdout
            StreamGobbler outputGobbler = new StreamGobbler(proc.getInputStream(), "OUT", this);

            // kick them off
            errorGobbler.start();
            outputGobbler.start();

            // any error???
            int exitVal = 0;
            try {
                exitVal = proc.waitFor();
            } catch (InterruptedException e) {
                logger.warn("Exec command interrupted.");
            }
            if (exitVal == 0) {
                try {
                    Thread.sleep(interval * 1000);
                } catch (InterruptedException e) {
                    logger.warn("sleep interrupted");
                }
            } else {
                throw new MCTException("exitVal " + exitVal + " returned from command: " + execCommand);
            }
        }
    }

    /**
     * The shift change reporter application entry.
     * @param args command line arguments
     * @throws Throwable
     */
    public static void main(String args[]) throws Throwable {
        String initialUser = null;
        if (args.length != 1 || StringUtil.isEmpty(args[0])) {
            logger.error("You must specify initial user. Exiting");
            return;
        } else {
            initialUser = args[0];
            logger.debug("initial User: {0}", initialUser);
        }
        try {
            ShiftChangeReporter shiftChangeReporter = new ShiftChangeReporter(initialUser);
            shiftChangeReporter.sanityCheck();
            shiftChangeReporter.detectShiftChange();

        } catch (Throwable e) {
            logger.error("Shift Change Reporter Error", e);
            throw e;
        }
    }

    /*
     * Ensures the open socket is ok. We want to discover this now, not at the
     * end of a shift.
     */
    void sanityCheck() throws MCTException {
        Socket s = openMonitor();
        closeMonitor(s);
    }

    int getMonitorPort() {
        return monitorPort;
    }

    String getExecCommand() {
        return execCommand;
    }

    String getCurrentUser() {
        return currentUser;
    }

    int getInterval() {
        return interval;
    }

    /*
     * If the current value changed from the previous, report. @returns true if
     * reported, false upon error or non reporting
     */
    boolean reportIfValueChanged(String newUser) {
        if (currentUser.equalsIgnoreCase(newUser)) {
            logger.debug("no change from current: {0}", currentUser);
            return false;
        }
        Socket socket = null;
        PrintWriter pw = null;
        OutputStream os = null;
        try {
            socket = openMonitor();

            if (socket != null)
                os = socket.getOutputStream();

            if (os != null)
                pw = new PrintWriter(os);

            if (pw != null)
                pw.println(newUser);

        } catch (IOException e) {
            logger.error("Could not get output stream ", e);
        } catch (MCTException e) {
            logger.error(e);
        } finally {
            if (pw != null) {
                pw.flush();
                pw.close(); // else servers get Connection Reset
            }
            closeMonitor(socket);
        }
        currentUser = newUser;
        logger.info("reported: {0}", newUser);
        return true;
    }

    void setReporterExpiration(int reporterExpiration) {
        this.reporterExpirationSeconds = reporterExpiration;
    }

    class ExpirationTask {
        final Timer timer;
        private int expireSeconds;

        public ExpirationTask(int seconds) {
            expireSeconds = seconds;
            timer = new Timer();
            timer.schedule(new StopTask(), seconds * 1000);
        }

        class StopTask extends TimerTask {
            public void run() {
                mayRun = false;
                logger.info("Expiration of Reporter after {0} seconds", expireSeconds);
                timer.cancel();
            }
        }
    }
}
TOP

Related Classes of gov.nasa.arc.mct.identitymgr.mcc.ShiftChangeReporter$ExpirationTask$StopTask

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.