/******************************************************************************* * Created by Carlos Yaconi * Copyright 2015 Prey Inc. All rights reserved. * License: GPLv3 * Full license at "/LICENSE" ******************************************************************************/ package com.prey.actions.observer; import java.util.ArrayList; import java.util.Collections; import java.util.Enumeration; import java.util.Hashtable; import java.util.List; import java.util.Random; import android.content.Context; import com.prey.PreyLogger; import com.prey.actions.PreyAction; import com.prey.actions.PreyExecutionWaitNotify; import com.prey.actions.compare.CompareAction; /** * This class is a representation of a related actions needed to be run - and * sent as report - as a whole. * */ public class JobsGroup { private Hashtable<Long,ActionJob> actionModules; private Hashtable<Long,ActionJob> reportModules; private List<ActionJob> modules; private long id; private long creationTime; private boolean running; private boolean finished; private ArrayList<ActionResult> syncResults; // Only gets track of report modules jobs, because them could take a while to finish, // and maybe we need to kill them before. private Hashtable<Long,Thread> runningJobs; private JobsQueue queue; private Context ctx; // public JobsGroup() { // this.initialize(); // } public JobsGroup(ArrayList<PreyAction> actions, Context ctx) { this.initialize(ctx); for (PreyAction preyAction : actions) { this.addJobToGroup(new ActionJob(preyAction, this, ctx)); } } private void initialize(Context ctx) { Random rnd = new Random(); this.id = rnd.nextLong(); this.ctx = ctx; this.actionModules = new Hashtable<Long,ActionJob>(); this.reportModules = new Hashtable<Long,ActionJob>(); this.creationTime = System.currentTimeMillis(); this.syncResults = new ArrayList<ActionResult>(); this.runningJobs = new Hashtable<Long,Thread>(); this.modules = new ArrayList<ActionJob>(); } public void addJobToGroup(ActionJob job) { if (job.isReportModuleJob()) this.reportModules.put(Long.valueOf(job.getId()), job); else this.actionModules.put(Long.valueOf(job.getId()), job); this.modules.add(job); } public void run(JobsQueue queue, boolean isMissing) { this.queue = queue; //Enumeration<Long> actionModulesJobId = this.actionModules.keys(); //Long jobId; PreyExecutionWaitNotify waitNotifyPriority = new PreyExecutionWaitNotify(); Collections.sort(this.modules, new CompareAction()); Long syncJobId; for (ActionJob actionJob : this.modules) { //actions if (!actionJob.isReportModuleJob()){ if (actionJob.getAction().getPriority()>0){ syncJobId=actionJob.getId(); Thread actionJobRun = new Thread(new PreyActionRunner(actionJob, ctx,waitNotifyPriority), syncJobId.toString()); actionJobRun.start(); }else{ new Thread(actionJob).start(); } }else{ //reports if (isMissing){ syncJobId=actionJob.getId(); Thread actionJobRun = new Thread(new PreyActionRunner(actionJob, ctx,waitNotifyPriority), syncJobId.toString()); actionJobRun.start(); this.runningJobs.put(syncJobId, actionJobRun); } } } waitNotifyPriority.doNotify(); /* while (actionModulesJobId.hasMoreElements()) { jobId = (Long) actionModulesJobId.nextElement(); new Thread((ActionJob) this.actionModules.get(jobId)).start(); } if (isMissing){ Enumeration<Long> reportModulesJobId = this.reportModules.keys(); Long syncJobId; while (reportModulesJobId.hasMoreElements()) { syncJobId = (Long) reportModulesJobId.nextElement(); Thread actionJobRun = new Thread((ActionJob) this.reportModules.get(syncJobId), syncJobId.toString()); actionJobRun.start(); // Only syncjobs are added to the running jobs list this.runningJobs.put(syncJobId, actionJobRun); } }*/ } public void jobFinished(ActionJob job) { this.syncResults.add(job.getResult()); this.runningJobs.remove(Long.valueOf(job.getId())); if (this.runningJobs.isEmpty()) this.queue.groupFinished(this, this.ctx); } public boolean hasReportModules(){ return !this.reportModules.isEmpty(); } public long getId() { return id; } public long getCreationTime() { return creationTime; } public boolean isRunning() { return running; } public boolean isFinished() { return finished; } public ArrayList<ActionResult> getResults() { return this.syncResults; } public void destroy() { Enumeration<Long> runningJobsId = this.runningJobs.keys(); Long jobId; while (runningJobsId.hasMoreElements()) { jobId = (Long) runningJobsId.nextElement(); Thread runningJob = (Thread) this.runningJobs.get(jobId); if (runningJob.isAlive()) runningJob.interrupt(); } } class PreyActionRunner implements Runnable { private ActionJob actionJob; private Context ctx; private PreyExecutionWaitNotify waitNotifyPriority ; public PreyActionRunner(ActionJob actionJob, Context ctx,PreyExecutionWaitNotify waitNotifyPriority ){ this.actionJob=actionJob; this.ctx=ctx; this.waitNotifyPriority=waitNotifyPriority; } public void run() { try { PreyAction action=actionJob.getAction(); PreyLogger.i(action.getClass().getName()+" Esperando el action:"); waitNotifyPriority.doWait(); PreyLogger.i(action.getClass().getName()+" Ejecutando el action:"); action.execute(actionJob, this.ctx); PreyLogger.i(action.getClass().getName()+" termino el execute el action:"); waitNotifyPriority.doNotify(); } catch (Exception e) { PreyLogger.e("Error:"+e.getMessage(),e); } } } }