diff --git a/.gitignore b/.gitignore index 9ce2b40..2a5da2a 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,6 @@ obj/ bin/ *.user -*.suo \ No newline at end of file +*.suo +*.exe +*.msi \ No newline at end of file diff --git a/ClickForensics.Quartz.Manager/AddJobForm.cs b/ClickForensics.Quartz.Manager/AddJobForm.cs index ff52468..e93ec8d 100644 --- a/ClickForensics.Quartz.Manager/AddJobForm.cs +++ b/ClickForensics.Quartz.Manager/AddJobForm.cs @@ -8,169 +8,171 @@ using System.Text; using System.Windows.Forms; using Quartz; using System.Reflection; +using Quartz.Impl; +using Quartz.Impl.Triggers; using Quartz.Job; using System.IO; namespace ClickForensics.Quartz.Manager { - public partial class AddJobForm : Form - { - public AddJobForm() - { - InitializeComponent(); - loadJobAssemblies(); - cboTriggerType.Items.Add("Cron"); - cboTriggerType.SelectedItem = "Cron"; - if (cboJobType.SelectedText == "NativeJob") - { - jobDataListView.Items.Add(new ListViewItem(new string[] { "consumeStreams", "true" })); - jobDataListView.Items.Add(new ListViewItem(new string[] { "waitForProcess", "true" })); - txtKey.Text = "command"; - } - } - private void loadJobAssemblies() - { - FileStream stream = File.OpenRead("JobAssemblies.txt"); - StreamReader reader = new StreamReader(stream); - string line; - SortedList jobTypes = new SortedList(); - while ((line = reader.ReadLine()) != null) - { - Assembly assembly = Assembly.LoadFile(Environment.CurrentDirectory + "\\" + line); - foreach (Type type in assembly.GetTypes()) - { - if (typeof(IJob).IsAssignableFrom(type) && type.IsClass) - { - jobTypes.Add(type.FullName, assembly.GetName().Name); - } - } - } - foreach (var item in jobTypes) - { - cboJobType.Items.Add(new JobType() { AssemblyName = item.Value, FullName = item.Key }); - } - //cboJobType.Items.AddRange(jobTypes.Values.ToArray()); - - } - - public AddJobForm(TriggerNode node) - : this() - { - setTriggerData((CronTrigger)node.Trigger); - setJobData(((JobNode)node.Parent.Parent).Detail); - } - - private void setTriggerData(CronTrigger trigger) - { - setTriggerType(); - txtCronExpression.Text = trigger.CronExpressionString; - txtTriggerDescription.Text = trigger.Description; - txtTriggerGroup.Text = trigger.Group; - txtTriggerName.Text = trigger.Name; - } - - private void setJobData(JobDetail detail) - { - setJobType(detail); - txtJobDescription.Text = detail.Description; - txtJobGroup.Text = detail.Group; - txtJobName.Text = detail.Name; - setJobDataMap(detail); - } - - private void setJobDataMap(JobDetail detail) - { - jobDataListView.Items.Clear(); - foreach (var item in detail.JobDataMap.GetKeys()) - { - jobDataListView.Items.Add(new ListViewItem(new string[] { item, detail.JobDataMap.Get(item).ToString() })); - } - } - - private void setJobType(JobDetail detail) - { - cboJobType.SelectedItem = detail.JobType.FullName; - - } - - private void setTriggerType() - { - //nothing to do right now - } - public JobDetail JobDetail { get; set; } - public Trigger Trigger { get; set; } - private void btnCancel_Click(object sender, EventArgs e) - { - this.Close(); - } - - private void btnAdd_Click(object sender, EventArgs e) - { - JobDetail = getJobDetail(); - Trigger = getTrigger(); - Trigger.JobGroup = JobDetail.Group; - Trigger.JobName = JobDetail.Name; - this.Close(); - } - - private JobDetail getJobDetail() - { - JobDetail detail = new JobDetail(); - detail.Description = txtJobDescription.Text; - detail.Group = txtJobGroup.Text; - detail.JobDataMap = getJobDataMap(); - detail.JobType = getJobType(); - detail.Name = txtJobName.Text; - return detail; - } - - private Trigger getTrigger() - { - Trigger trigger; - if (cboTriggerType.SelectedText == "Simple") - { - trigger = new SimpleTrigger(); - } - else - { - trigger = new CronTrigger(); - ((CronTrigger)trigger).CronExpressionString = txtCronExpression.Text; - } - trigger.Description = txtTriggerDescription.Text; - trigger.Group = txtTriggerGroup.Text; - trigger.Name = txtTriggerName.Text; - return trigger; - } - - private Type getJobType() - { - JobType type = (JobType)cboJobType.SelectedItem; - return Type.GetType(type.FullName + "," + type.AssemblyName, true); - } - - private JobDataMap getJobDataMap() - { - JobDataMap map = new JobDataMap(); - foreach (ListViewItem item in jobDataListView.Items) - { - map.Add(item.SubItems[0].Text, item.SubItems[1].Text); - } - - return map; - } - - private void btnAddKeyValue_Click(object sender, EventArgs e) - { - ListViewItem item = new ListViewItem(new string[] { txtKey.Text, txtValue.Text }); - jobDataListView.Items.Add(item); - } - - private void btnDelete_Click(object sender, EventArgs e) - { - foreach (ListViewItem item in jobDataListView.SelectedItems) - { - jobDataListView.Items.Remove(item); - } - } - } + public partial class AddJobForm : Form + { + public AddJobForm() + { + InitializeComponent(); + loadJobAssemblies(); + cboTriggerType.Items.Add("Cron"); + cboTriggerType.SelectedItem = "Cron"; + if (cboJobType.SelectedText == "NativeJob") + { + jobDataListView.Items.Add(new ListViewItem(new string[] { "consumeStreams", "true" })); + jobDataListView.Items.Add(new ListViewItem(new string[] { "waitForProcess", "true" })); + txtKey.Text = "command"; + } + } + private void loadJobAssemblies() + { + FileStream stream = File.OpenRead("JobAssemblies.txt"); + StreamReader reader = new StreamReader(stream); + string line; + SortedList jobTypes = new SortedList(); + while ((line = reader.ReadLine()) != null) + { + Assembly assembly = Assembly.LoadFile(Environment.CurrentDirectory + "\\" + line); + foreach (Type type in assembly.GetTypes()) + { + if (typeof(IJob).IsAssignableFrom(type) && type.IsClass) + { + jobTypes.Add(type.FullName, assembly.GetName().Name); + } + } + } + foreach (var item in jobTypes) + { + cboJobType.Items.Add(new JobType() { AssemblyName = item.Value, FullName = item.Key }); + } + //cboJobType.Items.AddRange(jobTypes.Values.ToArray()); + + } + + public AddJobForm(TriggerNode node) + : this() + { + setTriggerData((CronTriggerImpl)node.Trigger); + setJobData(((JobNode)node.Parent.Parent).Detail); + } + + private void setTriggerData(CronTriggerImpl trigger) + { + setTriggerType(); + txtCronExpression.Text = trigger.CronExpressionString; + txtTriggerDescription.Text = trigger.Description; + txtTriggerGroup.Text = trigger.Name.Group; + txtTriggerName.Text = trigger.Name; + } + + private void setJobData(IJobDetail detail) + { + setJobType(detail); + txtJobDescription.Text = detail.Description; + txtJobGroup.Text = detail.Key.Group; + txtJobName.Text = detail.Key.Name; + setJobDataMap(detail); + } + + private void setJobDataMap(IJobDetail detail) + { + jobDataListView.Items.Clear(); + foreach (var item in detail.JobDataMap.GetKeys()) + { + jobDataListView.Items.Add(new ListViewItem(new string[] { item, detail.JobDataMap.Get(item).ToString() })); + } + } + + private void setJobType(IJobDetail detail) + { + cboJobType.SelectedItem = detail.JobType.FullName; + + } + + private void setTriggerType() + { + //nothing to do right now + } + public IJobDetail JobDetail { get; set; } + public AbstractTrigger Trigger { get; set; } + private void btnCancel_Click(object sender, EventArgs e) + { + this.Close(); + } + + private void btnAdd_Click(object sender, EventArgs e) + { + JobDetail = getJobDetail(); + AbstractTrigger trigger = getTrigger(); + Trigger.JobGroup = JobDetail.Key.Group; + Trigger.JobName = JobDetail.Key.Name; + this.Close(); + } + + private IJobDetail getJobDetail() + { + IJobDetail detail = new IJobDetail(); + detail.Description = txtJobDescription.Text; + detail.Group = txtJobGroup.Text; + detail.JobDataMap = getJobDataMap(); + detail.JobType = getJobType(); + detail.Name = txtJobName.Text; + return detail; + } + + private AbstractTrigger getTrigger() + { + AbstractTrigger trigger; + if (cboTriggerType.SelectedText == "Simple") + { + trigger = new SimpleTrigger(); + } + else + { + trigger = new CronTrigger(); + ((CronTrigger)trigger).CronExpressionString = txtCronExpression.Text; + } + trigger.Description = txtTriggerDescription.Text; + trigger.Group = txtTriggerGroup.Text; + trigger.Name = txtTriggerName.Text; + return trigger; + } + + private Type getJobType() + { + JobType type = (JobType)cboJobType.SelectedItem; + return Type.GetType(type.FullName + "," + type.AssemblyName, true); + } + + private JobDataMap getJobDataMap() + { + JobDataMap map = new JobDataMap(); + foreach (ListViewItem item in jobDataListView.Items) + { + map.Add(item.SubItems[0].Text, item.SubItems[1].Text); + } + + return map; + } + + private void btnAddKeyValue_Click(object sender, EventArgs e) + { + ListViewItem item = new ListViewItem(new string[] { txtKey.Text, txtValue.Text }); + jobDataListView.Items.Add(item); + } + + private void btnDelete_Click(object sender, EventArgs e) + { + foreach (ListViewItem item in jobDataListView.SelectedItems) + { + jobDataListView.Items.Remove(item); + } + } + } } diff --git a/ClickForensics.Quartz.Manager/CronTriggerDisplay.cs b/ClickForensics.Quartz.Manager/CronTriggerDisplay.cs index 62f31db..4980bd7 100644 --- a/ClickForensics.Quartz.Manager/CronTriggerDisplay.cs +++ b/ClickForensics.Quartz.Manager/CronTriggerDisplay.cs @@ -7,48 +7,49 @@ using System.Linq; using System.Text; using System.Windows.Forms; using Quartz; +using Quartz.Impl.Triggers; namespace ClickForensics.Quartz.Manager { - public partial class CronTriggerDisplay : UserControl - { - public CronTriggerDisplay() - { - InitializeComponent(); - this.Load += new EventHandler(CronTriggerDisplay_Load); - } + public partial class CronTriggerDisplay : UserControl + { + public CronTriggerDisplay() + { + InitializeComponent(); + this.Load += new EventHandler(CronTriggerDisplay_Load); + } - void CronTriggerDisplay_Load(object sender, EventArgs e) - { - txtCronExpression.Text = _trigger.CronExpressionString; - lblDescription.Text = _trigger.Description; - lblGroup.Text = _trigger.Group; - lblName.Text = _trigger.Name; - if (_trigger.GetNextFireTimeUtc().HasValue) - { - lblNextFireTime.Text = _trigger.GetNextFireTimeUtc().Value.ToLocalTime().ToString(); - } - else - { - lblNextFireTime.Text = "Unknown"; - } + void CronTriggerDisplay_Load(object sender, EventArgs e) + { + txtCronExpression.Text = _trigger.CronExpressionString; + lblDescription.Text = _trigger.Description; + lblGroup.Text = _trigger.Group; + lblName.Text = _trigger.Name; + if (_trigger.GetNextFireTimeUtc().HasValue) + { + lblNextFireTime.Text = _trigger.GetNextFireTimeUtc().Value.ToLocalTime().ToString(); + } + else + { + lblNextFireTime.Text = "Unknown"; + } - if (_trigger.GetPreviousFireTimeUtc().HasValue) - { - lblPreviousFireTime.Text = _trigger.GetPreviousFireTimeUtc().Value.ToLocalTime().ToString(); - } - else - { - lblPreviousFireTime.Text = "Unknown"; - } - } - public CronTriggerDisplay(CronTrigger trigger) - : this() - { - _trigger = trigger; + if (_trigger.GetPreviousFireTimeUtc().HasValue) + { + lblPreviousFireTime.Text = _trigger.GetPreviousFireTimeUtc().Value.ToLocalTime().ToString(); + } + else + { + lblPreviousFireTime.Text = "Unknown"; + } + } + public CronTriggerDisplay(CronTriggerImpl trigger) + : this() + { + _trigger = trigger; - } + } - private CronTrigger _trigger; - } + private CronTriggerImpl _trigger; + } } diff --git a/ClickForensics.Quartz.Manager/JobNode.cs b/ClickForensics.Quartz.Manager/JobNode.cs index 4b497ae..ded18fb 100644 --- a/ClickForensics.Quartz.Manager/JobNode.cs +++ b/ClickForensics.Quartz.Manager/JobNode.cs @@ -4,18 +4,19 @@ using System.Linq; using System.Text; using System.Windows.Forms; using Quartz; +using Quartz.Impl; namespace ClickForensics.Quartz.Manager { - public class JobNode : TreeNode - { - public JobNode(JobDetail jobDetail) - : base() - { - this.Text = jobDetail.Name; - Detail = jobDetail; - } - public JobDetail Detail { get; private set; } + public class JobNode : TreeNode + { + public JobNode(IJobDetail jobDetail) + : base() + { + this.Text = jobDetail.Key.Name; + Detail = jobDetail; + } + public IJobDetail Detail { get; private set; } - } + } } diff --git a/ClickForensics.Quartz.Manager/MainForm.cs b/ClickForensics.Quartz.Manager/MainForm.cs index 42682c9..9c27476 100644 --- a/ClickForensics.Quartz.Manager/MainForm.cs +++ b/ClickForensics.Quartz.Manager/MainForm.cs @@ -11,370 +11,373 @@ using Quartz.Collection; using System.Net.Sockets; //using ClickForensics.Quartz.Jobs; using System.IO; +using Quartz.Impl; +using Quartz.Impl.Triggers; namespace ClickForensics.Quartz.Manager { - public partial class MainForm : Form - { - public MainForm() - { - InitializeComponent(); - jobGroupsTreeView.AfterSelect += new TreeViewEventHandler(jobGroupsTreeView_AfterSelect); - ctxScheduler.Opening += new CancelEventHandler(ctxScheduler_Opening); - jobGroupsTreeView.MouseDown += new MouseEventHandler(jobGroupsTreeView_MouseDown); - - } - - void ctxScheduler_Opening(object sender, CancelEventArgs e) - { - - } - - void jobGroupsTreeView_AfterSelect(object sender, TreeViewEventArgs e) - { - jobDetailsToggle(false); - if (e.Node is TriggerNode || e.Node is JobNode) - { - btnDeleteJob.Enabled = true; - } - else - { - btnDeleteJob.Enabled = false; - } - - if (e.Node is JobNode) - { - btnRunJobNow.Enabled = true; - pnlDetails.Controls.Add(new NativeJobDetailDisplay(((JobNode)e.Node).Detail)); - jobDetailsToggle(true); - } - else - { - btnRunJobNow.Enabled = false; - - } - if (e.Node is TriggerNode) - { - btnPause.Enabled = true; - setPauseButtonText(); - if (((TriggerNode)e.Node).Trigger is CronTrigger) - { - pnlDetails.Controls.Add(new CronTriggerDisplay((CronTrigger)((TriggerNode)e.Node).Trigger)); - jobDetailsToggle(true); - } - btnEdit.Enabled = true; - } - else - { - btnEdit.Enabled = false; - btnPause.Enabled = false; - } - } - - private void setPauseButtonText() - { - TriggerNode node = (TriggerNode)jobGroupsTreeView.SelectedNode; - string name = node.Trigger.Name; - string group = node.Trigger.Group; - if (Scheduler.GetScheduler().GetTriggerState(name, group) == TriggerState.Paused) - { - btnPause.Text = "Resume"; - } - else - { - btnPause.Text = "Pause"; - } - } - - private void connectToolStripMenuItem_Click(object sender, EventArgs e) - { - using (ServerConnectForm form = new ServerConnectForm()) - { - form.ShowDialog(); - try - { - Scheduler = new QuartzScheduler(form.Server, form.Port, form.Scheduler); - serverConnectStatusLabel.Text = string.Format("Connected to {0}", Scheduler.Address); - connectToolStripMenuItem.Enabled = false; - jobsToolStripMenuItem.Enabled = true; - loadJobGroups(); - updateRunningJobs(); - } - catch (SocketException ex) - { - ErrorDialog dialog = new ErrorDialog(); - dialog.Message = string.Format("Unable to connect to scheduler {0} on {1}:{2}", form.Scheduler, form.Server, form.Port); - dialog.Description = ex.Message; - dialog.ShowDialog(); - } - form.Close(); - } - //loadGlobalTriggers(); - } - - //private void loadGlobalTriggers() - //{ - // foreach (IJobListener jobListener in Scheduler.GetScheduler().GetJobDetail(null,null)..GlobalJobListeners) - // { - // globalTriggersListView.Items.Add(jobListener.Name); - // } - //} - - private void loadJobGroups() - { - - try - { - this.Cursor = Cursors.WaitCursor; - - jobDetailsToggle(false); - jobGroupsTreeView.Nodes.Clear(); - SchedulerNode schedulerNode = new SchedulerNode(Scheduler); - schedulerNode.ContextMenuStrip = ctxScheduler; - jobGroupsTreeView.Nodes.Add(schedulerNode); - TreeNode jobGroupsNode = schedulerNode.Nodes.Add("Job Groups"); - string[] jobGroups = Scheduler.GetScheduler().JobGroupNames; - foreach (string jobGroup in jobGroups) - { - TreeNode jobGroupNode = jobGroupsNode.Nodes.Add(jobGroup); - TreeNode jobsNode = jobGroupNode.Nodes.Add("Jobs"); - addJobNodes(jobsNode); - } - - jobGroupsTreeView.Nodes[0].Expand(); - jobGroupsNode.Expand(); - - StripStatusLabel_Job_Groups.Text = DateTime.Now.ToString("yyyy.MM.dd HH:mm.ss"); - - } - finally - { - this.Cursor = Cursors.Default; - } - - - } - - private void jobDetailsToggle(bool isVisible) - { - if (isVisible == false) - { - pnlDetails.Controls.Clear(); - } - } - - void jobGroupsTreeView_MouseDown(object sender, MouseEventArgs e) - { - if (e.Button == MouseButtons.Right) - { - TreeNode node = jobGroupsTreeView.GetNodeAt(e.X, e.Y); - if (node != null) - { - jobGroupsTreeView.SelectedNode = node; - ctxScheduler.Show(jobGroupsTreeView, e.Location); - } - } - } - //private void loadJobs() - //{ - // foreach (TreeNode node in jobGroupsTreeView.Nodes) - // { - // addJobNodes(node); - // } - //} - - private void addJobNodes(TreeNode node) - { - string group = node.Parent.Text; - string[] jobs = Scheduler.GetScheduler().GetJobNames(group); - foreach (string jobName in jobs) - { - try - { - JobDetail detail = Scheduler.GetScheduler().GetJobDetail(jobName, group); - JobNode jobNode = new JobNode(detail); - node.Nodes.Add(jobNode); - addTriggerNodes(jobNode); - addListenerNodes(jobNode); - } - catch (Exception ex) - { - //TODO: Do something useful with this exception. Most likely cause is the client does not have a copy of a given dll and can't load the type. - } - } - } - - private void addListenerNodes(JobNode node) - { - string jobName = node.Text; - string jobGroupName = node.Parent.Text; - string[] listenerNames = node.Detail.JobListenerNames; - foreach (string listener in listenerNames) - { - node.Text = string.Format("JL {0}", listenerNames); - } - //ISet set = Scheduler.GetScheduler().JobListenerNames; - } - - private void addTriggerNodes(TreeNode treeNode) - { - Trigger[] triggers = Scheduler.GetScheduler().GetTriggersOfJob(treeNode.Text, treeNode.Parent.Parent.Text); - TreeNode triggersNode = treeNode.Nodes.Add("Triggers"); - foreach (Trigger trigger in triggers) - { - TriggerNode node = new TriggerNode(trigger); - triggersNode.Nodes.Add(node); - } - - } - private void updateRunningJobs() - { - try - { - this.Cursor = Cursors.WaitCursor; - - timer_Refresh_Running_Jobs.Stop(); - - listView_RunningJobs.Items.Clear(); - - DataTable table = Scheduler.GetRunningJobs(); - foreach (DataRow row in table.Rows) - { - //JobName JobDuration - ListViewItem item = new ListViewItem(new string[] { Convert.ToString(row["JobName"]), Convert.ToString(row["Runtime"]) }); - listView_RunningJobs.Items.Add(item); - } - StripStatusLabel_Jobs_Refresh_date.Text = DateTime.Now.ToString("yyyy.MM.dd HH:mm.ss"); - - - //reset the timer ( documentation not clear if .stop = restart @ 0 in timing, but changing the interval sure should do that. ) - int timer_was = timer_Refresh_Running_Jobs.Interval; - timer_Refresh_Running_Jobs.Interval = timer_was + 1; - timer_Refresh_Running_Jobs.Interval = timer_was; - - timer_Refresh_Running_Jobs.Start(); - } - finally - { - this.Cursor = Cursors.Default; - } - } - public QuartzScheduler Scheduler { get; set; } - - private void addGlobalListenerToolStripMenuItem_Click(object sender, EventArgs e) - { - AddListenerForm form = new AddListenerForm(); - form.ListenerInterface = typeof(IJobListener); - form.ShowDialog(); - JobDataMap map = new JobDataMap(); - map.Add("type", form.ListenerType); - //Scheduler.ScheduleOneTimeJob(typeof(AddJobListenerJob), map, 0); - loadJobGroups(); - } - - private void addJobListenerToolStripMenuItem_Click(object sender, EventArgs e) - { - TreeNode selectedNode = jobGroupsTreeView.SelectedNode; - if (selectedNode != null && selectedNode is JobNode) - { - AddListenerForm form = new AddListenerForm(); - form.ListenerInterface = typeof(IJobListener); - form.ShowDialog(); - //JobHistoryListener listener = new JobHistoryListener(); - //listener.Name = null; - //((JobNode)selectedNode).Detail.AddJobListener(); - } - } - - private void addJobToolStripMenuItem_Click(object sender, EventArgs e) - { - AddJobForm form = new AddJobForm(); - form.ShowDialog(); - if (form.JobDetail != null && form.Trigger != null) - { - Scheduler.GetScheduler().ScheduleJob(form.JobDetail, form.Trigger); - loadJobGroups(); - } - } - - private void btnRefreshRunningJobs_Click(object sender, EventArgs e) - { - updateRunningJobs(); - } - - private void btnRefreshJobGroups_Click(object sender, EventArgs e) - { - loadJobGroups(); - } - - private void btnRunJobNow_Click(object sender, EventArgs e) - { - JobNode node = (JobNode)jobGroupsTreeView.SelectedNode; - string job = node.Detail.Name; - string group = node.Detail.Group; - Scheduler.GetScheduler().TriggerJobWithVolatileTrigger(job, group); - } - - private void btnDeleteJob_Click(object sender, EventArgs e) - { - TreeNode selectedNode = jobGroupsTreeView.SelectedNode; - if (selectedNode is JobNode) - { - JobNode node = (JobNode)jobGroupsTreeView.SelectedNode; - string job = node.Detail.Name; - string group = node.Detail.Group; - Scheduler.GetScheduler().DeleteJob(job, group); - jobGroupsTreeView.SelectedNode.Remove(); - - } - if (selectedNode is TriggerNode) - { - Scheduler.GetScheduler().UnscheduleJob(((TriggerNode)selectedNode).Trigger.Name, ((TriggerNode)selectedNode).Trigger.Group); - } - - //loadJobGroups(); - } - - private void btnPause_Click(object sender, EventArgs e) - { - TriggerNode node = (TriggerNode)jobGroupsTreeView.SelectedNode; - string name = node.Trigger.Name; - string group = node.Trigger.Group; - if (Scheduler.GetScheduler().GetTriggerState(name, group) == TriggerState.Paused) - { - Scheduler.GetScheduler().ResumeTrigger(name, group); - } - else - { - Scheduler.GetScheduler().PauseTrigger(name, group); - } - setPauseButtonText(); - } - - private void btnEdit_Click(object sender, EventArgs e) - { - TriggerNode node = (TriggerNode)jobGroupsTreeView.SelectedNode; - AddJobForm form = new AddJobForm(node); - form.ShowDialog(); - if (form.JobDetail != null && form.Trigger != null) - { - Scheduler.GetScheduler().RescheduleJob(node.Trigger.Name, node.Trigger.Group, form.Trigger); - loadJobGroups(); - } - } - - private void backupToolStripMenuItem_Click(object sender, EventArgs e) - { - QuartzScheduler scheduler = ((SchedulerNode)((TreeView)((ContextMenuStrip)((ToolStripMenuItem)sender).Owner).SourceControl).SelectedNode).Scheduler; - FileDialog dialog = new SaveFileDialog(); - dialog.ShowDialog(); - FileInfo file = new FileInfo(dialog.FileName); - scheduler.BackupToFile(file); - } - - private void timer_Refresh_Running_Jobs_Tick(object sender, EventArgs e) - { - updateRunningJobs(); - } - } + public partial class MainForm : Form + { + public MainForm() + { + InitializeComponent(); + jobGroupsTreeView.AfterSelect += new TreeViewEventHandler(jobGroupsTreeView_AfterSelect); + ctxScheduler.Opening += new CancelEventHandler(ctxScheduler_Opening); + jobGroupsTreeView.MouseDown += new MouseEventHandler(jobGroupsTreeView_MouseDown); + + } + + void ctxScheduler_Opening(object sender, CancelEventArgs e) + { + + } + + void jobGroupsTreeView_AfterSelect(object sender, TreeViewEventArgs e) + { + jobDetailsToggle(false); + if (e.Node is TriggerNode || e.Node is JobNode) + { + btnDeleteJob.Enabled = true; + } + else + { + btnDeleteJob.Enabled = false; + } + + if (e.Node is JobNode) + { + btnRunJobNow.Enabled = true; + pnlDetails.Controls.Add(new NativeJobDetailDisplay(((JobNode)e.Node).Detail)); + jobDetailsToggle(true); + } + else + { + btnRunJobNow.Enabled = false; + + } + if (e.Node is TriggerNode) + { + btnPause.Enabled = true; + setPauseButtonText(); + if (((TriggerNode)e.Node).Trigger is CronTrigger) + { + pnlDetails.Controls.Add(new CronTriggerDisplay((CronTrigger)((TriggerNode)e.Node).Trigger)); + jobDetailsToggle(true); + } + btnEdit.Enabled = true; + } + else + { + btnEdit.Enabled = false; + btnPause.Enabled = false; + } + } + + private void setPauseButtonText() + { + TriggerNode node = (TriggerNode)jobGroupsTreeView.SelectedNode; + string name = node.Trigger.Name; + string group = node.Trigger.Group; + if (Scheduler.GetScheduler().GetTriggerState(name, group) == TriggerState.Paused) + { + btnPause.Text = "Resume"; + } + else + { + btnPause.Text = "Pause"; + } + } + + private void connectToolStripMenuItem_Click(object sender, EventArgs e) + { + using (ServerConnectForm form = new ServerConnectForm()) + { + form.ShowDialog(); + try + { + Scheduler = new QuartzScheduler(form.Server, form.Port, form.Scheduler); + serverConnectStatusLabel.Text = string.Format("Connected to {0}", Scheduler.Address); + connectToolStripMenuItem.Enabled = false; + jobsToolStripMenuItem.Enabled = true; + loadJobGroups(); + updateRunningJobs(); + } + catch (SocketException ex) + { + ErrorDialog dialog = new ErrorDialog(); + dialog.Message = string.Format("Unable to connect to scheduler {0} on {1}:{2}", form.Scheduler, form.Server, form.Port); + dialog.Description = ex.Message; + dialog.ShowDialog(); + } + form.Close(); + } + //loadGlobalTriggers(); + } + + //private void loadGlobalTriggers() + //{ + // foreach (IJobListener jobListener in Scheduler.GetScheduler().GetJobDetail(null,null)..GlobalJobListeners) + // { + // globalTriggersListView.Items.Add(jobListener.Name); + // } + //} + + private void loadJobGroups() + { + + try + { + this.Cursor = Cursors.WaitCursor; + + jobDetailsToggle(false); + jobGroupsTreeView.Nodes.Clear(); + SchedulerNode schedulerNode = new SchedulerNode(Scheduler); + schedulerNode.ContextMenuStrip = ctxScheduler; + jobGroupsTreeView.Nodes.Add(schedulerNode); + TreeNode jobGroupsNode = schedulerNode.Nodes.Add("Job Groups"); + string[] jobGroups = Scheduler.GetScheduler().JobGroupNames; + foreach (string jobGroup in jobGroups) + { + TreeNode jobGroupNode = jobGroupsNode.Nodes.Add(jobGroup); + TreeNode jobsNode = jobGroupNode.Nodes.Add("Jobs"); + addJobNodes(jobsNode); + } + + jobGroupsTreeView.Nodes[0].Expand(); + jobGroupsNode.Expand(); + + StripStatusLabel_Job_Groups.Text = DateTime.Now.ToString("yyyy.MM.dd HH:mm.ss"); + + } + finally + { + this.Cursor = Cursors.Default; + } + + + } + + private void jobDetailsToggle(bool isVisible) + { + if (isVisible == false) + { + pnlDetails.Controls.Clear(); + } + } + + void jobGroupsTreeView_MouseDown(object sender, MouseEventArgs e) + { + if (e.Button == MouseButtons.Right) + { + TreeNode node = jobGroupsTreeView.GetNodeAt(e.X, e.Y); + if (node != null) + { + jobGroupsTreeView.SelectedNode = node; + ctxScheduler.Show(jobGroupsTreeView, e.Location); + } + } + } + //private void loadJobs() + //{ + // foreach (TreeNode node in jobGroupsTreeView.Nodes) + // { + // addJobNodes(node); + // } + //} + + private void addJobNodes(TreeNode node) + { + string group = node.Parent.Text; + string[] jobs = Scheduler.GetScheduler().GetJobNames(group); + foreach (string jobName in jobs) + { + try + { + IJobDetail detail = Scheduler.GetScheduler().GetJobDetail(new JobKey(jobName, group)); + JobNode jobNode = new JobNode(detail); + node.Nodes.Add(jobNode); + addTriggerNodes(jobNode); + addListenerNodes(jobNode); + } + catch (Exception ex) + { + //TODO: Do something useful with this exception. Most likely cause is the client does not have a copy of a given dll and can't load the type. + } + } + } + + private void addListenerNodes(JobNode node) + { + string jobName = node.Text; + string jobGroupName = node.Parent.Text; + //TODO: see joblistenermanager get listeners + //string[] listenerNames = node.Detail.JobListenerNames; + //foreach (string listener in listenerNames) + //{ + // node.Text = string.Format("JL {0}", listenerNames); + //} + //ISet set = Scheduler.GetScheduler().JobListenerNames; + } + + private void addTriggerNodes(TreeNode treeNode) + { + AbstractTrigger[] triggers = Scheduler.GetScheduler().GetTriggersOfJob(treeNode.Text, treeNode.Parent.Parent.Text); + TreeNode triggersNode = treeNode.Nodes.Add("Triggers"); + foreach (AbstractTrigger trigger in triggers) + { + TriggerNode node = new TriggerNode(trigger); + triggersNode.Nodes.Add(node); + } + + } + private void updateRunningJobs() + { + try + { + this.Cursor = Cursors.WaitCursor; + + timer_Refresh_Running_Jobs.Stop(); + + listView_RunningJobs.Items.Clear(); + + DataTable table = Scheduler.GetRunningJobs(); + foreach (DataRow row in table.Rows) + { + //JobName JobDuration + ListViewItem item = new ListViewItem(new string[] { Convert.ToString(row["JobName"]), Convert.ToString(row["Runtime"]) }); + listView_RunningJobs.Items.Add(item); + } + StripStatusLabel_Jobs_Refresh_date.Text = DateTime.Now.ToString("yyyy.MM.dd HH:mm.ss"); + + + //reset the timer ( documentation not clear if .stop = restart @ 0 in timing, but changing the interval sure should do that. ) + int timer_was = timer_Refresh_Running_Jobs.Interval; + timer_Refresh_Running_Jobs.Interval = timer_was + 1; + timer_Refresh_Running_Jobs.Interval = timer_was; + + timer_Refresh_Running_Jobs.Start(); + } + finally + { + this.Cursor = Cursors.Default; + } + } + public QuartzScheduler Scheduler { get; set; } + + private void addGlobalListenerToolStripMenuItem_Click(object sender, EventArgs e) + { + AddListenerForm form = new AddListenerForm(); + form.ListenerInterface = typeof(IJobListener); + form.ShowDialog(); + JobDataMap map = new JobDataMap(); + map.Add("type", form.ListenerType); + //Scheduler.ScheduleOneTimeJob(typeof(AddJobListenerJob), map, 0); + loadJobGroups(); + } + + private void addJobListenerToolStripMenuItem_Click(object sender, EventArgs e) + { + TreeNode selectedNode = jobGroupsTreeView.SelectedNode; + if (selectedNode != null && selectedNode is JobNode) + { + AddListenerForm form = new AddListenerForm(); + form.ListenerInterface = typeof(IJobListener); + form.ShowDialog(); + //JobHistoryListener listener = new JobHistoryListener(); + //listener.Name = null; + //((JobNode)selectedNode).Detail.AddJobListener(); + } + } + + private void addJobToolStripMenuItem_Click(object sender, EventArgs e) + { + AddJobForm form = new AddJobForm(); + form.ShowDialog(); + if (form.JobDetail != null && form.Trigger != null) + { + Scheduler.GetScheduler().ScheduleJob(form.JobDetail, form.Trigger); + loadJobGroups(); + } + } + + private void btnRefreshRunningJobs_Click(object sender, EventArgs e) + { + updateRunningJobs(); + } + + private void btnRefreshJobGroups_Click(object sender, EventArgs e) + { + loadJobGroups(); + } + + private void btnRunJobNow_Click(object sender, EventArgs e) + { + JobNode node = (JobNode)jobGroupsTreeView.SelectedNode; + string job = node.Detail.Name; + string group = node.Detail.Group; + Scheduler.GetScheduler().TriggerJobWithVolatileTrigger(job, group); + } + + private void btnDeleteJob_Click(object sender, EventArgs e) + { + TreeNode selectedNode = jobGroupsTreeView.SelectedNode; + if (selectedNode is JobNode) + { + JobNode node = (JobNode)jobGroupsTreeView.SelectedNode; + string job = node.Detail.Name; + string group = node.Detail.Group; + Scheduler.GetScheduler().DeleteJob(job, group); + jobGroupsTreeView.SelectedNode.Remove(); + + } + if (selectedNode is TriggerNode) + { + Scheduler.GetScheduler().UnscheduleJob(((TriggerNode)selectedNode).Trigger.Name, ((TriggerNode)selectedNode).Trigger.Group); + } + + //loadJobGroups(); + } + + private void btnPause_Click(object sender, EventArgs e) + { + TriggerNode node = (TriggerNode)jobGroupsTreeView.SelectedNode; + string name = node.Trigger.Name; + string group = node.Trigger.Group; + if (Scheduler.GetScheduler().GetTriggerState(name, group) == TriggerState.Paused) + { + Scheduler.GetScheduler().ResumeTrigger(name, group); + } + else + { + Scheduler.GetScheduler().PauseTrigger(name, group); + } + setPauseButtonText(); + } + + private void btnEdit_Click(object sender, EventArgs e) + { + TriggerNode node = (TriggerNode)jobGroupsTreeView.SelectedNode; + AddJobForm form = new AddJobForm(node); + form.ShowDialog(); + if (form.JobDetail != null && form.Trigger != null) + { + Scheduler.GetScheduler().RescheduleJob(node.Trigger.Name, node.Trigger.Group, form.Trigger); + loadJobGroups(); + } + } + + private void backupToolStripMenuItem_Click(object sender, EventArgs e) + { + QuartzScheduler scheduler = ((SchedulerNode)((TreeView)((ContextMenuStrip)((ToolStripMenuItem)sender).Owner).SourceControl).SelectedNode).Scheduler; + FileDialog dialog = new SaveFileDialog(); + dialog.ShowDialog(); + FileInfo file = new FileInfo(dialog.FileName); + scheduler.BackupToFile(file); + } + + private void timer_Refresh_Running_Jobs_Tick(object sender, EventArgs e) + { + updateRunningJobs(); + } + } } diff --git a/ClickForensics.Quartz.Manager/NativeJobDetailDisplay.cs b/ClickForensics.Quartz.Manager/NativeJobDetailDisplay.cs index 15dfa71..53a6632 100644 --- a/ClickForensics.Quartz.Manager/NativeJobDetailDisplay.cs +++ b/ClickForensics.Quartz.Manager/NativeJobDetailDisplay.cs @@ -7,6 +7,7 @@ using System.Linq; using System.Text; using System.Windows.Forms; using Quartz; +using Quartz.Impl; namespace ClickForensics.Quartz.Manager { @@ -21,8 +22,8 @@ namespace ClickForensics.Quartz.Manager void NativeJobDetailDisplay_Load(object sender, EventArgs e) { lblDescription.Text = _detail.Description; - lblGroup.Text = _detail.Group; - lblName.Text = _detail.Name; + lblGroup.Text = _detail.Key.Group; + lblName.Text = _detail.Key.Name; loadJobDataMap(); } @@ -33,12 +34,12 @@ namespace ClickForensics.Quartz.Manager jobDataListView.Items.Add(new ListViewItem(new string[] { item, _detail.JobDataMap.Get(item).ToString() })); } } - public NativeJobDetailDisplay(JobDetail detail) + public NativeJobDetailDisplay(IJobDetail detail) : this() { _detail = detail; } - private JobDetail _detail; + private IJobDetail _detail; } } diff --git a/ClickForensics.Quartz.Manager/QuartzScheduler.cs b/ClickForensics.Quartz.Manager/QuartzScheduler.cs index 561e9ca..8608cb9 100644 --- a/ClickForensics.Quartz.Manager/QuartzScheduler.cs +++ b/ClickForensics.Quartz.Manager/QuartzScheduler.cs @@ -11,301 +11,305 @@ using System.Collections; using System.Windows.Forms; using System.IO; using System.Xml.Linq; +using Quartz.Impl.Matchers; +using Quartz.Impl.Triggers; +using Quartz.Util; namespace ClickForensics.Quartz.Manager { - public class QuartzScheduler - { - public QuartzScheduler(string server, int port, string scheduler) - { - Address = string.Format("tcp://{0}:{1}/{2}", server, port, scheduler); - _schedulerFactory = new StdSchedulerFactory(getProperties(Address)); + public class QuartzScheduler + { + public QuartzScheduler(string server, int port, string scheduler) + { + Address = string.Format("tcp://{0}:{1}/{2}", server, port, scheduler); + _schedulerFactory = new StdSchedulerFactory(getProperties(Address)); - try - { - _scheduler = _schedulerFactory.GetScheduler(); - } - catch (SchedulerException se) - { - MessageBox.Show("Unable to connect to the specified server", "Connection Error", MessageBoxButtons.OK, MessageBoxIcon.Exclamation); - } - } - public string Address { get; private set; } - private NameValueCollection getProperties(string address) - { - NameValueCollection properties = new NameValueCollection(); - properties["quartz.scheduler.instanceName"] = "RemoteClient"; - properties["quartz.scheduler.proxy"] = "true"; - properties["quartz.threadPool.threadCount"] = "0"; - properties["quartz.scheduler.proxy.address"] = address; - return properties; - } - public IScheduler GetScheduler() - { - return _scheduler; - } - public DataTable GetJobs() - { - DataTable table = new DataTable(); - table.Columns.Add("GroupName"); - table.Columns.Add("JobName"); - table.Columns.Add("JobDescription"); - table.Columns.Add("TriggerName"); - table.Columns.Add("TriggerGroupName"); - table.Columns.Add("TriggerType"); - table.Columns.Add("TriggerState"); - table.Columns.Add("NextFireTime"); - table.Columns.Add("PreviousFireTime"); - string[] jobGroups = GetScheduler().JobGroupNames; - foreach (string group in jobGroups) - { - string[] jobNames = GetScheduler().GetJobNames(group); - foreach (string job in jobNames) - { - JobDetail detail = GetScheduler().GetJobDetail(job, group); - Trigger[] triggers = GetScheduler().GetTriggersOfJob(job, group); - foreach (Trigger trigger in triggers) - { - DataRow row = table.NewRow(); - row["GroupName"] = group; - row["JobName"] = job; - row["JobDescription"] = detail.Description; - row["TriggerName"] = trigger.Name; - row["TriggerGroupName"] = trigger.Group; - row["TriggerType"] = trigger.GetType().Name; - row["TriggerState"] = GetScheduler().GetTriggerState(trigger.Name, trigger.Group); - DateTime? nextFireTime = trigger.GetNextFireTimeUtc(); - if (nextFireTime != null) - { - row["NextFireTime"] = TimeZone.CurrentTimeZone.ToLocalTime((DateTime)nextFireTime); - } + try + { + _scheduler = _schedulerFactory.GetScheduler(); + } + catch (SchedulerException se) + { + MessageBox.Show("Unable to connect to the specified server", "Connection Error", MessageBoxButtons.OK, MessageBoxIcon.Exclamation); + } + } + public string Address { get; private set; } + private NameValueCollection getProperties(string address) + { + NameValueCollection properties = new NameValueCollection(); + properties["quartz.scheduler.instanceName"] = "RemoteClient"; + properties["quartz.scheduler.proxy"] = "true"; + properties["quartz.threadPool.threadCount"] = "0"; + properties["quartz.scheduler.proxy.address"] = address; + return properties; + } + public IScheduler GetScheduler() + { + return _scheduler; + } + public DataTable GetJobs() + { + DataTable table = new DataTable(); + table.Columns.Add("GroupName"); + table.Columns.Add("JobName"); + table.Columns.Add("JobDescription"); + table.Columns.Add("TriggerName"); + table.Columns.Add("TriggerGroupName"); + table.Columns.Add("TriggerType"); + table.Columns.Add("TriggerState"); + table.Columns.Add("NextFireTime"); + table.Columns.Add("PreviousFireTime"); + var jobGroups = GetScheduler().GetJobGroupNames(); + foreach (string group in jobGroups) + { + var groupMatcher = GroupMatcher.GroupContains(group); + var jobKeys = GetScheduler().GetJobKeys(groupMatcher); + foreach (var jobKey in jobKeys) + { + var detail = GetScheduler().GetJobDetail(jobKey); + var triggers = GetScheduler().GetTriggersOfJob(jobKey); + foreach (ITrigger trigger in triggers) + { + DataRow row = table.NewRow(); + row["GroupName"] = group; + row["JobName"] = jobKey.Name; + row["JobDescription"] = detail.Description; + row["TriggerName"] = trigger.Key.Name; + row["TriggerGroupName"] = trigger.Key.Group; + row["TriggerType"] = trigger.GetType().Name; + row["TriggerState"] = GetScheduler().GetTriggerState(trigger.Key); + DateTimeOffset? nextFireTime = trigger.GetNextFireTimeUtc(); + if (nextFireTime.HasValue) + { + row["NextFireTime"] = TimeZone.CurrentTimeZone.ToLocalTime(nextFireTime.Value.DateTime); + } - DateTime? previousFireTime = trigger.GetPreviousFireTimeUtc(); - if (previousFireTime != null) - { - row["PreviousFireTime"] = TimeZone.CurrentTimeZone.ToLocalTime((DateTime)previousFireTime); - } + DateTimeOffset? previousFireTime = trigger.GetPreviousFireTimeUtc(); + if (previousFireTime.HasValue) + { + row["PreviousFireTime"] = TimeZone.CurrentTimeZone.ToLocalTime(previousFireTime.Value.DateTime); + } - table.Rows.Add(row); - } - } - } - return table; - } + table.Rows.Add(row); + } + } + } + return table; + } - public void ScheduleOneTimeJob(Type jobType, JobDataMap dataMap, int clientID) - { - string name = string.Format("{0}-{1}", jobType.Name, clientID); - string group = clientID.ToString(); - JobDetail jobDetail = new JobDetail(name, group, jobType); - jobDetail.Description = "One time job"; - jobDetail.Durable = false; - jobDetail.Group = group; - jobDetail.JobDataMap = dataMap; - jobDetail.JobType = jobType; - jobDetail.Name = name; - jobDetail.Volatile = true; - SimpleTrigger trigger = new SimpleTrigger(); - trigger.Name = name; - trigger.Group = group; - trigger.StartTimeUtc = DateTime.UtcNow; - trigger.RepeatCount = 0; - trigger.RepeatInterval = TimeSpan.Zero; - GetScheduler().ScheduleJob(jobDetail, trigger); - } + public void ScheduleOneTimeJob(Type jobType, JobDataMap dataMap, int clientID) + { + string name = string.Format("{0}-{1}", jobType.Name, clientID); + string group = clientID.ToString(); + IJobDetail jobDetail = JobBuilder. + NewJob(). + OfType(jobType). + WithIdentity(name, group). + WithDescription("One time job"). + UsingJobData(dataMap).Build(); + ITrigger trigger = TriggerBuilder. + Create(). + ForJob(jobDetail). + WithIdentity(name, group). + WithSchedule(SimpleScheduleBuilder.Create().WithRepeatCount(0).WithInterval(TimeSpan.Zero)). + StartNow().Build(); + GetScheduler().ScheduleJob(jobDetail, trigger); + } - private ISchedulerFactory _schedulerFactory; + private ISchedulerFactory _schedulerFactory; - private IScheduler _scheduler; + private IScheduler _scheduler; - public DataTable GetRunningJobs() - { - DataTable table = new DataTable(); - table.Columns.Add("JobName", typeof(string)); - table.Columns.Add("RunTime", typeof(int)); - try - { - IList jobs = GetScheduler().GetCurrentlyExecutingJobs(); - foreach (JobExecutionContext context in jobs) - { - DataRow row = table.NewRow(); - row["JobName"] = context.JobDetail.Name; - row["RunTime"] = (DateTime.Now.ToUniversalTime() - (DateTime)context.FireTimeUtc).TotalMinutes; - table.Rows.Add(row); - } - } - catch (Exception ex) - { - //TODO: Let the user know we couldn't load the running jobs. - } + public DataTable GetRunningJobs() + { + DataTable table = new DataTable(); + table.Columns.Add("JobName", typeof(string)); + table.Columns.Add("RunTime", typeof(int)); + try + { + var contexts = GetScheduler().GetCurrentlyExecutingJobs(); + foreach (var context in contexts) + { + DataRow row = table.NewRow(); + row["JobName"] = context.JobDetail.Key.Name; + row["RunTime"] = (DateTime.Now.ToUniversalTime() - ((DateTimeOffset)context.FireTimeUtc).DateTime).TotalMinutes; + table.Rows.Add(row); + } + } + catch (Exception ex) + { + //TODO: Let the user know we couldn't load the running jobs. + } - return table; - } + return table; + } - public void BackupToFile(System.IO.FileInfo file) - { - IScheduler scheduler = GetScheduler(); - string[] jobGroupNames = scheduler.JobGroupNames; - List jobDetails = new List(); - foreach (var jobGroup in jobGroupNames) - { - string[] jobNames = scheduler.GetJobNames(jobGroup); - foreach (var jobName in jobNames) - { - jobDetails.Add(scheduler.GetJobDetail(jobName, jobGroup)); - } - } - writeToFile(file, jobDetails); + public void BackupToFile(System.IO.FileInfo file) + { + IScheduler scheduler = GetScheduler(); + string[] jobGroupNames = scheduler.JobGroupNames; + List jobDetails = new List(); + foreach (var jobGroup in jobGroupNames) + { + string[] jobNames = scheduler.GetJobNames(jobGroup); + foreach (var jobName in jobNames) + { + jobDetails.Add(scheduler.GetJobDetail(jobName, jobGroup)); + } + } + writeToFile(file, jobDetails); - } + } - private void writeToFile(System.IO.FileInfo file, List jobDetails) - { - using (StreamWriter writer = file.CreateText()) - { - XNamespace ns = "http://quartznet.sourceforge.net/JobSchedulingData"; - XDocument doc = new XDocument(new XDeclaration("1.0", "UTF-8", "yes") - , new XElement(ns + "quartz" - , new XAttribute(XNamespace.Xmlns + "xsi", "http://www.w3.org/2001/XMLSchema-instance") - , new XAttribute("version", "1.0") - , new XAttribute("overwrite-existing-jobs", "true") - ) - ); - foreach (JobDetail detail in jobDetails) - { - doc.Root.Add( - new XElement(ns + "job" - , new XElement(ns + "job-detail" - , new XElement(ns + "name", detail.Name) - , new XElement(ns + "group", detail.Group) - , new XElement(ns + "description", detail.Description) - , new XElement(ns + "job-type", detail.JobType.FullName + "," + detail.JobType.Assembly.FullName) - , new XElement(ns + "volatile", detail.Volatile) - , new XElement(ns + "durable", detail.Durable) - , new XElement(ns + "recover", detail.RequestsRecovery) - , getJobDataMap(ns, detail.JobDataMap) - ) - , getTriggers(ns, detail) - ) - ); - } - writer.Write(doc); - writer.Flush(); - writer.Close(); - } - } + private void writeToFile(System.IO.FileInfo file, List jobDetails) + { + using (StreamWriter writer = file.CreateText()) + { + XNamespace ns = "http://quartznet.sourceforge.net/JobSchedulingData"; + XDocument doc = new XDocument(new XDeclaration("1.0", "UTF-8", "yes") + , new XElement(ns + "quartz" + , new XAttribute(XNamespace.Xmlns + "xsi", "http://www.w3.org/2001/XMLSchema-instance") + , new XAttribute("version", "1.0") + , new XAttribute("overwrite-existing-jobs", "true") + ) + ); + foreach (JobDetail detail in jobDetails) + { + doc.Root.Add( + new XElement(ns + "job" + , new XElement(ns + "job-detail" + , new XElement(ns + "name", detail.Name) + , new XElement(ns + "group", detail.Group) + , new XElement(ns + "description", detail.Description) + , new XElement(ns + "job-type", detail.JobType.FullName + "," + detail.JobType.Assembly.FullName) + , new XElement(ns + "volatile", detail.Volatile) + , new XElement(ns + "durable", detail.Durable) + , new XElement(ns + "recover", detail.RequestsRecovery) + , getJobDataMap(ns, detail.JobDataMap) + ) + , getTriggers(ns, detail) + ) + ); + } + writer.Write(doc); + writer.Flush(); + writer.Close(); + } + } - private XElement getJobDataMap(XNamespace ns, JobDataMap jobDataMap) - { - XElement map = new XElement(ns + "job-data-map"); - foreach (var key in jobDataMap.GetKeys()) - { - map.Add(new XElement(ns + "entry" - , new XElement(ns + "key", key) - , new XElement(ns + "value", jobDataMap[key]) - ) - ); - } + private XElement getJobDataMap(XNamespace ns, JobDataMap jobDataMap) + { + XElement map = new XElement(ns + "job-data-map"); + foreach (var key in jobDataMap.GetKeys()) + { + map.Add(new XElement(ns + "entry" + , new XElement(ns + "key", key) + , new XElement(ns + "value", jobDataMap[key]) + ) + ); + } - return map; - } + return map; + } - private XElement[] getTriggers(XNamespace ns, JobDetail detail) - { - Trigger[] triggers = _scheduler.GetTriggersOfJob(detail.Name, detail.Group); - XElement[] elements = new XElement[triggers.Length]; - for (int i = 0; i < triggers.Length; i++) - { - elements[i] = new XElement(ns + "trigger"); - if (triggers[i] is SimpleTrigger) - { - elements[i].Add(getSimpleTrigger(ns, (SimpleTrigger)triggers[i])); - } - else if (triggers[i] is CronTrigger) - { - elements[i].Add(getCronTrigger(ns, (CronTrigger)triggers[i])); - } - } - return elements; - } + private XElement[] getTriggers(XNamespace ns, IJobDetail detail) + { + var triggers = _scheduler.GetTriggersOfJob(detail.Key); + XElement[] elements = new XElement[triggers.Count]; + int i = 0; + foreach (var trigger in triggers) + { + elements[i] = new XElement(ns + "trigger"); + if (triggers[i] is SimpleTriggerImpl) + { + elements[i].Add(getSimpleTrigger(ns, (SimpleTriggerImpl)triggers[i])); + } + else if (triggers[i] is CronTriggerImpl) + { + elements[i].Add(getCronTrigger(ns, (CronTriggerImpl)triggers[i])); + } + i++; + } + return elements; + } - private XElement getCronTrigger(XNamespace ns, CronTrigger trigger) - { - XElement cronTrigger = new XElement(ns + "cron"); - addCommonTriggerData(ns, cronTrigger, trigger); - cronTrigger.Add( - new XElement(ns + "cron-expression", trigger.CronExpressionString) - ); - return cronTrigger; - } + private XElement getCronTrigger(XNamespace ns, CronTriggerImpl trigger) + { + XElement cronTrigger = new XElement(ns + "cron"); + addCommonTriggerData(ns, cronTrigger, trigger); + cronTrigger.Add( + new XElement(ns + "cron-expression", trigger.CronExpressionString) + ); + return cronTrigger; + } - private void addCommonTriggerData(XNamespace ns, XElement rootTriggerElement, Trigger trigger) - { - rootTriggerElement.Add( - new XElement(ns + "name", trigger.Name) - , new XElement(ns + "group", trigger.Group) - , new XElement(ns + "description", trigger.Description) - , new XElement(ns + "misfire-instruction", getMisfireInstructionText(trigger)) - , new XElement(ns + "volatile", trigger.Volatile) - , new XElement(ns + "job-name", trigger.JobName) - , new XElement(ns + "job-group", trigger.JobGroup) - ); - } + private void addCommonTriggerData(XNamespace ns, XElement rootTriggerElement, AbstractTrigger trigger) + { + rootTriggerElement.Add( + new XElement(ns + "name", trigger.Name) + , new XElement(ns + "group", trigger.Group) + , new XElement(ns + "description", trigger.Description) + , new XElement(ns + "misfire-instruction", getMisfireInstructionText(trigger)) + //, new XElement(ns + "volatile", trigger.Volatile) + , new XElement(ns + "job-name", trigger.JobName) + , new XElement(ns + "job-group", trigger.JobGroup) + ); + } - private string getMisfireInstructionText(Trigger trigger) - { - if (trigger is CronTrigger) - { - return getCronTriggerMisfireInstructionText(trigger.MisfireInstruction); - } - return getSimpleTriggerMisfireInstructionText(trigger.MisfireInstruction); - } + private string getMisfireInstructionText(AbstractTrigger trigger) + { + if (trigger is CronTriggerImpl) + { + return getCronTriggerMisfireInstructionText(trigger.MisfireInstruction); + } + return getSimpleTriggerMisfireInstructionText(trigger.MisfireInstruction); + } - private string getSimpleTriggerMisfireInstructionText(int misfireInstruction) - { - switch (misfireInstruction) - { - case 0: - return "SmartPolicy"; - case 1: - return "FireNow"; - case 2: - return "RescheduleNowWithExistingRepeatCount"; - case 3: - return "RescheduleNowWithRemainingRepeatCount"; - case 4: - return "RescheduleNextWithRemainingCount"; - case 5: - return "RescheduleNextWithExistingCount"; - default: - throw new ArgumentOutOfRangeException(string.Format("{0} is not a supported misfire instruction for SimpleTrigger See Quartz.MisfireInstruction for more details.", misfireInstruction)); - } - } + private string getSimpleTriggerMisfireInstructionText(int misfireInstruction) + { + switch (misfireInstruction) + { + case 0: + return "SmartPolicy"; + case 1: + return "FireNow"; + case 2: + return "RescheduleNowWithExistingRepeatCount"; + case 3: + return "RescheduleNowWithRemainingRepeatCount"; + case 4: + return "RescheduleNextWithRemainingCount"; + case 5: + return "RescheduleNextWithExistingCount"; + default: + throw new ArgumentOutOfRangeException(string.Format("{0} is not a supported misfire instruction for SimpleTrigger See Quartz.MisfireInstruction for more details.", misfireInstruction)); + } + } - private string getCronTriggerMisfireInstructionText(int misfireInstruction) - { - switch (misfireInstruction) - { - case 0: - return "SmartPolicy"; - case 1: - return "FireOnceNow"; - case 2: - return "DoNothing"; - default: - throw new ArgumentOutOfRangeException(string.Format("{0} is not a supported misfire instruction for CronTrigger See Quartz.MisfireInstruction for more details.", misfireInstruction)); - } - } + private string getCronTriggerMisfireInstructionText(int misfireInstruction) + { + switch (misfireInstruction) + { + case 0: + return "SmartPolicy"; + case 1: + return "FireOnceNow"; + case 2: + return "DoNothing"; + default: + throw new ArgumentOutOfRangeException(string.Format("{0} is not a supported misfire instruction for CronTrigger See Quartz.MisfireInstruction for more details.", misfireInstruction)); + } + } - private XElement getSimpleTrigger(XNamespace ns, SimpleTrigger trigger) - { - XElement simpleTrigger = new XElement(ns + "simple"); - addCommonTriggerData(ns, simpleTrigger, trigger); - simpleTrigger.Add( - new XElement(ns + "repeat-count", trigger.RepeatCount) - , new XElement(ns + "repeat-interval", trigger.RepeatInterval.Milliseconds) - ); - return simpleTrigger; - } - } + private XElement getSimpleTrigger(XNamespace ns, SimpleTriggerImpl trigger) + { + XElement simpleTrigger = new XElement(ns + "simple"); + addCommonTriggerData(ns, simpleTrigger, trigger); + simpleTrigger.Add( + new XElement(ns + "repeat-count", trigger.RepeatCount) + , new XElement(ns + "repeat-interval", trigger.RepeatInterval.Milliseconds) + ); + return simpleTrigger; + } + } } diff --git a/ClickForensics.Quartz.Manager/TriggerNode.cs b/ClickForensics.Quartz.Manager/TriggerNode.cs index 43944b1..352859a 100644 --- a/ClickForensics.Quartz.Manager/TriggerNode.cs +++ b/ClickForensics.Quartz.Manager/TriggerNode.cs @@ -4,17 +4,18 @@ using System.Linq; using System.Text; using System.Windows.Forms; using Quartz; +using Quartz.Impl.Triggers; namespace ClickForensics.Quartz.Manager { - public class TriggerNode : TreeNode - { - public TriggerNode(Trigger trigger) - { - Text = trigger.Name; - - Trigger = trigger; - } - public Trigger Trigger { get; set; } - } + public class TriggerNode : TreeNode + { + public TriggerNode(AbstractTrigger trigger) + { + Text = trigger.Name; + + Trigger = trigger; + } + public AbstractTrigger Trigger { get; set; } + } } diff --git a/lib/Quartz.dll b/lib/Quartz.dll index b65ee66..6e66a61 100644 Binary files a/lib/Quartz.dll and b/lib/Quartz.dll differ