org.jpos.ee.status.StatusManager.java Source code

Java tutorial

Introduction

Here is the source code for org.jpos.ee.status.StatusManager.java

Source

/*
 * jPOS Project [http://jpos.org]
 * Copyright (C) 2000-2012 Alejandro P. Revilla
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package org.jpos.ee.status;

import org.hibernate.HibernateException;
import org.hibernate.ObjectNotFoundException;
import org.hibernate.Query;
import org.hibernate.Transaction;
import org.jpos.ee.DB;
import org.jpos.ee.SysLog;
import org.jpos.ee.SysLogManager;

import java.sql.SQLException;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * @author Alejandro Revilla
 */
public class StatusManager {
    DB db;
    SysLogManager syslog;
    public static final Map severity = new HashMap();

    static {
        severity.put(Status.OK, new Integer(SysLog.INFO));
        severity.put(Status.OFF, new Integer(SysLog.INFO));
        severity.put(Status.WARN, new Integer(SysLog.WARN));
        severity.put(Status.ERROR, new Integer(SysLog.ERROR));
        severity.put(Status.CRITICAL, new Integer(SysLog.CRITICAL));
    }

    public StatusManager(DB db) {
        super();
        this.db = db;
        this.syslog = new SysLogManager(db);
    }

    /**
     * @param id status id
     * @param state Status.OK, Status.WARN, Status.ERROR or user defined
     * @param detail optional detail information
     */
    public void touch(String id, String state, String detail) throws HibernateException, SQLException {
        Transaction tx = db.beginTransaction();
        Status status = touch(id, state, detail, tx);
        tx.commit();
        db.session().evict(status);
    }

    /**
     * @param id status id
     * @param state Status.OK, Status.WARN, Status.ERROR or user defined
     * @param detail optional detail information
     * @param tx transaction 
     */
    public Status touch(String id, String state, String detail, Transaction tx)
            throws HibernateException, SQLException {
        Status status = getStatus(id, true);
        if (state == null) {
            state = Status.ERROR;
            if (detail == null)
                detail = "";
            detail = detail + " invalid state (null)";
        }
        Date now = new Date();

        String previousState = status.getState();
        if ((status.getMaxEvents() > 0 || status.getMaxEvents() == -1) && previousState != null
                && !state.equals(previousState)) {
            Set events = status.getEvents();
            if (events != null) {
                purgeEvents(events, status.getMaxEvents());
                StringBuffer transition = new StringBuffer();
                transition.append(status.getState());
                transition.append("-->");
                transition.append(state);
                events.add(syslog.log("status:" + status.getId(), state, getSysLogSeverity(state),
                        transition.toString(), detail));
            }
        }
        status.setState(state);
        status.setLastTick(now);
        status.setDetail(detail);
        status.setExpired(false);
        return status;
    }

    /**
     * @param state
     * @return syslog severity associated with this state
     */
    public int getSysLogSeverity(String state) {
        if (state != null) {
            Integer sev = (Integer) severity.get(state);
            if (sev != null)
                return sev.intValue();
        }
        return SysLog.ERROR;
    }

    /**
     * @param key status name
     * @param state Status.OK, Status.WARN, Status.ERROR or user defined
     * @param info optional information
     */
    public void touch(String key, String state) throws HibernateException, SQLException {
        touch(key, state, null);
    }

    /**
     * @param id status id and optional name (used when create=true)
     * @param create if true and status doesn't exist, a new status with an optional name would be created.
     */
    public Status getStatus(String id, boolean create) throws HibernateException, SQLException {
        String name = "";
        int sp = id.indexOf(" ");
        if (sp > 0 && id.length() > sp) {
            name = id.substring(sp + 1);
            id = id.substring(0, sp);
        }
        Status s = null;
        try {
            s = (Status) db.session().load(Status.class, id);
            s.getName(); // force real load
        } catch (ObjectNotFoundException e) {
            if (create) {
                s = new Status();
                s.setId(id);
                s.setName(name.length() > 0 ? name : id);
                s.setTimeoutState(Status.OFF);
                s.setGroupName("Unfiled");
                db.save(s);
            }
        }
        return s;
    }

    /**
     * Get optional command associated with this status.
     * If response is not null, then we understand the command has been executed
     * already and we return null.
     * @return command or null
     */
    public String getNextCommand(String id) throws HibernateException, SQLException {
        Status status = getStatus(id, false);
        if (status != null)
            return status.getCommand();
        return null;
    }

    public void setNextCommand(String id, String command) throws HibernateException, SQLException {
        Transaction tx = db.beginTransaction();
        Status status = getStatus(id, false);
        if (status != null)
            status.setCommand(command);
        tx.commit();
    }

    /**
     * Set command to null and optionally log optional response
     * @param id status id
     * @param response response to be logged in revision history - may be null
     */
    public void setResponse(String id, String response) throws HibernateException, SQLException {
        Transaction tx = db.beginTransaction();
        Status status = getStatus(id, false);
        if (status != null && status.getCommand() != null && response != null
                && (status.getMaxEvents() > 0 || status.getMaxEvents() == -1)) {
            Set events = status.getEvents();
            if (events != null) {
                purgeEvents(events, status.getMaxEvents());
                StringBuffer sb = new StringBuffer();
                sb.append(status.getCommand());
                sb.append(" = ");
                sb.append(response);
                events.add(syslog.log("status:" + status.getId(), "AUDIT", SysLog.INFO, sb.toString(), null));
            }
        }
        status.setCommand(null); // command has been processed
        tx.commit();
        db.session().evict(status);
    }

    /**
     * check if a status is expired, and create appropriate syslog event
     * @param id status id
     */
    public void check(Status status) throws HibernateException, SQLException {
        Transaction tx = null;
        try {
            if (!status.isExpired() && status.hasExpired()) {
                tx = db.beginTransaction();
                String state = status.getState();
                String timeoutState = status.getTimeoutState();
                String detail = status.getDetail();
                if (state == null)
                    state = Status.ERROR;
                if (timeoutState == null)
                    timeoutState = Status.ERROR;
                if (detail == null)
                    detail = "(timeout)";
                else
                    detail = detail + " (timeout)";
                StringBuffer transition = new StringBuffer();
                if (!state.equals(timeoutState)) {
                    transition.append(state);
                    transition.append("-->");
                    transition.append(timeoutState);
                }
                Set events = status.getEvents();
                purgeEvents(events, status.getMaxEvents());
                if (status.getMaxEvents() > 0 || status.getMaxEvents() == -1) {
                    events.add(syslog.log("status:" + status.getId(), state, getSysLogSeverity(timeoutState),
                            transition.toString()));
                }
                status.setState(timeoutState);
                status.setExpired(true);
                status.setDetail(detail);
            }
        } finally {
            if (tx != null)
                tx.commit();
        }
    }

    /**
     * check if unexpired status entries became expired, and create 
     * appropriate syslog event.
     * @param id status id
     */
    public void check() throws HibernateException, SQLException {
        Iterator iter = findByExpired(false).iterator();
        while (iter.hasNext()) {
            check((Status) iter.next());
        }
    }

    public List findByExpired(boolean expired) throws SQLException, HibernateException {
        Query q = db.session().createQuery("from org.jpos.ee.status.Status where expired=:expired");
        q.setBoolean("expired", expired);
        return q.list();
    }

    private void purgeEvents(Set events, int maxEvents) {
        if (maxEvents > 0) {
            int rmcount = events.size() - maxEvents + 1;
            Iterator iter = events.iterator();
            for (; rmcount > 0 && iter.hasNext(); rmcount--) {
                iter.next();
                iter.remove();
            }
        }
    }
}