public class CheckJob implements Job {

    
    @Override
    public void execute(JobExecutionContext jec) throws JobExecutionException {
        try {
            JobDataMap dataMap = jec.getJobDetail().getJobDataMap();
            Integer cid = dataMap.getInt("cid");
            ServiceCheck sc = returnServiceCheck(cid);
            
            // is check active?
            if(!sc.isIs_active())
            {
                com.clavain.muninmxcd.logger.info("[CheckJob] Check " + sc.getCheckname() + " with id " + sc.getCid() + " is paused. skipping run");
                return;
            }
            
            ReturnServiceCheck rsc = new RunServiceCheck(sc).execute();

            
            ReturnDebugTrace rdt = null;
            sc.setIterations(sc.getIterations() + 1);

            // do trace because of error?
            if(rsc.getReturnValue() == 2 || rsc.getReturnValue() == 3)
            {
                rdt = new RunDebugTrace(sc).execute();
            }
            
            BasicDBObject doc = new BasicDBObject();
            if(rdt != null)
            {
                com.clavain.muninmxcd.logger.info("[CheckJob] Added Trace for Check "+sc.getCheckname()+" with id " + sc.getCid());
                doc.put("cid", rdt.getCid());
                doc.put("status", rdt.getRetval());
                if(rdt.getOutput().length() > 1)
                {
                    doc.put("output",rdt.getOutput());
                }  
                doc.put("time", rdt.getChecktime());
                doc.put("user_id", rdt.getUser_id());
                doc.put("type", "trace");
                com.clavain.muninmxcd.mongo_check_queue.put(doc);
            }
            
            // ok schedule this shit for data insertion
            if(rsc != null)
            {
                doc = null;
                doc = new BasicDBObject();
                doc.put("cid", rsc.getCid());
                doc.put("status", rsc.getReturnValue());
                if(rsc.getOutput().size() > 1)
                {
                    doc.put("pdata",rsc.getOutput().get(1));
                }
                doc.put("hread", rsc.getOutput().get(0));
                doc.put("time", rsc.getChecktime());
                doc.put("user_id", rsc.getUser_id());
                doc.put("type", "check");
                com.clavain.muninmxcd.mongo_check_queue.put(doc);
                // HELL SHIT DO WE HAVE A ALERT?
                if(rsc.getReturnValue() == 2 || rsc.getReturnValue() == 3)
                {
                      // check if its already handled
                      if(!checkIsProcessing(rsc.getCid()))
                      {
                        com.clavain.muninmxcd.logger.info("[ServiceCheck] - Check " + sc.getCheckname() + " with id " + sc.getCid() + " is in error state. Starting Inspector"); 
                        // START Inspector
                        com.clavain.muninmxcd.errorProcessing.add(rsc.getCid());
                        com.clavain.muninmxcd.check_error_queue.add(rsc);
                      }
                      else
                      {
                          com.clavain.muninmxcd.logger.info("[ServiceCheck] - Check " + sc.getCheckname() + " with id " + sc.getCid() + " is in error state but already in inspection");
                      }
                }
            }
            
        } catch (Exception ex) {
            Logger.getLogger(CheckJob.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
    
} public class CustomJob implements Job {
    @Override
    public void execute(JobExecutionContext jec) throws JobExecutionException {
          JobDataMap dataMap = jec.getJobDetail().getJobDataMap();
          Integer customId = dataMap.getInt("customId");
          
          Thread runner = new Thread(new CustomJobRunner(customId));
          int maxAge = getUnixtime() + 60;
          boolean keepMeRunning = true;
          
          runner.start();
          try
          {
            while(keepMeRunning)
            {
                Thread.sleep(1000);
                if(runner.isAlive())
                {
                    if(getUnixtime() > maxAge)
                    {
                      keepMeRunning = false;
                      logger.warn("interrupting CustomJobRunner for custom interval: " + customId);
                      runner.interrupt();
                      runner.suspend();
                      runner.interrupt();
                      if(runner.isAlive())
                      {
                          logger.warn("final call, stopping CustomJobRunner after 2 unsuccessfull interrupts for custom interval " + customId);
                          runner.stop();
                          Thread.sleep(100);
                          runner.stop();
                      }
                      return;
                    }
                }
                else
                {
                    return;
                }
            }
          } catch (Exception ex)
          {
              logger.error("Error in CustomJob: " + ex.getLocalizedMessage());
          }
    
    }
    
} public class MuninJob implements Job {

    @Override
    public void execute(JobExecutionContext jec) throws JobExecutionException {
          JobDataMap dataMap = jec.getJobDetail().getJobDataMap();
          Integer nodeId = dataMap.getInt("nodeId");
          
          Thread runner = new Thread(new JobRunner(nodeId));
          int maxjobage = Integer.parseInt(com.clavain.muninmxcd.p.getProperty("job.maxruntime","60"));
          int maxAge = getUnixtime() + maxjobage;
          boolean keepMeRunning = true;
          
          runner.start();
          try
          {
            while(keepMeRunning)
            {
                Thread.sleep(1000);
                if(runner.isAlive())
                {
                    if(getUnixtime() > maxAge)
                    {
                      keepMeRunning = false;
                      logger.warn("interrupting JobRunner for node: " + nodeId);
                      runner.interrupt();
                      Thread.sleep(500);
                      
                      if(runner.isAlive())
                      {
                          logger.warn("final call, stopping JobRunner after 2 unsuccessfull interrupts for node " + nodeId);
                          runner.stop();
                      }
                      return;
                    }
                }
                else
                {
                    return;
                }
            }
          } catch (Exception ex)
          {
              logger.error("Error in MuninJob: " + ex.getLocalizedMessage());
          }
    
    }
    
} public class ScheduledJob {
    private String jobId;
    private String userId;
    private String nextFireTime;

    /**
     * @return the jobName
     */
    public String getJobName() {
        return jobId;
    }

    /**
     * @param jobName the jobName to set
     */
    public void setJobName(String jobName) {
        this.jobId = jobName;
    }

    /**
     * @return the groupName
     */
    public String getGroupName() {
        return userId;
    }

    /**
     * @param groupName the groupName to set
     */
    public void setGroupName(String groupName) {
        this.userId = groupName;
    }

    /**
     * @return the nextFireTime
     */
    public String getNextFireTime() {
        return nextFireTime;
    }

    /**
     * @param nextFireTime the nextFireTime to set
     */
    public void setNextFireTime(String nextFireTime) {
        this.nextFireTime = nextFireTime;
    }
} public class ServiceCheck implements Serializable {
    private static final long serialVersionUID = -4991349865504351287L;
    private String  checkname;
    private Integer interval;
    private Integer checktype;
    private String nonearg;
    private String command;
    private String[] param;
    private Integer user_id;
    private Integer cid;
    private Integer iterations = 0;
    private boolean is_active = true;


    /**
     * @return the checkname
     */
    public String getCheckname() {
        return checkname;
    }

    /**
     * @param checkname the checkname to set
     */
    public void setCheckname(String checkname) {
        this.checkname = checkname;
    }

    /**
     * @return the interval
     */
    public Integer getInterval() {
        return interval;
    }

    /**
     * @param interval the interval to set
     */
    public void setInterval(Integer interval) {
        this.interval = interval;
    }

    /**
     * @return the checktype
     */
    public Integer getChecktype() {
        return checktype;
    }

    /**
     * @param checktype the checktype to set
     */
    public void setChecktype(Integer checktype) {
        this.checktype = checktype;
    }

    /**
     * @return the nonearg
     */
    public String getNonearg() {
        return nonearg;
    }

    /**
     * @param nonearg the nonearg to set
     */
    public void setNonearg(String nonearg) {
        this.nonearg = nonearg;
    }

    /**
     * @return the command
     */
    public String getCommand() {
        return command;
    }

    /**
     * @param command the command to set
     */
    public void setCommand(String command) {
        this.command = command;
    }

    /**
     * @return the param
     */
    public String[] getParam() {
        return param;
    }

    /**
     * @param param the param to set
     */
    public void setParam(String[] p_param) {
        param = p_param;
    }

    /**
     * @return the user_id
     */
    public Integer getUser_id() {
        return user_id;
    }

    /**
     * @param user_id the user_id to set
     */
    public void setUser_id(Integer user_id) {
        this.user_id = user_id;
    }

    /**
     * @return the cid
     */
    public Integer getCid() {
        return cid;
    }

    /**
     * @param cid the cid to set
     */
    public void setCid(Integer cid) {
        this.cid = cid;
    }


    /**
     * @return the iterations
     */
    public Integer getIterations() {
        return iterations;
    }

    /**
     * @param iterations the iterations to set
     */
    public void setIterations(Integer iterations) {
        this.iterations = iterations;
    }

    /**
     * @return the is_active
     */
    public boolean isIs_active() {
        return is_active;
    }

    /**
     * @param is_active the is_active to set
     */
    public void setIs_active(boolean is_active) {
        this.is_active = is_active;
    }


} public class MuninNode 
{
  private String    str_nodename;
  private String    str_hostname    = "unset";  
  private int       i_port          = 4949;
  private String    str_group;
  private boolean   b_isRunning     = false;
  private transient long  l_lastFrontendQuery;   
  private String    str_muninVersion = "";
  private transient CopyOnWriteArrayList<MuninPlugin> v_loaded_plugins;
  private transient int       i_GraphCount    = 0;
  private int       i_lastRun        = 0;
  private Integer   node_id          = 0;
  private Integer   user_id          = 0;
  private int       queryInterval    = 0;
  private int       last_plugin_load = 0;
  private String    authpw           = "";
  private boolean   is_init = false;
  private boolean   track_pkg       = false;
  private boolean   essentials      = false;
  private int       last_pkg_update = 0;
  private int       last_essentials_update = 0;
  private transient Socket lastSocket;
  private String    str_via = "unset";

  
    public void setQueryInterval(Integer p_int)
    {
        queryInterval = p_int;
    }
    
    public int getQueryInterval()
    {
        return queryInterval;
    }
  
    public int getGraphCount()
    {
        return i_GraphCount;
    }

    /**
     * @return the str_hostname
     */
    public String getHostname()
    {
        return str_hostname;
    }

    /**
     * @param str_hostname the str_hostname to set
     */
    public void setHostname(String str_hostname)
    {
        this.str_hostname = str_hostname;
    }

    /**
     * @return the i_port
     */
    public int getPort()
    {
        return i_port;
    }

    /**
     * @param i_port the i_port to set
     */
    public void setPort(int i_port)
    {
        this.i_port = i_port;
    }

    /**
     * @return the str_nodename
     */
    public String getNodename()
    {
        return str_nodename;
    }

    /**
     * @param str_nodename the str_nodename to set
     */
    public void setNodename(String str_nodename)
    {
        this.str_nodename = str_nodename;
    }

    /**
     * @return the str_group
     */
    public String getGroup()
    {
        return str_group;
    }

    /**
     * @param str_group the str_group to set
     */
    public void setGroup(String str_group)
    {
        this.str_group = str_group;
    }
    
    /**
     * 
     * @return if the Thread is active or not 
     */
    public boolean isRunning()
    {
        return b_isRunning;
    }
    
    public void setIsRunning(boolean p_isRunning)
    {
        b_isRunning = p_isRunning;
    }

    
    /** 
     * will retrieve a list of loaded munin plugins for this host. If the node was never
     * contacted before the list is downloaded from munin-node
     * 
     * @return list of plugins
     */
    public CopyOnWriteArrayList<MuninPlugin> getPluginList()
    {
        if(getLoadedPlugins() == null)
        {
            // using logger from main class because of gson throwing stackoverflow otherwise
            logger.info("Empty Pluginlist for " + this.getHostname() + ". Loading from munin-node...");
            loadPlugins();
        }
        return getLoadedPlugins();
    }
    

    /**
     * Will load the plugin list from munin-node
     */
    public boolean loadPlugins()
    {
        setLoadedPlugins(new CopyOnWriteArrayList<MuninPlugin>());
        String l_lastProceeded = "";
        
        
        try 
        {
            Socket cs = new Socket();
            cs.setKeepAlive(false);
            cs.setSoLinger(true, 0);
            cs.setReuseAddress(true);  
            cs.setSoTimeout(com.clavain.muninmxcd.socketTimeout);
            if(!str_via.equals("unset"))
            {
                cs.connect(new InetSocketAddress(this.getStr_via(), this.getPort()),com.clavain.muninmxcd.socketTimeout);    
            }
            else
            {
                cs.connect(new InetSocketAddress(this.getHostname(), this.getPort()),com.clavain.muninmxcd.socketTimeout);
            }
          
            if(p.getProperty("kill.sockets").equals("true"))
            {
                SocketCheck sc = new SocketCheck(cs,getUnixtime());
                sc.setHostname(this.getHostname());
                com.clavain.muninmxcd.v_sockets.add(sc);
            }
            PrintStream os = new PrintStream( cs.getOutputStream() );
            BufferedReader in = new BufferedReader(new InputStreamReader( cs.getInputStream()) );  
            
            String s = in.readLine();

            if(s != null)
            {
                // Set version
                os.println("version");
                Thread.sleep(150);
                s = in.readLine();
                
                String version = s.substring(s.indexOf(":")+1,s.length()).trim();
                this.str_muninVersion = version;
                
                if(authpw != null)
                {
                    // if authpw is set, verify
                    if(!authpw.trim().equals(""))
                    {
                        os.println("config muninmxauth");
                        Thread.sleep(150);
                        String apw = in.readLine();
                        s = in.readLine();
                        if(!apw.trim().equals(this.getAuthpw()))
                        {
                            logger.error("Invalid muninmxauth password for host: " + this.getHostname());
                            cs.close();
                            return false;
                        }
                    }
                }
                // check anyway if muninmxauth plugin is present
                else
                {
                    os.println("config muninmxauth");
                    Thread.sleep(100);
                    String apw = in.readLine();
                    if(!apw.trim().equals("# Unknown service"))
                    {
                        logger.error("no auth password given, but muninmxauth plugin present on " + this.getHostname());
                        cs.close();
                        return false;                        
                    }
                    s = in.readLine();
                }
                
                // get list of available plugins
                if(str_via.equals("unset"))
                {
                    os.println("list");
                }
                else
                {
                    os.println("list " + str_hostname);
                }

                Thread.sleep(250);
                s = in.readLine();
 
                // if response is empty and host is not via, do a list $hostname
                if(s.trim().equals("") && str_via.equals("unset"))
                {
                    logger.info("Plugin Response Empty on " + this.getHostname() + " trying to load with list $hostname");
                    os.println("list " + this.getHostname());
                    Thread.sleep(250);
                    s = in.readLine();
                }
                
                String l_tmp;
                StringTokenizer l_st = new StringTokenizer(s, " ");
                
                // create plugin
                MuninPlugin l_mp = new MuninPlugin();
                // negative support
                ArrayList<String> tmp_negatives = new ArrayList<String>();
                
                while(l_st.hasMoreTokens())
                {
                     
                    String l_strPlugin = l_st.nextToken();
                    
                    // check for track_pkg and muninmx essentials
                    if(l_strPlugin.equals("muninmx_trackpkg"))
                    {
                        this.setTrack_pkg(true);
                        continue;
                    }
                    
                    // got essentials?
                    if(l_strPlugin.equals("muninmx_essentials"))
                    {
                        this.setEssentials(true);
                        continue;
                    }                    
                    
                    if(isPluginIgnored(l_strPlugin.toUpperCase()))
                    {
                        continue;
                    }
                                      
                    l_mp.setPluginName(l_strPlugin);

                    os.println("config " + l_strPlugin);
                    
                    // create graphs for plugin
                    int l_iGraphsFound = 0;  
                    int l_iTmp         = 0;
                    MuninGraph  l_mg = new MuninGraph();                    
                    l_mg.setQueryInterval(this.getQueryInterval());
                    while ((l_tmp = in.readLine()) != null) 
                    {
                      if(l_tmp.startsWith("."))
                      {
                        break;
                      }
                      // collect graphs only for plugin
                      String l_strName;
                      String l_strType;
                      String l_strValue;

                      
                      if(!l_tmp.contains("graph_") && !l_tmp.trim().equals("") && !l_tmp.contains("host_name") && !l_tmp.contains("multigraph") && !l_tmp.trim().equals("graph no") && !l_tmp.trim().equals("# Bad exit") && !l_tmp.trim().contains("info Currently our peer") && !l_tmp.trim().startsWith("#") && !l_tmp.trim().contains("Bonding interface errors"))
                      {
                        l_lastProceeded = l_tmp;
                        l_strName  = l_tmp.substring(0,l_tmp.indexOf("."));
                        l_strType  = l_tmp.substring(l_tmp.indexOf(".")+1,l_tmp.indexOf(" "));
                        l_strValue = l_tmp.substring(l_tmp.indexOf(" ")+1,l_tmp.length());
                        //System.err.println("Name: " + l_strName + " Type: " + l_strType + " Value: " + l_strValue);
                        
                        if(l_strType.equals("label"))
                        {
                           l_iTmp++;
                          
                           if(l_iTmp > 1)
                           {
                               l_mp.addGraph(l_mg);
                               l_mg = new MuninGraph();
                               l_mg.setQueryInterval(this.getQueryInterval());
                           }
                           l_mg.setGraphName(l_strName);
                           l_mg.setGraphLabel(l_strValue);
                        }
                        else if(l_strType.equals("draw"))
                        {
                            l_mg.setGraphDraw(l_strValue);
                        }
                        else if(l_strType.equals("type"))
                        {
                            l_mg.setGraphType(l_strValue);
                        }
                        else if(l_strType.equals("info"))
                        {
                            l_mg.setGraphInfo(l_strValue);
                        }
                        else if(l_strType.equals("negative"))
                        {
                            // add to temporary negative list to set negatives later
                            tmp_negatives.add(l_strValue);
                        }

                        //System.out.println(l_strName); 
                        //System.out.println(l_strType);
                        //System.out.println(l_strValue);
                      }
                      else
                      {
                          // set plugin title
                          if(l_tmp.contains("graph_title"))
                          {
                              l_mp.setPluginTitle(l_tmp.substring(12,l_tmp.length()));
                          }
                          // set plugin info, if any
                          if(l_tmp.contains("graph_info"))
                          {
                              l_mp.setPluginInfo(l_tmp.substring(11,l_tmp.length()));
                          }
                          // set graph category
                          if(l_tmp.contains("graph_category"))
                          {
                              l_mp.setPluginCategory(l_tmp.substring(15,l_tmp.length()));
                          }
                          // set graph vlabel
                          if(l_tmp.contains("graph_vlabel"))
                          {
                              l_mp.setPluginLabel(l_tmp.substring(13,l_tmp.length()));
                          }
                          // set plugin title
                          if(l_tmp.contains("graph_mxdraw"))
                          {
                              l_mp.setStr_LineMode(l_tmp.substring(13,l_tmp.length()));
                          }                          
                      }
                      
                    }
                  
                    
                    // add to pluginlist
                    l_mp.addGraph(l_mg);
                    
                   Iterator it = l_mp.getGraphs().iterator();
                   while(it.hasNext())
                   {
                       MuninGraph l_mpNg = (MuninGraph) it.next();
                       if(tmp_negatives.contains(l_mpNg.getGraphName()))
                       {
                           l_mpNg.setNegative(true);
                       }
                   }
                    
                    // add plugin if it got valid graphs and add nodeid (req. for alerts)
                    if(l_mp.getGraphs().size() > 0)
                    {
                        l_mp.set_NodeId(this.getNode_id());
                        getLoadedPlugins().add(l_mp);
                    }
                    // flush temporary negatives
                    tmp_negatives.clear();
                    l_mp = null;
                    l_mp = new MuninPlugin();
                    //String l_strGraphTitle = s.substring(s.indexOf("graph_title") + 11,s.length());
                    //System.out.println(" - " + l_strGraphTitle);
                }
                cs.close();
                in.close();
                os.close();
                last_plugin_load = getUnixtime();
                //System.out.println(s);
            }
            else
            {
                cs.close();
                in.close();
                os.close();
                logger.warn("Error loading plugins on " + str_hostname + " ("+this.getNode_id()+"). Check connectivity or munin-node");
            }
            /*
            for (MuninPlugin l_mn : getLoadedPlugins()) {
                i_GraphCount = i_GraphCount + l_mn.getGraphs().size();
                logger.debug(l_mn.getGraphs().size() + " graphs found for plugin: " + l_mn.getPluginName().toUpperCase() + " on node: " + this.getNodename());
            }*/
        } catch (Exception ex) {
            logger.error("Error loading plugins on " + str_hostname + " ("+this.getNode_id()+") : " + ex.getMessage());
            ex.printStackTrace();
            return false;
        } 

        return true;
    }
            

    public void run() {
        b_isRunning = true;

        if(this.str_via.equals("unset"))
        {
            logger.info(getHostname() + " Monitoring job started");
        }
        else
        {
            logger.info(getHostname() + " (VIA: "+this.str_via+") Monitoring job started");
        }
        
        int iCurTime = getUnixtime();
        int iPluginRefreshTime = last_plugin_load + Integer.parseInt(p.getProperty("plugin.refreshtime"));
        try {
            // update plugins, maybe we have some new :)
            // double try to load plugins if fail
       
            if(getPluginList().size() > 0)
            {
                if(!is_init)
                {
                    logger.info("[Job: " + getHostname() + "] Updating Database");
                    // update graphs in database too
                    for(MuninPlugin it_pl : getPluginList()) {
                        if(it_pl.getGraphs().size() > 0)
                        {
                            //logger.info(it_pl.getPluginName());
                            dbUpdatePluginForNode(getNode_id(),it_pl);
                        }
                     }
                    // delete now missing plugins
                    dbDeleteMissingPlugins(getNode_id(),getPluginList());
                    logger.info("[Job: " + getHostname() + "] Databaseupdate Done");
                    is_init = true;
                }
                else
                {
                    if(iCurTime > iPluginRefreshTime )
                    {
                        logger.info("Refreshing Plugins on " + this.getHostname());
                        this.loadPlugins();
                        dbUpdateAllPluginsForNode(this);
                    }
                }
            }
            else
            {
                this.loadPlugins();
            }
                  
            
            Socket clientSocket = new Socket();
            clientSocket.setSoTimeout(com.clavain.muninmxcd.socketTimeout);
            clientSocket.setKeepAlive(false);
            clientSocket.setReuseAddress(true);   
            if(this.str_via.equals("unset"))
            {            
                clientSocket.connect(new InetSocketAddress(this.getHostname(), this.getPort()),com.clavain.muninmxcd.socketTimeout);
            }
            else
            {
                clientSocket.connect(new InetSocketAddress(this.getStr_via(), this.getPort()),com.clavain.muninmxcd.socketTimeout);
            }
            lastSocket = clientSocket;
            SocketCheck sc = new SocketCheck(clientSocket,getUnixtime());
            if(p.getProperty("kill.sockets").equals("true"))
            {  
                sc.setHostname(this.getHostname());
                com.clavain.muninmxcd.v_sockets.add(sc);
            }
            this.i_lastRun = getUnixtime();

            // track packages?
            if(this.track_pkg)
            {
                updateTrackPackages(clientSocket);
            }
            
            // gather essentials?
            if(this.essentials)
            {
                updateEssentials(clientSocket);
            }
            
            // update graphs for all plugins
            Iterator it = this.getLoadedPlugins().iterator();
            while(it.hasNext())
            {
                MuninPlugin l_mp = (MuninPlugin) it.next();
                if(logMore)
                {
                    logger.info(getHostname() + " fetching graphs for " + l_mp.getPluginName().toUpperCase());
                }
                // snmp support
                if(!str_via.equals("unset"))
                { 
                    l_mp.updateAllGraps(this.getStr_via(), this.getPort(), clientSocket, getQueryInterval());
                }  
                else
                {
                    l_mp.updateAllGraps(this.getHostname(), this.getPort(), clientSocket, getQueryInterval());
                }
                // add all graphs to insertion queue for mongodb
                queuePluginFetch(l_mp.returnAllGraphs(), l_mp.getPluginName());
            }
            clientSocket.close();
            
            if(p.getProperty("kill.sockets").equals("true"))
            {
                com.clavain.muninmxcd.v_sockets.remove(sc);
            }
            sc = null;
        } catch (Exception ex) {
           logger.fatal("Error in thread for host: " + getHostname() + " : " + ex.getLocalizedMessage());
           ex.printStackTrace();
        }
        int iRunTime = getUnixtime() - iCurTime;
        dbUpdateLastContact(this.getNode_id());
        logger.info(getHostname() + " Monitoring job stopped - runtime: " + iRunTime);
        
    }

    
    /*
     * update essentials
     */
    private void updateEssentials(Socket p_socket)
    {
        String decodestr = "";
        try {
            PrintStream os = new PrintStream( p_socket.getOutputStream() );
            BufferedReader in = new BufferedReader(new InputStreamReader( p_socket.getInputStream()) );
            os.println("config muninmx_essentials");
            
            // skip first line if starts with #
            decodestr = in.readLine();
            if(decodestr.startsWith("#"))
            {
                decodestr = in.readLine();    
            }

            if(decodestr.equals("."))
            {
                decodestr = in.readLine();    
            }             
            BasicDBObject doc = new BasicDBObject();
            doc.put("data", decodestr);
            doc.put("time",getUnixtime());
            doc.put("node", this.node_id);
            doc.put("type","essential");
            com.clavain.muninmxcd.mongo_essential_queue.add(doc);  
            logger.info("Essentials Updated for Node: " + this.getHostname() + ": received base64 (length): " + decodestr.length());
            last_essentials_update = getUnixtime();
            // read following .
            in.readLine();
        } catch (Exception ex)
        {
            logger.error("Error in updateEssentials for Node " + this.getHostname() + " : " + ex.getLocalizedMessage());
            logger.error("updateEssentials for Node " + this.getHostname() + " received: " + decodestr);
            ex.printStackTrace();     
        }
    }
    
    /*
     * update track package log
     */
    private void updateTrackPackages(Socket p_socket)
    {
        // only try to update this once per hour
        int curTime = getUnixtime();
        int lalert = this.last_pkg_update + 3600;
        if(lalert > curTime )
        {  
            return;
        } 
        
        String decodestr = "";
        try 
        {
            logger.info("TrackPackages - fetching " + this.str_hostname);
            PrintStream os = new PrintStream( p_socket.getOutputStream() );
            BufferedReader in = new BufferedReader(new InputStreamReader( p_socket.getInputStream()) );
            os.println("config muninmx_trackpkg");
            // skip first line if starts with #
            decodestr = in.readLine();
            if(decodestr.startsWith("#"))
            {
                decodestr = in.readLine();    
            }

            if(decodestr.equals("."))
            {
                decodestr = in.readLine();    
            }   
            byte[] decode = Base64.decodeBase64(decodestr);
            ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(decode); 
            GZIPInputStream gzipInputStream;
            gzipInputStream = new GZIPInputStream(byteArrayInputStream);

            InputStreamReader inputStreamReader = new InputStreamReader(gzipInputStream);
            BufferedReader bufferedReader = new BufferedReader(inputStreamReader, 4);

            String read;
            String sum = bufferedReader.readLine();
            if(sum == null) 
            {  
                logger.error("TrackPackages - sum is null for: " + this.str_hostname);
                return; 
            }  
            String dist = bufferedReader.readLine();
            String ver  = bufferedReader.readLine();
            String kernel = bufferedReader.readLine();
            if(dbTrackLogChangedForNode(sum, this.node_id))
            {
                logger.info("TrackPackages - packages changed, updating " + this.str_hostname);
                // purge old logs
                removeOldPackageTrack(this.node_id);
                
                dbUpdateNodeDistVerKernel(sum,dist, ver, kernel, this.node_id);      
                int i = 0;
                while ((read = bufferedReader.readLine()) != null) 
                {
                     BasicDBObject doc = new BasicDBObject();
                     doc.put("package", read);
                     doc.put("time",getUnixtime());
                     doc.put("node", this.node_id);
                     doc.put("type","trackpkg");
                     com.clavain.muninmxcd.mongo_essential_queue.add(doc);
                     i++;
                } 
                logger.info("TrackPackages Updated for Node: " + this.getHostname() + " ("+dist+" " + ver + " " + kernel + "). tracking " + i + " packages"); 
            }
            else
            {
                logger.info("TrackPackages - sum not changed since last run for Node: " + this.getHostname());
            }
            this.last_pkg_update = getUnixtime();

        } catch (Exception ex)
        {
            logger.error("Error in updateTrackPackages for Node " + this.getHostname() + " : " + ex.getLocalizedMessage());
            logger.error("updateTrackPackages for Node " + this.getHostname() + " received: " + decodestr);
            ex.printStackTrace();
        }
            
    }
    
    public void queuePluginFetch(ArrayList<MuninGraph> p_almg, String p_strPluginName)
    {
        queuePluginFetch(p_almg, p_strPluginName, 0);
    }
    
    /**
     * fill insertion queue with current graph values for each plugin
     */
    public void queuePluginFetch(ArrayList<MuninGraph> p_almg, String p_strPluginName, int p_iCustomId)
    {
        Iterator<MuninGraph> it = p_almg.iterator();
        while(it.hasNext())
        {
            MuninGraph mg = it.next();
            // prepare document object
            BasicDBObject doc = new BasicDBObject();
            doc.put("hostname", this.getHostname());
            doc.put("plugin", p_strPluginName);
            doc.put("graph", mg.getGraphName());
            doc.put("value", mg.getGraphValue().toString());
            doc.put("recv", mg.getLastGraphTime());
            doc.put("user_id", this.getUser_id());
            doc.put("nodeid", this.getNode_id());
            
            if(p_iCustomId > 0)
            {
                doc.put("customId",p_iCustomId);
            }
            
            // only queue if plugin is initialized or it is a if_err plugin
            if(mg.isInit() || p_strPluginName.startsWith("if_err") || p_strPluginName.equals("swap"))
            {
                com.clavain.muninmxcd.mongo_queue.add(doc);
                mg.setLastQueued(getUnixtime());
                
                logger.debug("Queued: " + this.getHostname() + " (" + p_strPluginName + " / " + mg.getGraphName() + ") Value: " + mg.getGraphValue());
                if(logMore)
                {
                    logger.info("Queued: " + this.getHostname() + " (" + p_strPluginName + " / " + mg.getGraphName() + ") Value: " + mg.getGraphValue());   
                }                
            }

        }
    }
    
    /**
     * @return the v_loaded_plugins
     */
    public CopyOnWriteArrayList<MuninPlugin> getLoadedPlugins() {
        return v_loaded_plugins;
    }

    /**
     * @param v_loaded_plugins the v_loaded_plugins to set
     */
    public void setLoadedPlugins(CopyOnWriteArrayList<MuninPlugin> v_loaded_plugins) {
        this.v_loaded_plugins = v_loaded_plugins;
    }

    /**
     * @return the l_lastFrontendQuery
     */
    public long getLastFrontendQuery() {
        return l_lastFrontendQuery;
    }

    /**
     * @param l_lastFrontendQuery the l_lastFrontendQuery to set
     */
    public void setLastFrontendQuery(long l_lastFrontendQuery) {
        this.l_lastFrontendQuery = l_lastFrontendQuery;
    }
    
    /**
     * Sets lastFrontendQuery to current unixtime
     */
    public void setLastFrontendQuery()
    {
        l_lastFrontendQuery = System.currentTimeMillis() / 1000L;
    }

    private void cleanUpGraphs() 
    {
        Iterator it = this.getLoadedPlugins().iterator();
        while(it.hasNext())
        {
            MuninPlugin l_mp = (MuninPlugin) it.next();
            Iterator itg = l_mp.getGraphs().iterator();
            while(itg.hasNext())
            {
                MuninGraph l_mg = (MuninGraph) itg.next();
                l_mg.setGraphValue("0");
                l_mg.setLastGraphValue("0");
                l_mg.setLastGraphValueCounter("0");
            }
        }
    }

    /**
     * @return the node_id
     */
    public Integer getNode_id() {
        return node_id;
    }

    /**
     * @param node_id the node_id to set
     */
    public void setNode_id(Integer node_id) {
        this.node_id = node_id;
    }

    /**
     * @return the user_id
     */
    public Integer getUser_id() {
        return user_id;
    }

    /**
     * @param user_id the user_id to set
     */
    public void setUser_id(Integer user_id) {
        this.user_id = user_id;
    }

    /**
     * @return the lastSocket
     */
    public Socket getLastSocket() {
        return lastSocket;
    }

    /**
     * @return the str_via
     */
    public String getStr_via() {
        return str_via;
    }

    /**
     * @param str_via the str_via to set
     */
    public void setStr_via(String str_via) {
        this.str_via = str_via;
    }

    /**
     * @return the authpw
     */
    public String getAuthpw() {
        return authpw;
    }

    /**
     * @param authpw the authpw to set
     */
    public void setAuthpw(String authpw) {
        this.authpw = authpw;
    }

    /**
     * @return the track_pkg
     */
    public boolean isTrack_pkg() {
        return track_pkg;
    }

    /**
     * @param track_pkg the track_pkg to set
     */
    public void setTrack_pkg(boolean track_pkg) {
        this.track_pkg = track_pkg;
    }

    /**
     * @return the essentials
     */
    public boolean isEssentials() {
        return essentials;
    }

    /**
     * @param essentials the essentials to set
     */
    public void setEssentials(boolean essentials) {
        this.essentials = essentials;
    }
}
 public class MuninPlugin {
    private String str_PluginName;
    private String str_PluginTitle;
    private String str_PluginInfo;
    private String str_PluginCategory;
    private String str_PluginLabel;
    private String str_LineMode = "default";
    private long   l_lastFrontendQuery;
    private transient long   l_lastMuninQuery;
    private transient Socket csMuninSocket;
    private transient boolean b_IntervalIsSeconds = false;
    private int i_nodeId;
    private transient Integer from_time;
    private transient Integer to_time;
    private transient String timezone;
    private transient Integer customId;
    private transient Integer query_interval;
    private transient Integer user_id;
    private transient String crontab = "false";
    private ArrayList<MuninGraph> v_graphs = new ArrayList<>();

    
    public void addGraph(MuninGraph p_graph)
    {
        getGraphs().add(p_graph);
    }
    
    /**
     * @return the str_PluginName
     */
    public String getPluginName() {
        return str_PluginName;
    }

    /**
     * @param str_PluginName the str_PluginName to set
     */
    public void setPluginName(String str_PluginName) {
        this.str_PluginName = str_PluginName;
    }

    /**
     * @return the str_GraphTitle
     */
    public String getPluginTitle() {
        return str_PluginTitle;
    }

    /**
     * @param str_GraphTitle the str_GraphTitle to set
     */
    public void setPluginTitle(String str_GraphTitle) {
        this.str_PluginTitle = str_GraphTitle;
    }

    /**
     * @return the str_GraphInfo
     */
    public String getPluginInfo() {
        return str_PluginInfo;
    }

    /**
     * @param str_PluginInfo the str_GraphInfo to set
     */
    public void setPluginInfo(String str_GraphInfo) {
        this.str_PluginInfo = str_GraphInfo;
    }

    /**
     * @return the v_graphs
     */
    public ArrayList<MuninGraph> getGraphs() {
        return getV_graphs();
    }

    /**
     * @param v_graphs the v_graphs to set
     */
    public void setGraphs(ArrayList<MuninGraph> v_graphs) {
        this.setV_graphs(v_graphs);
    }

    /**
     * @return the l_lastFrontendQuery
     */
    public long getLastFrontendQuery() {
        return l_lastFrontendQuery;
    }

    /**
     * @param l_lastFrontendQuery the l_lastFrontendQuery to set
     */
    public void setLastFrontendQuery(long l_lastFrontendQuery) {
        this.l_lastFrontendQuery = l_lastFrontendQuery;
    }
    
    /**
     * Sets lastFrontendQuery to current unixtime
     */
    public void setLastFrontendQuery()
    {
        l_lastFrontendQuery = System.currentTimeMillis() / 1000L;
    }
    
    
    /*
     * will connect to munin if no connections exists and will update
     * values for all graphs, then return all graphs with updated stats
     */
    public void updateAllGraps(String p_strHostname, int p_iPort, Socket p_socket, int p_queryInterval)
    {

        try
        {
            setCsMuninSocket(p_socket);
            // connection available?
            if(getCsMuninSocket() != null)
            {
                if(!csMuninSocket.isConnected() || getCsMuninSocket().isClosed())
                {
                    setCsMuninSocket(null);
                    setCsMuninSocket(new Socket());
                    getCsMuninSocket().setSoTimeout(5000);
                    getCsMuninSocket().setKeepAlive(false);
                    getCsMuninSocket().setSoLinger(true, 0);
                    getCsMuninSocket().setReuseAddress(true);                     
                    getCsMuninSocket().connect(new InetSocketAddress(p_strHostname, p_iPort),5000);
                    logger.info("Reconnecting to " + p_strHostname);
                }
            }
            else
            {
                setCsMuninSocket(new Socket());
                getCsMuninSocket().setSoTimeout(5000);
                getCsMuninSocket().setKeepAlive(false);
                getCsMuninSocket().setSoLinger(true, 0);
                getCsMuninSocket().setReuseAddress(true);                  
                getCsMuninSocket().connect(new InetSocketAddress(p_strHostname, p_iPort),5000);
            }
            PrintStream os = new PrintStream( getCsMuninSocket().getOutputStream() );
            BufferedReader in = new BufferedReader(new InputStreamReader( getCsMuninSocket().getInputStream()) );
            os.println("fetch " + this.getPluginName());
            if(logMore)
            {
                logger.info(p_strHostname + " Executed:  fetch " + this.getPluginName());
            }
            String line;    
            while((line = in.readLine()) != null) {
                if(line.startsWith("."))
                {
                    if(logMore)
                    {
                        logger.info(p_strHostname + " Executed:  fetch " + this.getPluginName() + " BUT INSTEAD GOT . AS RESULT");
                    }                    
                    // close wait fix for single mode
                    if(customId != null)
                    {
                        os.println("quit");
                        os.close();
                        in.close();
                        csMuninSocket.close();
                        csMuninSocket = null;
                    }                        
                    return;
                }
                if(logMore)
                {                
                    logger.info(p_strHostname + " Received from (fetch " + this.getPluginName()+") Result: " + line);
                }
                //System.out.println(line);
                if(line.contains("value") && !line.contains("#"))
                {
                    String l_graphName = line.substring(0,line.indexOf("."));
                    String l_value      = line.substring(line.indexOf(" ")+1,line.length());
                    if(logMore)
                    {
                        logger.info(p_strHostname + " - " + l_graphName + " - " + l_value);
                    }
                    Iterator it = this.getV_graphs().iterator();
                    while (it.hasNext())
                    {
                        MuninGraph l_mg = (MuninGraph) it.next();
                        l_mg.setQueryInterval(p_queryInterval);
                        // required for customer plugin intervals
                        if(IntervalIsSeconds() != false)
                        {
                           l_mg.setIntervalIsSeconds(true); 
                        }
                        
                        if(logMore)
                        {
                            logger.info(p_strHostname + " - equalcheck - Given: " + l_mg.getGraphName() + " required: " + l_graphName);
                        }                          
                        if(l_mg.getGraphName().equals(l_graphName))
                        {    
                            if(logMore)
                            {
                                logger.info(p_strHostname + " - equalcheck passed - Given: " + l_mg.getGraphName() + " found: " + l_graphName);
                            }                                
                            if(l_value.trim().length() < 1)
                            {
                                l_mg.setGraphValue("0");
                            }
                            else
                            {
                                // check....
                                try
                                {
                                    if(logMore)
                                    {
                                        logger.info(p_strHostname + " - graph: " + l_mg.getGraphName() + " calling setGraphValue with value: " + l_value.trim());
                                    }                                    
                                    l_mg.setGraphValue(l_value.trim());
                                    // check if we need to add alert value as well
                                    if(l_mg.isInit())
                                    {
                                        ArrayList<Alert> av = getAlertByNidPluginAndGraph(this.get_NodeId(),this.getPluginName(),l_mg.getGraphName());
                                        if(!av.isEmpty())
                                        {
                                            for (Alert l_av : av) {
                                                l_av.addAndCheckSample(getUnixtime(), l_mg.getGraphValue());
                                            }
                                        }
                                    }
                                } catch (Exception ex)
                                {
                                    l_mg.setGraphValue("U");
                                    System.err.println(p_strHostname + " setvalue error on "+this.str_PluginName+" with " + l_value + " details: " + ex.getLocalizedMessage());
                                    ex.printStackTrace();
                                }
                            }
                        }
                        
                    }
                }
            }

            if(customId != null)
            {
                os.close();
                in.close();
                csMuninSocket.shutdownInput();
                csMuninSocket.shutdownOutput();
                csMuninSocket.close();
                
                csMuninSocket = null;
            }

        } catch (Exception ex)
        {
            //this.getCsMuninSocket().close();
            //try { csMuninSocket.close(); } catch (Exception e) {};
            logger.error(p_strHostname + " Unable to connect/process: " + ex.getMessage());
            ex.printStackTrace();
        }
        
    }
    
    public ArrayList<MuninGraph> returnAllGraphs()
    {
        return getV_graphs();   
    }

    void setPluginCategory(String p_strCategory) {
        setStr_PluginCategory(p_strCategory);
    }

    /**
     * @return the str_PluginLabel
     */
    public String getPluginLabel() {
        return str_PluginLabel;
    }

    /**
     * @param str_PluginLabel the str_PluginLabel to set
     */
    public void setPluginLabel(String str_PluginLabel) {
        this.str_PluginLabel = str_PluginLabel;
    }

    /**
     * @return the str_PluginCategory
     */
    public String getStr_PluginCategory() {
        return str_PluginCategory;
    }

    /**
     * @param str_PluginCategory the str_PluginCategory to set
     */
    public void setStr_PluginCategory(String str_PluginCategory) {
        this.str_PluginCategory = str_PluginCategory;
    }

    /**
     * @return the b_IntervalIsSeconds
     */
    public boolean IntervalIsSeconds() {
        return b_IntervalIsSeconds;
    }

    /**
     * @param b_IntervalIsSeconds the b_IntervalIsSeconds to set
     */
    public void set_IntervalIsSeconds(boolean b_IntervalIsSeconds) {
        this.b_IntervalIsSeconds = b_IntervalIsSeconds;
    }

    /**
     * @return the i_nodeId
     */
    public int get_NodeId() {
        return i_nodeId;
    }

    /**
     * @param i_nodeId the i_nodeId to set
     */
    public void set_NodeId(int i_nodeId) {
        this.i_nodeId = i_nodeId;
    }

    /**
     * @return the to_time
     */
    public Integer getTo_time() {
        return to_time;
    }

    /**
     * @param to_time the to_time to set
     */
    public void setTo_time(Integer to_time) {
        this.to_time = to_time;
    }

    /**
     * @return the timezone
     */
    public String getTimezone() {
        return timezone;
    }

    /**
     * @param timezone the timezone to set
     */
    public void setTimezone(String timezone) {
        this.timezone = timezone;
    }

    /**
     * @return the v_graphs
     */
    public ArrayList<MuninGraph> getV_graphs() {
        return v_graphs;
    }

    /**
     * @param v_graphs the v_graphs to set
     */
    public void setV_graphs(ArrayList<MuninGraph> v_graphs) {
        this.v_graphs = v_graphs;
    }

    /**
     * @return the from_time
     */
    public Integer getFrom_time() {
        return from_time;
    }

    /**
     * @param from_time the from_time to set
     */
    public void setFrom_time(Integer from_time) {
        this.from_time = from_time;
    }

    /**
     * @return the customId
     */
    public Integer getCustomId() {
        return customId;
    }

    /**
     * @param customId the customId to set
     */
    public void setCustomId(Integer customId) {
        this.customId = customId;
    }

    /**
     * @return the user_id
     */
    public Integer getUser_id() {
        return user_id;
    }

    /**
     * @param user_id the user_id to set
     */
    public void setUser_id(Integer user_id) {
        this.user_id = user_id;
    }

    /**
     * @return the query_interval
     */
    public Integer getQuery_interval() {
        return query_interval;
    }

    /**
     * @param query_interval the query_interval to set
     */
    public void setQuery_interval(Integer query_interval) {
        this.query_interval = query_interval;
    }

    /**
     * @return the csMuninSocket
     */
    public Socket getCsMuninSocket() {
        return csMuninSocket;
    }

    /**
     * @param csMuninSocket the csMuninSocket to set
     */
    public void setCsMuninSocket(Socket csMuninSocket) {
        this.csMuninSocket = csMuninSocket;
    }

    /**
     * @return the crontab
     */
    public String getCrontab() {
        return crontab;
    }

    /**
     * @param crontab the crontab to set
     */
    public void setCrontab(String crontab) {
        this.crontab = crontab;
    }

    /**
     * @return the str_LineMode
     */
    public String getStr_LineMode() {
        return str_LineMode;
    }

    /**
     * @param str_LineMode the str_LineMode to set
     */
    public void setStr_LineMode(String str_LineMode) {
        this.str_LineMode = str_LineMode;
    }
}
 public static Logger logger     = Logger.getRootLogger(); public static Scheduler sched; public static MuninPlugin getMuninPluginForCustomJobFromDb(Integer p_id)
{
    MuninPlugin retval = new MuninPlugin();
    try
    {
        Connection conn = connectToDatabase(p);
        java.sql.Statement stmt = conn.createStatement();  
        ResultSet rs = stmt.executeQuery("SELECT plugins_custom_interval.*,plugins_custom_interval.query_interval AS second_interval , nodes.*, nodes.id AS nodeid, nodes.query_interval AS node_query_interval FROM  `plugins_custom_interval` LEFT JOIN nodes ON plugins_custom_interval.node_id = nodes.id WHERE plugins_custom_interval.id = "+p_id); 
        while(rs.next())
        {
            MuninNode l_node = getMuninNode(rs.getInt("nodeid"));
            if(l_node == null)
            {
                logger.error("getMuninPluginFromCustomInterval: cannot find MuninNode with id " + rs.getInt("nodeid") + " for custom interval: " + p_id);
                return null;
            }
            retval.set_IntervalIsSeconds(true);
            retval.set_NodeId(l_node.getNode_id());
            retval.setTo_time(rs.getInt("to_time"));
            retval.setFrom_time(rs.getInt("from_time"));
            retval.setTimezone(rs.getString("timezone"));
            String str_PluginName = rs.getString("pluginname").trim();
            retval.setUser_id(l_node.getUser_id());
            retval.setQuery_interval(rs.getInt("second_interval"));
            retval.setCrontab(rs.getString("crontab"));
            retval.setCustomId(p_id);
            // find plugin for custom interval and copy graphs and plugin informations
            Iterator it = l_node.getPluginList().iterator();
            while(it.hasNext())
            {
                MuninPlugin l_mp = (MuninPlugin) it.next();
                if(l_mp.getPluginName().equals(str_PluginName))
                {
                    retval.setPluginInfo(l_mp.getPluginInfo());
                    retval.setPluginLabel((l_mp.getPluginLabel()));
                    retval.setPluginName(l_mp.getPluginName());
                    retval.setPluginTitle(l_mp.getPluginTitle());
                    retval.setStr_PluginCategory(l_mp.getStr_PluginCategory());
                        
                    // copy graph base informations
                    Iterator git = l_mp.getGraphs().iterator();
                    while(git.hasNext())
                    {
                        MuninGraph old_mg = (MuninGraph) git.next();
                        MuninGraph new_mg = new MuninGraph();
                        new_mg.setGraphDraw(old_mg.getGraphDraw());
                        new_mg.setGraphInfo(old_mg.getGraphInfo());
                        new_mg.setGraphLabel(old_mg.getGraphLabel());
                        new_mg.setGraphName(old_mg.getGraphName());
                        new_mg.setGraphType(old_mg.getGraphType());
                        new_mg.setNegative(old_mg.isNegative());
                        new_mg.setQueryInterval(rs.getInt("second_interval"));
                        new_mg.setIntervalIsSeconds(true);
                        retval.addGraph(new_mg);
                        logger.info("getMuninPluginFromCustomInterval: added graph " + new_mg.getGraphName() + " for custom interval: " + p_id);
                    }
                }
            }
           return retval;
        }
            
    } catch (Exception ex)
    {
        logger.error("Error in getMuninPluginFromCustomInterval: " + ex.getLocalizedMessage());
        ex.printStackTrace();
        retval = null;
    }
    return retval;
} public static ServiceCheck getServiceCheckFromDatabase(Integer cid)
{
    ServiceCheck sc = null;
    try
    {
        Connection conn = connectToDatabase(p);
        java.sql.Statement stmt = conn.createStatement();
        ResultSet rs = stmt.executeQuery("SELECT * FROM service_checks WHERE id = " + cid);

        while(rs.next())
        {
            Gson gson = new Gson();
            sc = gson.fromJson(rs.getString("json"), ServiceCheck.class);
            sc.setCid(rs.getInt("id"));
            sc.setUser_id(rs.getInt("user_id"));
            v_serviceChecks.add(sc);
            logger.info("* " + sc.getCheckname() + " Service Check added from database");                
        }   
        conn.close();
    } catch (Exception ex)
    {
        logger.error("getServiceCheckFromDatabase Error: " + ex.getLocalizedMessage());
        ex.printStackTrace();
        return null;
    }        
    return sc;
} public static long getStampFromTimeAndZone(String time, String zone) {
    long retval = 0;
    ///usr/local/bin/php /opt/pcvd/getTime.php
    List<String> commands = new ArrayList<String>();
    commands.add("/usr/bin/php");
    commands.add("/opt/muninmx/getTime.php");
    commands.add(zone);
    commands.add(time);
    try {
        ProcessBuilder pb = new ProcessBuilder(commands);
        Process p = pb.start();
        InputStream is = p.getInputStream();
        BufferedReader reader = new BufferedReader(new InputStreamReader(is));
        // print output
        String str_output = null;
        String str_parse = null;
        while ((str_output = reader.readLine()) != null) {
            //logger.info(str_output);
            str_parse = str_output;
        }
        com.clavain.muninmxcd.logger.info("getTime.php returned: " + str_parse);
        retval = Long.parseLong(str_parse);
    } catch (Exception ex) {
        com.clavain.muninmxcd.logger.error("Error in getStampFromTimeAndZone:" + ex.getLocalizedMessage());
    }
    return retval;
} public static MuninPlugin getMuninPluginForCustomJob(Integer customId) {
    Iterator it = com.clavain.muninmxcd.v_cinterval_plugins.iterator();
    while (it.hasNext()) {
        MuninPlugin l_mp = (MuninPlugin) it.next();
        if (l_mp.getCustomId().equals(customId)) {
            return l_mp;
        }
    }
    com.clavain.muninmxcd.logger.error("getMuninPluginForCustomJob: Cant find plugin for custom id: " + customId);
    return null;
}
import com.clavain.jobs.CheckJob;
import com.clavain.jobs.CustomJob;
import com.clavain.jobs.MuninJob;
import com.clavain.json.ScheduledJob;
import com.clavain.json.ServiceCheck;
import com.clavain.munin.MuninNode;
import com.clavain.munin.MuninPlugin;
import static org.quartz.SimpleScheduleBuilder.simpleSchedule;
import org.quartz.Trigger;
import static com.clavain.muninmxcd.logger;
import static com.clavain.muninmxcd.sched;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.quartz.impl.matchers.GroupMatcher;
import org.quartz.JobDetail;
import org.quartz.SchedulerException;
import static org.quartz.JobBuilder.*;
import org.quartz.JobKey;
import static org.quartz.TriggerBuilder.newTrigger;
import static org.quartz.impl.matchers.GroupMatcher.groupEquals;
import static com.clavain.utils.Database.getMuninPluginForCustomJobFromDb;
import static com.clavain.utils.Database.getServiceCheckFromDatabase;
import static com.clavain.utils.Generic.getStampFromTimeAndZone;
import static com.clavain.utils.Generic.getMuninPluginForCustomJob;
import java.text.SimpleDateFormat;
import java.util.TimeZone;
import org.quartz.CronScheduleBuilder;
/*
 * MuninMX
 * Written by Enrico Kern, kern@clavain.com
 * www.clavain.com
 * 
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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.
 */
package com.clavain.utils;



/**
 *
 * @author enricokern
 */
public class Quartz {
    
    public static boolean scheduleServiceCheck(Integer p_cid)
    {
        ServiceCheck sc = getServiceCheckFromDatabase(p_cid);
        if(sc == null)
        {
            return false;
        }
        return scheduleServiceCheck(sc);
    }
    
    // schedule a new check
    public static boolean scheduleServiceCheck(ServiceCheck p_sc)
    {
        boolean l_retVal = false;   
        Trigger trigger = newTrigger().withIdentity("checktrigger", p_sc.getUser_id().toString() + p_sc.getCid() + System.currentTimeMillis()).startNow().withSchedule(simpleSchedule().withIntervalInMinutes(p_sc.getInterval()) .repeatForever().withMisfireHandlingInstructionFireNow()).build(); 
        JobDetail job = newJob(CheckJob.class).withIdentity(p_sc.getCid().toString(), p_sc.getUser_id().toString()).usingJobData("cid", p_sc.getCid()).build();
        try
        {
            com.clavain.muninmxcd.sched_checks.scheduleJob(job, trigger);
            l_retVal = true;
        } catch (Exception ex)
        {
            com.clavain.muninmxcd.logger.error(ex);
        }
        return l_retVal;
    }    
    
    // delete a job
    public static boolean unscheduleServiceCheck(String p_cid, String p_uid)
    {
        boolean l_retVal = false;
        JobKey jk = new JobKey(p_cid.toString(),p_uid.toString());
        try {
            com.clavain.muninmxcd.sched_checks.deleteJob(jk);
            l_retVal = true;
        } catch (SchedulerException ex) {
            com.clavain.muninmxcd.logger.error(ex.getLocalizedMessage());
        }
        
        return l_retVal;
    }    
    
    public static boolean isServiceCheckScheduled(int p_cid)
    {
        boolean retval = false;
        String match = p_cid+"";
        
        for(ScheduledJob sj : getScheduledServiceChecks())
        {
            if(sj.getJobName().equals(match))
            {
                return true;
            }
        }
        
        return retval;
    }  
    
    public static ArrayList<ScheduledJob> getScheduledServiceChecks()
    {
        ArrayList<ScheduledJob> retval = new ArrayList<>();
        try {
            for (String groupName : com.clavain.muninmxcd.sched_checks.getJobGroupNames()) {

                for (JobKey jobKey : com.clavain.muninmxcd.sched_checks.getJobKeys(GroupMatcher.jobGroupEquals(groupName))) {

                     String jobName = jobKey.getName();
                     String jobGroup = jobKey.getGroup();

                     //get job's trigger
                     List<Trigger> triggers = (List<Trigger>) com.clavain.muninmxcd.sched_checks.getTriggersOfJob(jobKey);
                     Date nextFireTime = triggers.get(0).getNextFireTime(); 
                     ScheduledJob sj = new ScheduledJob();
                     sj.setJobName(jobName);
                     sj.setGroupName(jobGroup);
                     sj.setNextFireTime(nextFireTime.toString());
                     retval.add(sj);
                     }

               }
        } catch (SchedulerException ex) {
            com.clavain.muninmxcd.logger.error(ex.getLocalizedMessage());
            ex.printStackTrace();
        }
        return retval;
    }        
    
    // schedule a new check
    public static boolean scheduleJob(MuninNode mn)
    {
        boolean l_retVal = false;   
        String uid = mn.getUser_id().toString();
        Trigger trigger = newTrigger().withIdentity("trigger", uid + mn.getNode_id() + System.currentTimeMillis()).startNow().withSchedule(simpleSchedule().withIntervalInMinutes(mn.getQueryInterval()) .repeatForever().withMisfireHandlingInstructionFireNow()).build(); 
        JobDetail job = newJob(MuninJob.class).withIdentity(mn.getNode_id().toString(), mn.getUser_id().toString()).usingJobData("nodeId", mn.getNode_id()).build();