1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 package org.jdtaus.core.monitor.ri;
22
23 import java.util.Date;
24 import java.util.HashMap;
25 import java.util.Iterator;
26 import java.util.Locale;
27 import java.util.Map;
28 import javax.swing.event.EventListenerList;
29 import org.jdtaus.core.container.ContainerFactory;
30 import org.jdtaus.core.logging.spi.Logger;
31 import org.jdtaus.core.monitor.Task;
32 import org.jdtaus.core.monitor.TaskEvent;
33 import org.jdtaus.core.monitor.TaskListener;
34 import org.jdtaus.core.monitor.spi.TaskMonitor;
35 import org.jdtaus.core.text.Message;
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59 public class DefaultTaskMonitor implements TaskMonitor
60 {
61
62
63
64
65
66
67 public DefaultTaskMonitor()
68 {
69 super();
70 }
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85 private Logger getLogger()
86 {
87 return (Logger) ContainerFactory.getContainer().
88 getDependency( this, "Logger" );
89
90 }
91
92
93
94
95
96
97 private TaskListener[] getTaskListener()
98 {
99 return (TaskListener[]) ContainerFactory.getContainer().
100 getDependency( this, "TaskListener" );
101
102 }
103
104
105
106
107
108
109 private Locale getLocale()
110 {
111 return (Locale) ContainerFactory.getContainer().
112 getDependency( this, "Locale" );
113
114 }
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129 private java.lang.Long getDefaultPollIntervalMillis()
130 {
131 return (java.lang.Long) ContainerFactory.getContainer().
132 getProperty( this, "defaultPollIntervalMillis" );
133
134 }
135
136
137
138
139
140
141 public void addTaskListener( final TaskListener listener )
142 {
143 if ( listener == null )
144 {
145 throw new NullPointerException( "listener" );
146 }
147
148 this.taskListeners.add( TaskListener.class, listener );
149 }
150
151 public void removeTaskListener( final TaskListener listener )
152 {
153 if ( listener == null )
154 {
155 throw new NullPointerException( "listener" );
156 }
157
158 this.taskListeners.remove( TaskListener.class, listener );
159 }
160
161 public TaskListener[] getTaskListeners()
162 {
163 return (TaskListener[]) this.taskListeners.getListeners(
164 TaskListener.class );
165
166 }
167
168
169
170
171 public void monitor( final Task task )
172 {
173 if ( task == null )
174 {
175 throw new NullPointerException( "task" );
176 }
177
178 synchronized ( this.stateMap )
179 {
180 this.fireTaskEvent( new TaskEvent( task, TaskEvent.STARTED ) );
181 this.createTaskState( task );
182 this.checkMonitorThread();
183 }
184 }
185
186 public void finish( final Task task )
187 {
188 if ( task == null )
189 {
190 throw new NullPointerException( "task" );
191 }
192
193 synchronized ( this.stateMap )
194 {
195 if ( this.changedState( task ) )
196 {
197 this.fireTaskEvent( new TaskEvent( task,
198 TaskEvent.CHANGED_STATE ) );
199
200 }
201
202 this.removeTaskState( task );
203 this.fireTaskEvent( new TaskEvent( task, TaskEvent.ENDED ) );
204 }
205 }
206
207
208
209
210
211 private final EventListenerList taskListeners = new EventListenerList();
212
213
214 private MonitorThread monitorThread;
215
216
217 private final Map stateMap = new HashMap( 1000 );
218
219
220 private Long pollIntervalMillis;
221
222
223
224
225
226
227
228 public DefaultTaskMonitor( final long pollIntervalMillis )
229 {
230 if ( pollIntervalMillis > 0L )
231 {
232 this.pollIntervalMillis = new Long( pollIntervalMillis );
233 }
234 }
235
236
237
238
239
240
241 private long getPollIntervalMillis()
242 {
243 if ( this.pollIntervalMillis == null )
244 {
245 this.pollIntervalMillis = this.getDefaultPollIntervalMillis();
246 }
247
248 return this.pollIntervalMillis.longValue();
249 }
250
251
252 private static final class TaskState
253 {
254
255 boolean indeterminate;
256
257 boolean cancelable;
258
259 boolean cancelled;
260
261 int minimum;
262
263 int maximum;
264
265 int progress;
266
267 Message progressDescription;
268
269 private TaskState()
270 {
271 super();
272 }
273
274 }
275
276
277 private final class MonitorThread extends Thread
278 {
279
280
281 private final long pollIntervalMillis;
282
283
284 private MonitorThread( final long pollIntervalMillis )
285 {
286 super( "DefaultTaskMonitor" );
287 this.pollIntervalMillis = pollIntervalMillis;
288 }
289
290
291 public void run()
292 {
293 boolean monitoring = true;
294
295 while ( monitoring )
296 {
297 try
298 {
299 Thread.sleep( this.pollIntervalMillis );
300 monitoring = this.checkTasks();
301 }
302 catch ( final InterruptedException e )
303 {
304 monitoring = this.checkTasks();
305 }
306 }
307 }
308
309 public void start()
310 {
311 super.start();
312
313 if ( getLogger().isDebugEnabled() )
314 {
315 getLogger().debug( getThreadStartedMessage(
316 getLocale(), new Long( this.pollIntervalMillis ) ) );
317
318 }
319 }
320
321
322
323
324
325 private boolean checkTasks()
326 {
327 synchronized ( DefaultTaskMonitor.this.stateMap )
328 {
329 for ( final Iterator it = DefaultTaskMonitor.this.stateMap.
330 keySet().iterator(); it.hasNext(); )
331 {
332 final Task task = (Task) it.next();
333 if ( changedState( task ) )
334 {
335 fireTaskEvent( new TaskEvent(
336 task, TaskEvent.CHANGED_STATE ) );
337
338 }
339 }
340
341 return !DefaultTaskMonitor.this.stateMap.isEmpty();
342 }
343 }
344
345 }
346
347
348
349
350
351
352 private synchronized void checkMonitorThread()
353 {
354 if ( this.monitorThread == null
355 || !this.monitorThread.isAlive() )
356 {
357 this.monitorThread =
358 new MonitorThread( this.getPollIntervalMillis() );
359
360 this.monitorThread.start();
361 }
362 }
363
364
365
366
367
368
369 private void fireTaskEvent( final TaskEvent e )
370 {
371 if ( e == null )
372 {
373 throw new NullPointerException( "e" );
374 }
375
376
377 final Object[] listeners = this.taskListeners.getListenerList();
378 for ( int i = listeners.length - 2; i >= 0; i -= 2 )
379 {
380 if ( listeners[i] == TaskListener.class )
381 {
382 ( (TaskListener) listeners[i + 1] ).onTaskEvent( e );
383 }
384 }
385
386 final TaskListener[] taskListener = this.getTaskListener();
387 for ( int i = taskListener.length - 1; i >= 0; i-- )
388 {
389 taskListener[i].onTaskEvent( e );
390 }
391 }
392
393
394
395
396
397
398
399
400
401
402 private void createTaskState( final Task task )
403 {
404 final TaskState state = new TaskState();
405 state.cancelable = task.isCancelable();
406 state.indeterminate = task.isIndeterminate();
407 state.cancelled = state.cancelable
408 ? task.isCancelled()
409 : false;
410
411 state.progressDescription = task.getProgressDescription();
412
413 if ( state.indeterminate )
414 {
415 state.maximum = Integer.MIN_VALUE;
416 state.minimum = Integer.MIN_VALUE;
417 state.progress = Integer.MIN_VALUE;
418 }
419 else
420 {
421 state.maximum = task.getMaximum();
422 state.minimum = task.getMinimum();
423 state.progress = task.getProgress();
424 }
425
426 if ( this.stateMap.put( task, state ) != null )
427 {
428 throw new IllegalStateException( this.getTaskAlreadyStartedMessage(
429 this.getLocale(),
430 task.getDescription().getText( this.getLocale() ),
431 new Date( task.getTimestamp() ) ) );
432
433 }
434 }
435
436
437
438
439
440
441
442
443 private void removeTaskState( final Task task )
444 {
445 if ( task == null )
446 {
447 throw new NullPointerException( "task" );
448 }
449
450 this.stateMap.remove( task );
451 }
452
453
454
455
456
457
458
459
460
461
462
463
464 private boolean changedState( final Task task )
465 {
466 if ( task == null )
467 {
468 throw new NullPointerException( "task" );
469 }
470
471
472 boolean changedState = false;
473 final TaskState state = (TaskState) this.stateMap.get( task );
474
475 if ( state == null )
476 {
477 throw new IllegalStateException();
478 }
479
480 if ( state.indeterminate )
481 {
482 state.indeterminate = task.isIndeterminate();
483 if ( !state.indeterminate )
484 {
485 state.minimum = task.getMinimum();
486 state.maximum = task.getMaximum();
487 state.progress = task.getProgress();
488 changedState = true;
489 }
490 }
491 else
492 {
493 state.indeterminate = task.isIndeterminate();
494 if ( state.indeterminate )
495 {
496 changedState = true;
497 }
498 else
499 {
500 if ( state.minimum != task.getMinimum() )
501 {
502 state.minimum = task.getMinimum();
503 changedState = true;
504 }
505 if ( state.maximum != task.getMaximum() )
506 {
507 state.maximum = task.getMaximum();
508 changedState = true;
509 }
510 if ( state.progress != task.getProgress() )
511 {
512 state.progress = task.getProgress();
513 changedState = true;
514 }
515 }
516 }
517
518 if ( state.cancelable )
519 {
520 state.cancelable = task.isCancelable();
521 if ( !state.cancelable )
522 {
523 changedState = true;
524 }
525 else
526 {
527 if ( state.cancelled != task.isCancelled() )
528 {
529 state.cancelled = task.isCancelled();
530 changedState = true;
531 }
532 }
533 }
534 else
535 {
536 state.cancelable = task.isCancelable();
537 if ( !state.cancelable )
538 {
539 state.cancelled = false;
540 changedState = true;
541 }
542 }
543
544 if ( state.progressDescription != task.getProgressDescription() )
545 {
546 state.progressDescription = task.getProgressDescription();
547 changedState = true;
548 }
549 else if ( state.progressDescription != null
550 && !state.progressDescription.getText( this.getLocale() ).
551 equals( task.getProgressDescription().getText(
552 this.getLocale() ) ) )
553 {
554 changedState = true;
555 }
556
557 return changedState;
558 }
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576 private String getThreadStartedMessage( final Locale locale,
577 final java.lang.Number periodMillis )
578 {
579 return ContainerFactory.getContainer().
580 getMessage( this, "threadStarted", locale,
581 new Object[]
582 {
583 periodMillis
584 });
585
586 }
587
588
589
590
591
592
593
594
595
596
597
598
599 private String getTaskAlreadyStartedMessage( final Locale locale,
600 final java.lang.String taskDescription,
601 final java.util.Date startTime )
602 {
603 return ContainerFactory.getContainer().
604 getMessage( this, "taskAlreadyStarted", locale,
605 new Object[]
606 {
607 taskDescription,
608 startTime
609 });
610
611 }
612
613
614
615
616 }