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.checkMonitorThread();
181 this.createTaskState( task );
182 this.fireTaskEvent( new TaskEvent( task, TaskEvent.STARTED ) );
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 }
270
271
272 private class MonitorThread extends Thread
273 {
274
275
276 private final long pollIntervalMillis;
277
278
279 private MonitorThread( final long pollIntervalMillis )
280 {
281 super( "DefaultTaskMonitor" );
282 this.pollIntervalMillis = pollIntervalMillis;
283 }
284
285
286 public void run()
287 {
288 while ( true )
289 {
290 try
291 {
292 Thread.sleep( this.pollIntervalMillis );
293 this.checkTasks();
294 }
295 catch ( InterruptedException e )
296 {
297 this.checkTasks();
298 }
299 }
300 }
301
302 public void start()
303 {
304 super.start();
305 getLogger().debug( getThreadStartedMessage(
306 getLocale(), new Long( this.pollIntervalMillis ) ) );
307
308 }
309
310
311
312
313
314 private void checkTasks()
315 {
316 synchronized ( DefaultTaskMonitor.this.stateMap )
317 {
318 for ( Iterator it = DefaultTaskMonitor.this.stateMap.keySet().
319 iterator(); it.hasNext(); )
320 {
321 final Task task = (Task) it.next();
322 if ( changedState( task ) )
323 {
324 fireTaskEvent( new TaskEvent(
325 task, TaskEvent.CHANGED_STATE ) );
326
327 }
328 }
329 }
330 }
331
332 }
333
334
335
336
337
338
339 private synchronized void checkMonitorThread()
340 {
341 if ( this.monitorThread == null )
342 {
343 this.monitorThread =
344 new MonitorThread( this.getPollIntervalMillis() );
345
346 this.monitorThread.start();
347 }
348
349 if ( !this.monitorThread.isAlive() )
350 {
351 this.getLogger().warn( this.getThreadDiedMessage(
352 this.getLocale() ) );
353
354 this.monitorThread =
355 new MonitorThread( this.getPollIntervalMillis() );
356
357 this.monitorThread.start();
358 }
359 }
360
361
362
363
364
365
366 private void fireTaskEvent( final TaskEvent e )
367 {
368 if ( e == null )
369 {
370 throw new NullPointerException( "e" );
371 }
372
373
374 final Object[] listeners = this.taskListeners.getListenerList();
375 for ( int i = listeners.length - 2; i >= 0; i -= 2 )
376 {
377 if ( listeners[i] == TaskListener.class )
378 {
379 ( (TaskListener) listeners[i + 1] ).onTaskEvent( e );
380 }
381 }
382
383 final TaskListener[] taskListener = this.getTaskListener();
384 for ( int i = taskListener.length - 1; i >= 0; i-- )
385 {
386 taskListener[i].onTaskEvent( e );
387 }
388 }
389
390
391
392
393
394
395
396
397
398
399 private void createTaskState( final Task task )
400 {
401 final TaskState state = new TaskState();
402 state.cancelable = task.isCancelable();
403 state.indeterminate = task.isIndeterminate();
404 state.cancelled = state.cancelable
405 ? task.isCancelled()
406 : false;
407
408 state.progressDescription = task.getProgressDescription();
409
410 if ( state.indeterminate )
411 {
412 state.maximum = Integer.MIN_VALUE;
413 state.minimum = Integer.MIN_VALUE;
414 state.progress = Integer.MIN_VALUE;
415 }
416 else
417 {
418 state.maximum = task.getMaximum();
419 state.minimum = task.getMinimum();
420 state.progress = task.getProgress();
421 }
422
423 if ( this.stateMap.put( task, state ) != null )
424 {
425 throw new IllegalStateException( this.getTaskAlreadyStartedMessage(
426 this.getLocale(),
427 task.getDescription().getText( this.getLocale() ),
428 new Date( task.getTimestamp() ) ) );
429
430 }
431 }
432
433
434
435
436
437
438
439
440 private void removeTaskState( final Task task )
441 {
442 if ( task == null )
443 {
444 throw new NullPointerException( "task" );
445 }
446
447 this.stateMap.remove( task );
448 }
449
450
451
452
453
454
455
456
457
458
459
460
461 private boolean changedState( final Task task )
462 {
463 if ( task == null )
464 {
465 throw new NullPointerException( "task" );
466 }
467
468
469 boolean changedState = false;
470 final TaskState state = (TaskState) this.stateMap.get( task );
471
472 if ( state == null )
473 {
474 throw new IllegalStateException();
475 }
476
477 if ( state.indeterminate )
478 {
479 state.indeterminate = task.isIndeterminate();
480 if ( !state.indeterminate )
481 {
482 state.minimum = task.getMinimum();
483 state.maximum = task.getMaximum();
484 state.progress = task.getProgress();
485 changedState = true;
486 }
487 }
488 else
489 {
490 state.indeterminate = task.isIndeterminate();
491 if ( state.indeterminate )
492 {
493 changedState = true;
494 }
495 else
496 {
497 if ( state.minimum != task.getMinimum() )
498 {
499 state.minimum = task.getMinimum();
500 changedState = true;
501 }
502 if ( state.maximum != task.getMaximum() )
503 {
504 state.maximum = task.getMaximum();
505 changedState = true;
506 }
507 if ( state.progress != task.getProgress() )
508 {
509 state.progress = task.getProgress();
510 changedState = true;
511 }
512 }
513 }
514
515 if ( state.cancelable )
516 {
517 state.cancelable = task.isCancelable();
518 if ( !state.cancelable )
519 {
520 changedState = true;
521 }
522 else
523 {
524 if ( state.cancelled != task.isCancelled() )
525 {
526 state.cancelled = task.isCancelled();
527 changedState = true;
528 }
529 }
530 }
531 else
532 {
533 state.cancelable = task.isCancelable();
534 if ( !state.cancelable )
535 {
536 state.cancelled = false;
537 changedState = true;
538 }
539 }
540
541 if ( state.progressDescription != task.getProgressDescription() )
542 {
543 state.progressDescription = task.getProgressDescription();
544 changedState = true;
545 }
546 else if ( state.progressDescription != null &&
547 !state.progressDescription.getText( this.getLocale() ).
548 equals( task.getProgressDescription().getText(
549 this.getLocale() ) ) )
550 {
551 changedState = true;
552 }
553
554 return changedState;
555 }
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573 private String getThreadStartedMessage( final Locale locale,
574 final java.lang.Number periodMillis )
575 {
576 return ContainerFactory.getContainer().
577 getMessage( this, "threadStarted", locale,
578 new Object[]
579 {
580 periodMillis
581 });
582
583 }
584
585
586
587
588
589
590
591
592
593
594 private String getThreadDiedMessage( final Locale locale )
595 {
596 return ContainerFactory.getContainer().
597 getMessage( this, "threadDied", locale, null );
598
599 }
600
601
602
603
604
605
606
607
608
609
610
611
612 private String getTaskAlreadyStartedMessage( final Locale locale,
613 final java.lang.String taskDescription,
614 final java.util.Date startTime )
615 {
616 return ContainerFactory.getContainer().
617 getMessage( this, "taskAlreadyStarted", locale,
618 new Object[]
619 {
620 taskDescription,
621 startTime
622 });
623
624 }
625
626
627
628
629 }