| JobManager.java |
1 /**
2 * Distribution License:
3 * JSword is free software; you can redistribute it and/or modify it under
4 * the terms of the GNU Lesser General Public License, version 2.1 or later
5 * as published by the Free Software Foundation. This program is distributed
6 * in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
7 * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
8 * See the GNU Lesser General Public License for more details.
9 *
10 * The License is available on the internet at:
11 * http://www.gnu.org/copyleft/lgpl.html
12 * or by writing to:
13 * Free Software Foundation, Inc.
14 * 59 Temple Place - Suite 330
15 * Boston, MA 02111-1307, USA
16 *
17 * © CrossWire Bible Society, 2005 - 2016
18 *
19 */
20 package org.crosswire.common.progress;
21
22 import org.slf4j.Logger;
23 import org.slf4j.LoggerFactory;
24
25 import java.util.Iterator;
26 import java.util.List;
27 import java.util.Set;
28 import java.util.UUID;
29 import java.util.concurrent.CopyOnWriteArrayList;
30 import java.util.concurrent.CopyOnWriteArraySet;
31
32 /**
33 * JobManager is responsible for creating jobs and informing listeners about the
34 * progress they make to completion.
35 *
36 * <p>
37 * Example code:
38 *
39 * <pre>
40 * final Thread worker = new Thread("DisplayPreLoader")
41 * {
42 * public void run()
43 * {
44 * URL predictURI = Project.instance().getWritablePropertiesURI("save-name");
45 * Progress job = JobManager.createJob("Job Title", predictURI, this, true);
46 * try
47 * {
48 * job.setProgress("Step 1");
49 * ...
50 * job.setProgress("Step 2");
51 * ...
52 * }
53 * catch (Exception ex)
54 * {
55 * ...
56 * job.ignoreTimings();
57 * }
58 * finally
59 * {
60 * job.done();
61 * }
62 * }
63 * };
64 * worker.setPriority(Thread.MIN_PRIORITY);
65 * worker.start();
66 * </pre>
67 *
68 * @see gnu.lgpl.License The GNU Lesser General Public License for details.
69 * @author Joe Walker
70 */
71 public final class JobManager {
72 /**
73 * Prevent instantiation
74 */
75 private JobManager() {
76 }
77
78 /**
79 * Create a new Job that cannot be canceled.
80 *
81 * @param jobName the name of the Job
82 * @return the job
83 */
84 public static Progress createJob(String jobName) {
85 return createJob(UUID.randomUUID().toString(), jobName, null);
86 }
87
88 /**
89 * Create a new Job that can be canceled.
90 *
91 * @param jobID a unique identifier for the job
92 * @param jobName the name of the Job
93 * @param workerThread the thread on which this job runs
94 * @return the job
95 */
96 public static Progress createJob(String jobID, String jobName, Thread workerThread) {
97 Progress job = new Job(jobID, jobName, workerThread);
98 jobs.add(job);
99
100 log.debug("job starting: {}", job.getJobName());
101
102 return job;
103 }
104
105 /**
106 * Add a listener to the list
107 *
108 * @param li the interested listener
109 */
110 public static void addWorkListener(WorkListener li) {
111 listeners.add(li);
112 }
113
114 /**
115 * Remove a listener from the list
116 *
117 * @param li the disinterested listener
118 */
119 public static void removeWorkListener(WorkListener li) {
120 listeners.remove(li);
121 }
122
123 /**
124 * Accessor for the currently known jobs
125 *
126 * @return an iterator over the jobs
127 */
128 public static Iterator<Progress> iterator() {
129 return jobs.iterator();
130 }
131
132 /**
133 * @return the number of current jobs
134 */
135 public static int getJobCount() {
136 return jobs.size();
137 }
138
139 /**
140 * Inform the listeners that a title has changed.
141 *
142 * @param job the job that has made progress
143 */
144 protected static void fireWorkProgressed(Progress job) {
145 final WorkEvent ev = new WorkEvent(job);
146
147 // We ought only to tell listeners about jobs that are in our
148 // list of jobs so we need to fire before delete.
149 for (WorkListener worker : listeners) {
150 worker.workProgressed(ev);
151 }
152
153 // Do we need to remove the job? Note that the section above will
154 // probably execute after this so we will be firing events for jobs
155 // that are no longer in our list of jobs. ho hum.
156 if (job.isFinished()) {
157 log.debug("job finished: {}", job.getJobName());
158 jobs.remove(job);
159 }
160 }
161
162 /**
163 * List of listeners using thread safe list
164 */
165 private static List<WorkListener> listeners = new CopyOnWriteArrayList<WorkListener>();
166
167 /**
168 * List of current jobs
169 */
170 private static Set<Progress> jobs = new CopyOnWriteArraySet<Progress>();
171
172 /**
173 * The log stream
174 */
175 private static final Logger log = LoggerFactory.getLogger(JobManager.class);
176 }
177