/*
 * jPOS Project [http://jpos.org]
 * Copyright (C) 2000-2020 jPOS Software SRL
 *
 * 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 java.util.List;
import java.util.Timer;
import java.util.TimerTask;
import java.util.Iterator;
import java.util.ArrayList;
import org.jpos.ee.DB;
import org.jpos.q2.QFactory;
import org.jpos.q2.QBeanSupport;
import org.jpos.core.XmlConfigurable;
import org.jpos.core.ConfigurationException;
import org.jdom2.Element;
import org.hibernate.HibernateException;

public class Monitor extends QBeanSupport implements XmlConfigurable {
    DB db;
    StatusManager mgr;
    long interval;
    String statusId;
    Element config;
    Timer timer;

    public void initService () {
        db = new DB();
        mgr = new StatusManager (db);
        timer = new Timer (true);
        Iterator iter = config.getChildren ("monitor").iterator();
        List handlers = new ArrayList();
        while (iter.hasNext()) {
            Element e = (Element) iter.next();
            try {
                registerTask (e);
            } catch (ConfigurationException ex) {
                getLog().error (ex);
            }
        }
    }
    public void destroyService() {
        getLog().info ("Cancelling timer");
        timer.cancel();
    }
    private void close() {
        try {
            db.close();
        } catch (HibernateException e) {
            getLog().error (e);
        }
    }
    public void setConfiguration (Element config) {
        this.config = config;
    }
    private void registerTask (Element e) 
        throws ConfigurationException
    {
        QFactory qf = getServer().getFactory();
        Object obj  = qf.newInstance (e.getChildTextTrim ("class"));
        if (!(obj instanceof MonitorTask)) {
            throw new ConfigurationException (
                obj.toString() + " is not an instance of MonitorTask"
            );
        }
        qf.setLogger (obj, e);
        qf.setConfiguration (obj, e);
        timer.schedule (
            new MonitorTimerTask (
                e.getAttributeValue("id"),
                (MonitorTask) obj), 
                getLong (e.getAttributeValue ("delay")),
                getLong (e.getAttributeValue ("period"))
        );
    }
    private long getLong (String l) 
        throws ConfigurationException
    {
        try {
            return Long.parseLong (l);
        } catch (Exception e) {
            throw new ConfigurationException (e);
        }
    }
    private synchronized void touch (String id, String detail) {
        int sp = detail.indexOf (" ");
        String state = Status.OFF;
        if (sp > 0 && detail.length() > sp) {
            state = detail.substring (0, sp);
            detail = detail.substring (++sp);
        }
        try {
            db.open ();
            mgr.touch (id, state, detail);
        } catch (Throwable t) {
            getLog().error (t);
        } finally {
            close();
        }
    }
    private synchronized String getNextCommand (String id) {
        try {
            db.open ();
            return mgr.getNextCommand (id);
        } catch (Throwable t) {
            getLog().error (t);
        } finally {
            close();
        }
        return null;
    }
    private synchronized void setResponse (String id, String response) {
        try {
            db.open ();
            mgr.setResponse (id, response);
        } catch (Throwable t) {
            getLog().error (t);
        } finally {
            close();
        }
    }
    public class MonitorTimerTask extends TimerTask {
        String id;
        MonitorTask task;
        public MonitorTimerTask (String id, MonitorTask task) {
            super();
            this.id = id;
            this.task = task;
        }
        public void run() {
            if (task instanceof TwoWayMonitorTask) {
                String command = getNextCommand (id);
                if (command != null) 
                    setResponse (id, 
                            ((TwoWayMonitorTask)task).command (command));
            }
            touch (id, task.checkService());
        }
    }
}


@@ -1077,16 +1077,50 @@
 eption;%0A
+import org.jpos.core.Environment;%0A
 import o
@@ -2277,32 +2277,88 @@
 Exception%0A    %7B%0A
+        Environment env = Environment.getEnvironment();%0A
         QFactory
@@ -2790,16 +2790,32 @@
         
+env.getProperty(
 e.getAtt
@@ -2831,16 +2831,17 @@
 ue(%22id%22)
+)
 ,%0A      
@@ -2887,32 +2887,48 @@
         getLong 
+(env.getProperty
 (e.getAttributeV
@@ -2942,16 +2942,17 @@
 delay%22))
+)
 ,%0A      
@@ -2969,16 +2969,32 @@
 getLong 
+(env.getProperty
 (e.getAt
@@ -3017,16 +3017,17 @@
 eriod%22))
+)
 %0A       

Use the 'Environment' class to get the monitor properties.