KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > ui > internal > progress > ProgressManager


1 /*******************************************************************************
2  * Copyright (c) 2003, 2007 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11 package org.eclipse.ui.internal.progress;
12
13 import java.io.FileNotFoundException JavaDoc;
14 import java.io.IOException JavaDoc;
15 import java.io.InputStream JavaDoc;
16 import java.lang.reflect.InvocationTargetException JavaDoc;
17 import java.net.MalformedURLException JavaDoc;
18 import java.net.URL JavaDoc;
19 import java.util.ArrayList JavaDoc;
20 import java.util.Collection JavaDoc;
21 import java.util.Collections JavaDoc;
22 import java.util.Enumeration JavaDoc;
23 import java.util.HashMap JavaDoc;
24 import java.util.HashSet JavaDoc;
25 import java.util.Hashtable JavaDoc;
26 import java.util.Iterator JavaDoc;
27 import java.util.Map JavaDoc;
28
29 import org.eclipse.core.runtime.IProgressMonitor;
30 import org.eclipse.core.runtime.IProgressMonitorWithBlocking;
31 import org.eclipse.core.runtime.IStatus;
32 import org.eclipse.core.runtime.NullProgressMonitor;
33 import org.eclipse.core.runtime.OperationCanceledException;
34 import org.eclipse.core.runtime.QualifiedName;
35 import org.eclipse.core.runtime.Status;
36 import org.eclipse.core.runtime.jobs.IJobChangeEvent;
37 import org.eclipse.core.runtime.jobs.IJobChangeListener;
38 import org.eclipse.core.runtime.jobs.IJobManager;
39 import org.eclipse.core.runtime.jobs.ISchedulingRule;
40 import org.eclipse.core.runtime.jobs.Job;
41 import org.eclipse.core.runtime.jobs.JobChangeAdapter;
42 import org.eclipse.core.runtime.jobs.ProgressProvider;
43 import org.eclipse.jface.dialogs.Dialog;
44 import org.eclipse.jface.operation.IRunnableContext;
45 import org.eclipse.jface.operation.IRunnableWithProgress;
46 import org.eclipse.jface.resource.ImageDescriptor;
47 import org.eclipse.jface.resource.ImageRegistry;
48 import org.eclipse.jface.resource.JFaceResources;
49 import org.eclipse.swt.custom.BusyIndicator;
50 import org.eclipse.swt.graphics.Image;
51 import org.eclipse.swt.graphics.ImageData;
52 import org.eclipse.swt.graphics.ImageLoader;
53 import org.eclipse.swt.widgets.Display;
54 import org.eclipse.swt.widgets.Shell;
55 import org.eclipse.ui.IWorkbench;
56 import org.eclipse.ui.PlatformUI;
57 import org.eclipse.ui.internal.IPreferenceConstants;
58 import org.eclipse.ui.internal.Workbench;
59 import org.eclipse.ui.internal.WorkbenchPlugin;
60 import org.eclipse.ui.internal.dialogs.EventLoopProgressMonitor;
61 import org.eclipse.ui.internal.dialogs.WorkbenchDialogBlockedHandler;
62 import org.eclipse.ui.internal.misc.Policy;
63 import org.eclipse.ui.progress.IProgressConstants;
64 import org.eclipse.ui.progress.IProgressService;
65 import org.eclipse.ui.progress.WorkbenchJob;
66 import org.eclipse.ui.statushandlers.StatusAdapter;
67 import org.eclipse.ui.statushandlers.StatusManager;
68
69 /**
70  * JobProgressManager provides the progress monitor to the job manager and
71  * informs any ProgressContentProviders of changes.
72  */

73 public class ProgressManager extends ProgressProvider implements
74         IProgressService {
75     /**
76      * A property to determine if the job was run in the dialog. Kept for
77      * backwards compatability.
78      *
79      * @deprecated
80      * @see IProgressConstants#PROPERTY_IN_DIALOG
81      */

82     public static final QualifiedName PROPERTY_IN_DIALOG = IProgressConstants.PROPERTY_IN_DIALOG;
83
84     private static final String JavaDoc ERROR_JOB = "errorstate.gif"; //$NON-NLS-1$
85

86     static final String JavaDoc ERROR_JOB_KEY = "ERROR_JOB"; //$NON-NLS-1$
87

88     private static ProgressManager singleton;
89
90     final private Map JavaDoc jobs = Collections.synchronizedMap(new HashMap JavaDoc());
91
92     final private Map JavaDoc familyListeners = Collections
93             .synchronizedMap(new HashMap JavaDoc());
94
95     final Object JavaDoc familyKey = new Object JavaDoc();
96
97     private IJobProgressManagerListener[] listeners = new IJobProgressManagerListener[0];
98
99     final Object JavaDoc listenersKey = new Object JavaDoc();
100
101     IJobChangeListener changeListener;
102
103     static final String JavaDoc PROGRESS_VIEW_NAME = "org.eclipse.ui.views.ProgressView"; //$NON-NLS-1$
104

105     static final String JavaDoc PROGRESS_FOLDER = "$nl$/icons/full/progress/"; //$NON-NLS-1$
106

107     private static final String JavaDoc SLEEPING_JOB = "sleeping.gif"; //$NON-NLS-1$
108

109     private static final String JavaDoc WAITING_JOB = "waiting.gif"; //$NON-NLS-1$
110

111     private static final String JavaDoc BLOCKED_JOB = "lockedstate.gif"; //$NON-NLS-1$
112

113     /**
114      * The key for the sleeping job icon.
115      */

116     public static final String JavaDoc SLEEPING_JOB_KEY = "SLEEPING_JOB"; //$NON-NLS-1$
117

118     /**
119      * The key for the waiting job icon.
120      */

121     public static final String JavaDoc WAITING_JOB_KEY = "WAITING_JOB"; //$NON-NLS-1$
122

123     /**
124      * The key for the locked job icon.
125      */

126     public static final String JavaDoc BLOCKED_JOB_KEY = "LOCKED_JOB"; //$NON-NLS-1$
127

128     final Map JavaDoc runnableMonitors = Collections.synchronizedMap(new HashMap JavaDoc());
129
130     final Object JavaDoc monitorKey = new Object JavaDoc();
131
132     FinishedJobs finishedJobs;
133
134     // A table that maps families to keys in the Jface image
135
// table
136
private Hashtable JavaDoc imageKeyTable = new Hashtable JavaDoc();
137
138     private static final String JavaDoc IMAGE_KEY = "org.eclipse.ui.progress.images"; //$NON-NLS-1$
139

140     /**
141      * Get the progress manager currently in use.
142      *
143      * @return JobProgressManager
144      */

145     public static ProgressManager getInstance() {
146         if (singleton == null) {
147             singleton = new ProgressManager();
148         }
149         return singleton;
150     }
151
152     /**
153      * Shutdown the singleton if there is one.
154      */

155     public static void shutdownProgressManager() {
156         if (singleton == null) {
157             return;
158         }
159         singleton.shutdown();
160     }
161
162     /**
163      * The JobMonitor is the inner class that handles the IProgressMonitor
164      * integration with the ProgressMonitor.
165      */

166     class JobMonitor implements IProgressMonitorWithBlocking {
167         Job job;
168
169         String JavaDoc currentTaskName;
170
171         IProgressMonitorWithBlocking listener;
172
173         /**
174          * Create a monitor on the supplied job.
175          *
176          * @param newJob
177          */

178         JobMonitor(Job newJob) {
179             job = newJob;
180         }
181
182         /**
183          * Add monitor as another monitor that
184          *
185          * @param monitor
186          */

187         void addProgressListener(IProgressMonitorWithBlocking monitor) {
188             listener = monitor;
189             JobInfo info = getJobInfo(job);
190             TaskInfo currentTask = info.getTaskInfo();
191             if (currentTask != null) {
192                 listener.beginTask(currentTaskName, currentTask.totalWork);
193                 listener.internalWorked(currentTask.preWork);
194             }
195         }
196
197         /*
198          * (non-Javadoc)
199          *
200          * @see org.eclipse.core.runtime.IProgressMonitor#beginTask(java.lang.String,
201          * int)
202          */

203         public void beginTask(String JavaDoc taskName, int totalWork) {
204             JobInfo info = getJobInfo(job);
205             info.beginTask(taskName, totalWork);
206             refreshJobInfo(info);
207             currentTaskName = taskName;
208             if (listener != null) {
209                 listener.beginTask(taskName, totalWork);
210             }
211         }
212
213         /*
214          * (non-Javadoc)
215          *
216          * @see org.eclipse.core.runtime.IProgressMonitor#done()
217          */

218         public void done() {
219             JobInfo info = getJobInfo(job);
220             info.clearTaskInfo();
221             info.clearChildren();
222             runnableMonitors.remove(job);
223             if (listener != null) {
224                 listener.done();
225             }
226         }
227
228         /*
229          * (non-Javadoc)
230          *
231          * @see org.eclipse.core.runtime.IProgressMonitor#internalWorked(double)
232          */

233         public void internalWorked(double work) {
234             JobInfo info = getJobInfo(job);
235             if (info.hasTaskInfo()) {
236                 info.addWork(work);
237                 refreshJobInfo(info);
238             }
239             if (listener != null) {
240                 listener.internalWorked(work);
241             }
242         }
243
244         /*
245          * (non-Javadoc)
246          *
247          * @see org.eclipse.core.runtime.IProgressMonitor#isCanceled()
248          */

249         public boolean isCanceled() {
250             // Use the internal get so we don't create a Job Info for
251
// a job that is not running (see bug 149857)
252
JobInfo info = internalGetJobInfo(job);
253             if (info == null)
254                 return false;
255             return info.isCanceled();
256         }
257
258         /*
259          * (non-Javadoc)
260          *
261          * @see org.eclipse.core.runtime.IProgressMonitor#setCanceled(boolean)
262          */

263         public void setCanceled(boolean value) {
264             JobInfo info = getJobInfo(job);
265             // Don't bother cancelling twice
266
if (value && !info.isCanceled()) {
267                 info.cancel();
268                 // Only inform the first time
269
if (listener != null) {
270                     listener.setCanceled(value);
271                 }
272             }
273         }
274
275         /*
276          * (non-Javadoc)
277          *
278          * @see org.eclipse.core.runtime.IProgressMonitor#setTaskName(java.lang.String)
279          */

280         public void setTaskName(String JavaDoc taskName) {
281             JobInfo info = getJobInfo(job);
282             if (info.hasTaskInfo()) {
283                 info.setTaskName(taskName);
284             } else {
285                 beginTask(taskName, 100);
286                 return;
287             }
288             info.clearChildren();
289             refreshJobInfo(info);
290             currentTaskName = taskName;
291             if (listener != null) {
292                 listener.setTaskName(taskName);
293             }
294         }
295
296         /*
297          * (non-Javadoc)
298          *
299          * @see org.eclipse.core.runtime.IProgressMonitor#subTask(java.lang.String)
300          */

301         public void subTask(String JavaDoc name) {
302             if (name == null) {
303                 return;
304             }
305             JobInfo info = getJobInfo(job);
306             info.clearChildren();
307             info.addSubTask(name);
308             refreshJobInfo(info);
309             if (listener != null) {
310                 listener.subTask(name);
311             }
312         }
313
314         /*
315          * (non-Javadoc)
316          *
317          * @see org.eclipse.core.runtime.IProgressMonitor#worked(int)
318          */

319         public void worked(int work) {
320             internalWorked(work);
321         }
322
323         /*
324          * (non-Javadoc)
325          *
326          * @see org.eclipse.core.runtime.IProgressMonitorWithBlocking#clearBlocked()
327          */

328         public void clearBlocked() {
329             JobInfo info = getJobInfo(job);
330             info.setBlockedStatus(null);
331             refreshJobInfo(info);
332             if (listener != null) {
333                 listener.clearBlocked();
334             }
335         }
336
337         /*
338          * (non-Javadoc)
339          *
340          * @see org.eclipse.core.runtime.IProgressMonitorWithBlocking#setBlocked(org.eclipse.core.runtime.IStatus)
341          */

342         public void setBlocked(IStatus reason) {
343             JobInfo info = getJobInfo(job);
344             info.setBlockedStatus(null);
345             refreshJobInfo(info);
346             if (listener != null) {
347                 listener.setBlocked(reason);
348             }
349         }
350     }
351
352     /**
353      * Create a new instance of the receiver.
354      */

355     ProgressManager() {
356         Job.getJobManager().setProgressProvider(this);
357         Dialog.setBlockedHandler(new WorkbenchDialogBlockedHandler());
358         createChangeListener();
359         Job.getJobManager().addJobChangeListener(this.changeListener);
360         URL JavaDoc iconsRoot = ProgressManagerUtil.getIconsRoot();
361         try {
362             setUpImage(iconsRoot, SLEEPING_JOB, SLEEPING_JOB_KEY);
363             setUpImage(iconsRoot, WAITING_JOB, WAITING_JOB_KEY);
364             setUpImage(iconsRoot, BLOCKED_JOB, BLOCKED_JOB_KEY);
365
366             // Let the error manager set up its own icons
367
setUpImages(iconsRoot);
368         } catch (MalformedURLException JavaDoc e) {
369             ProgressManagerUtil.logException(e);
370         }
371     }
372
373     /**
374      * Set up any images the error management needs.
375      *
376      * @param iconsRoot
377      * @throws MalformedURLException
378      */

379     void setUpImages(URL JavaDoc iconsRoot) throws MalformedURLException JavaDoc {
380         // TODO see ErrorNotificationManager - this method isn't currently used
381
// In the ErrorNotificationManager it is invoked by ProgressManager
382
JFaceResources.getImageRegistry().put(ERROR_JOB_KEY,
383                 ImageDescriptor.createFromURL(new URL JavaDoc(iconsRoot, ERROR_JOB)));
384     }
385
386     /**
387      * Create the IJobChangeListener registered with the Job manager.
388      */

389     private void createChangeListener() {
390         changeListener = new JobChangeAdapter() {
391
392             /*
393              * (non-Javadoc)
394              *
395              * @see org.eclipse.core.runtime.jobs.JobChangeAdapter#aboutToRun(org.eclipse.core.runtime.jobs.IJobChangeEvent)
396              */

397             public void aboutToRun(IJobChangeEvent event) {
398                 JobInfo info = getJobInfo(event.getJob());
399                 refreshJobInfo(info);
400                 Iterator JavaDoc startListeners = busyListenersForJob(event.getJob())
401                         .iterator();
402                 while (startListeners.hasNext()) {
403                     IJobBusyListener next = (IJobBusyListener) startListeners
404                             .next();
405                     next.incrementBusy(event.getJob());
406                 }
407             }
408
409             /*
410              * (non-Javadoc)
411              *
412              * @see org.eclipse.core.runtime.jobs.JobChangeAdapter#done(org.eclipse.core.runtime.jobs.IJobChangeEvent)
413              */

414             public void done(IJobChangeEvent event) {
415                 if (!PlatformUI.isWorkbenchRunning()) {
416                     return;
417                 }
418                 Iterator JavaDoc startListeners = busyListenersForJob(event.getJob())
419                         .iterator();
420                 while (startListeners.hasNext()) {
421                     IJobBusyListener next = (IJobBusyListener) startListeners
422                             .next();
423                     next.decrementBusy(event.getJob());
424                 }
425
426                 final JobInfo info = getJobInfo(event.getJob());
427                 removeJobInfo(info);
428
429                 if (event.getResult() != null
430                         && event.getResult().getSeverity() == IStatus.ERROR) {
431                     StatusAdapter statusAdapter = new StatusAdapter(event
432                             .getResult());
433                     statusAdapter.addAdapter(Job.class, event.getJob());
434
435                     if (event
436                             .getJob()
437                             .getProperty(
438                                     IProgressConstants.NO_IMMEDIATE_ERROR_PROMPT_PROPERTY) == Boolean.TRUE) {
439                         statusAdapter
440                                 .setProperty(
441                                         IProgressConstants.NO_IMMEDIATE_ERROR_PROMPT_PROPERTY,
442                                         Boolean.TRUE);
443                         StatusAdapterHelper.getInstance().putStatusAdapter(
444                                 info, statusAdapter);
445                     }
446
447                     StatusManager.getManager().handle(statusAdapter,
448                             StatusManager.SHOW);
449                 }
450             }
451
452             /*
453              * (non-Javadoc)
454              *
455              * @see org.eclipse.core.runtime.jobs.JobChangeAdapter#scheduled(org.eclipse.core.runtime.jobs.IJobChangeEvent)
456              */

457             public void scheduled(IJobChangeEvent event) {
458                 updateFor(event);
459                 if (event.getJob().isUser()) {
460                     boolean noDialog = shouldRunInBackground();
461                     if (!noDialog) {
462                         final IJobChangeEvent finalEvent = event;
463                         WorkbenchJob showJob = new WorkbenchJob(
464                                 ProgressMessages.ProgressManager_showInDialogName) {
465                             /*
466                              * (non-Javadoc)
467                              *
468                              * @see org.eclipse.ui.progress.UIJob#runInUIThread(org.eclipse.core.runtime.IProgressMonitor)
469                              */

470                             public IStatus runInUIThread(
471                                     IProgressMonitor monitor) {
472                                 showInDialog(null, finalEvent.getJob());
473                                 return Status.OK_STATUS;
474                             }
475                         };
476                         showJob.setSystem(true);
477                         showJob.schedule();
478                         return;
479                     }
480                 }
481             }
482
483             /**
484              * Update the listeners for the receiver for the event.
485              *
486              * @param event
487              */

488             private void updateFor(IJobChangeEvent event) {
489                 if (isNeverDisplayedJob(event.getJob())) {
490                     return;
491                 }
492                 if (jobs.containsKey(event.getJob())) {
493                     refreshJobInfo(getJobInfo(event.getJob()));
494                 } else {
495                     addJobInfo(new JobInfo(event.getJob()));
496                 }
497             }
498
499             /*
500              * (non-Javadoc)
501              *
502              * @see org.eclipse.core.runtime.jobs.JobChangeAdapter#awake(org.eclipse.core.runtime.jobs.IJobChangeEvent)
503              */

504             public void awake(IJobChangeEvent event) {
505                 updateFor(event);
506             }
507
508             /*
509              * (non-Javadoc)
510              *
511              * @see org.eclipse.core.runtime.jobs.JobChangeAdapter#sleeping(org.eclipse.core.runtime.jobs.IJobChangeEvent)
512              */

513             public void sleeping(IJobChangeEvent event) {
514                 updateFor(event);
515             }
516         };
517     }
518
519     /**
520      * Set up the image in the image regsitry.
521      *
522      * @param iconsRoot
523      * @param fileName
524      * @param key
525      * @throws MalformedURLException
526      */

527     private void setUpImage(URL JavaDoc iconsRoot, String JavaDoc fileName, String JavaDoc key)
528             throws MalformedURLException JavaDoc {
529         JFaceResources.getImageRegistry().put(key,
530                 ImageDescriptor.createFromURL(new URL JavaDoc(iconsRoot, fileName)));
531     }
532
533     /*
534      * (non-Javadoc)
535      *
536      * @see org.eclipse.core.runtime.jobs.ProgressProvider#createMonitor(org.eclipse.core.runtime.jobs.Job)
537      */

538     public IProgressMonitor createMonitor(Job job) {
539         return progressFor(job);
540     }
541
542     /*
543      * (non-Javadoc)
544      *
545      * @see org.eclipse.core.runtime.jobs.ProgressProvider#getDefaultMonitor()
546      */

547     public IProgressMonitor getDefaultMonitor() {
548         // only need a default monitor for operations the UI thread
549
// and only if there is a display
550
Display display;
551         if (PlatformUI.isWorkbenchRunning()
552                 && !((Workbench) PlatformUI.getWorkbench()).isStarting()) {
553             display = PlatformUI.getWorkbench().getDisplay();
554             if (!display.isDisposed()
555                     && (display.getThread() == Thread.currentThread())) {
556                 return new EventLoopProgressMonitor(new NullProgressMonitor());
557             }
558         }
559         return super.getDefaultMonitor();
560     }
561
562     /**
563      * Return a monitor for the job. Check if we cached a monitor for this job
564      * previously for a long operation timeout check.
565      *
566      * @param job
567      * @return IProgressMonitor
568      */

569     public JobMonitor progressFor(Job job) {
570
571         synchronized (monitorKey) {
572             if (runnableMonitors.containsKey(job)) {
573                 return (JobMonitor) runnableMonitors.get(job);
574             }
575             JobMonitor monitor = new JobMonitor(job);
576             runnableMonitors.put(job, monitor);
577             return monitor;
578         }
579
580     }
581
582     /**
583      * Add an IJobProgressManagerListener to listen to the changes.
584      *
585      * @param listener
586      */

587     void addListener(IJobProgressManagerListener listener) {
588
589         synchronized (listenersKey) {
590             ArrayList JavaDoc newListeners = new ArrayList JavaDoc(listeners.length + 1);
591             for (int i = 0; i < listeners.length; i++) {
592                 newListeners.add(listeners[i]);
593             }
594             newListeners.add(listener);
595             listeners = new IJobProgressManagerListener[newListeners.size()];
596             newListeners.toArray(listeners);
597         }
598
599     }
600
601     /**
602      * Remove the supplied IJobProgressManagerListener from the list of
603      * listeners.
604      *
605      * @param listener
606      */

607     void removeListener(IJobProgressManagerListener listener) {
608         synchronized (listenersKey) {
609             ArrayList JavaDoc newListeners = new ArrayList JavaDoc();
610             for (int i = 0; i < listeners.length; i++) {
611                 if (listeners[i].equals(listener)) {
612                     continue;
613                 }
614                 newListeners.add(listeners[i]);
615             }
616             listeners = new IJobProgressManagerListener[newListeners.size()];
617             newListeners.toArray(listeners);
618         }
619     }
620
621     /**
622      * Get the JobInfo for the job. If it does not exist create it.
623      *
624      * @param job
625      * @return JobInfo
626      */

627     JobInfo getJobInfo(Job job) {
628         JobInfo info = internalGetJobInfo(job);
629         if (info == null) {
630             info = new JobInfo(job);
631             jobs.put(job, info);
632         }
633         return info;
634     }
635
636     /**
637      * Return an existing job info for the given Job or <code>null</code> if
638      * there isn't one.
639      *
640      * @param job
641      * @return JobInfo
642      */

643     JobInfo internalGetJobInfo(Job job) {
644         return (JobInfo) jobs.get(job);
645     }
646
647     /**
648      * Refresh the IJobProgressManagerListeners as a result of a change in info.
649      *
650      * @param info
651      */

652     public void refreshJobInfo(JobInfo info) {
653         GroupInfo group = info.getGroupInfo();
654         if (group != null) {
655             refreshGroup(group);
656         }
657
658         synchronized (listenersKey) {
659             for (int i = 0; i < listeners.length; i++) {
660                 IJobProgressManagerListener listener = listeners[i];
661                 if (!isNonDisplayableJob(info.getJob(), listener.showsDebug())) {
662                     listener.refreshJobInfo(info);
663                 }
664             }
665         }
666     }
667
668     /**
669      * Refresh the IJobProgressManagerListeners as a result of a change in info.
670      *
671      * @param info
672      */

673     public void refreshGroup(GroupInfo info) {
674
675         synchronized (listenersKey) {
676             for (int i = 0; i < listeners.length; i++) {
677                 listeners[i].refreshGroup(info);
678             }
679         }
680     }
681
682     /**
683      * Refresh all the IJobProgressManagerListener as a result of a change in
684      * the whole model.
685      */

686     public void refreshAll() {
687
688         pruneStaleJobs();
689         synchronized (listenersKey) {
690             for (int i = 0; i < listeners.length; i++) {
691                 listeners[i].refreshAll();
692             }
693         }
694
695     }
696
697     /**
698      * Refresh the content providers as a result of a deletion of info.
699      *
700      * @param info
701      * JobInfo
702      */

703     public void removeJobInfo(JobInfo info) {
704
705         Job job = info.getJob();
706         jobs.remove(job);
707         synchronized (monitorKey) {
708             if (runnableMonitors.containsKey(job)) {
709                 runnableMonitors.remove(job);
710             }
711         }
712
713         synchronized (listenersKey) {
714             for (int i = 0; i < listeners.length; i++) {
715                 IJobProgressManagerListener listener = listeners[i];
716                 if (!isNonDisplayableJob(info.getJob(), listener.showsDebug())) {
717                     listener.removeJob(info);
718                 }
719             }
720         }
721
722     }
723
724     /**
725      * Remove the group from the roots and inform the listeners.
726      *
727      * @param group
728      * GroupInfo
729      */

730     public void removeGroup(GroupInfo group) {
731
732         synchronized (listenersKey) {
733             for (int i = 0; i < listeners.length; i++) {
734                 listeners[i].removeGroup(group);
735             }
736         }
737     }
738
739     /**
740      * Refresh the content providers as a result of an addition of info.
741      *
742      * @param info
743      */

744     public void addJobInfo(JobInfo info) {
745         GroupInfo group = info.getGroupInfo();
746         if (group != null) {
747             refreshGroup(group);
748         }
749
750         jobs.put(info.getJob(), info);
751         synchronized (listenersKey) {
752             for (int i = 0; i < listeners.length; i++) {
753                 IJobProgressManagerListener listener = listeners[i];
754                 if (!isNonDisplayableJob(info.getJob(), listener.showsDebug())) {
755                     listener.addJob(info);
756                 }
757             }
758         }
759     }
760
761     /**
762      * Return whether or not this job is currently displayable.
763      *
764      * @param job
765      * @param debug
766      * If the listener is in debug mode.
767      * @return boolean <code>true</code> if the job is not displayed.
768      */

769     boolean isNonDisplayableJob(Job job, boolean debug) {
770         if (isNeverDisplayedJob(job)) {
771             return true;
772         }
773         if (debug) {
774             return false;
775         }
776         return job.isSystem() || job.getState() == Job.SLEEPING;
777     }
778
779     /**
780      * Return whether or not this job is ever displayable.
781      *
782      * @param job
783      * @return boolean <code>true</code> if it is never displayed.
784      */

785     private boolean isNeverDisplayedJob(Job job) {
786         if (Policy.DEBUG_SHOW_ALL_JOBS)
787             return false;
788         return job.getProperty(ProgressManagerUtil.INFRASTRUCTURE_PROPERTY) != null;
789     }
790
791     /**
792      * Return the current job infos filtered on debug mode.
793      *
794      * @param debug
795      * @return JobInfo[]
796      */

797     public JobInfo[] getJobInfos(boolean debug) {
798         synchronized (jobs) {
799             Iterator JavaDoc iterator = jobs.keySet().iterator();
800             Collection JavaDoc result = new ArrayList JavaDoc();
801             while (iterator.hasNext()) {
802                 Job next = (Job) iterator.next();
803                 if (!isNonDisplayableJob(next, debug)) {
804                     result.add(jobs.get(next));
805                 }
806             }
807             JobInfo[] infos = new JobInfo[result.size()];
808             result.toArray(infos);
809             return infos;
810         }
811     }
812
813     /**
814      * Return the current root elements filtered on the debug mode.
815      *
816      * @param debug
817      * @return JobTreeElement[]
818      */

819     public JobTreeElement[] getRootElements(boolean debug) {
820         synchronized (jobs) {
821             Iterator JavaDoc iterator = jobs.keySet().iterator();
822             Collection JavaDoc result = new HashSet JavaDoc();
823             while (iterator.hasNext()) {
824                 Job next = (Job) iterator.next();
825                 if (!isNonDisplayableJob(next, debug)) {
826                     JobInfo jobInfo = (JobInfo) jobs.get(next);
827                     GroupInfo group = jobInfo.getGroupInfo();
828                     if (group == null) {
829                         result.add(jobInfo);
830                     } else {
831                         result.add(group);
832                     }
833                 }
834             }
835             JobTreeElement[] infos = new JobTreeElement[result.size()];
836             result.toArray(infos);
837             return infos;
838         }
839     }
840
841     /**
842      * Return whether or not there are any jobs being displayed.
843      *
844      * @return boolean
845      */

846     public boolean hasJobInfos() {
847         synchronized (jobs) {
848             Iterator JavaDoc iterator = jobs.keySet().iterator();
849             while (iterator.hasNext()) {
850                 return true;
851             }
852             return false;
853         }
854     }
855
856     /**
857      * Returns the image descriptor with the given relative path.
858      *
859      * @param source
860      * @return Image
861      */

862     Image getImage(ImageData source) {
863         ImageData mask = source.getTransparencyMask();
864         return new Image(null, source, mask);
865     }
866
867     /**
868      * Returns the image descriptor with the given relative path.
869      *
870      * @param fileSystemPath
871      * The URL for the file system to the image.
872      * @param loader -
873      * the loader used to get this data
874      * @return ImageData[]
875      */

876     ImageData[] getImageData(URL JavaDoc fileSystemPath, ImageLoader loader) {
877         try {
878             InputStream JavaDoc stream = fileSystemPath.openStream();
879             ImageData[] result = loader.load(stream);
880             stream.close();
881             return result;
882         } catch (FileNotFoundException JavaDoc exception) {
883             ProgressManagerUtil.logException(exception);
884             return null;
885         } catch (IOException JavaDoc exception) {
886             ProgressManagerUtil.logException(exception);
887             return null;
888         }
889     }
890
891     /*
892      * (non-Javadoc)
893      *
894      * @see org.eclipse.ui.progress.IProgressService#busyCursorWhile(org.eclipse.jface.operation.IRunnableWithProgress)
895      */

896     public void busyCursorWhile(final IRunnableWithProgress runnable)
897             throws InvocationTargetException JavaDoc, InterruptedException JavaDoc {
898         final ProgressMonitorJobsDialog dialog = new ProgressMonitorJobsDialog(
899                 ProgressManagerUtil.getDefaultParent());
900         dialog.setOpenOnRun(false);
901         final InvocationTargetException JavaDoc[] invokes = new InvocationTargetException JavaDoc[1];
902         final InterruptedException JavaDoc[] interrupt = new InterruptedException JavaDoc[1];
903         // show a busy cursor until the dialog opens
904
Runnable JavaDoc dialogWaitRunnable = new Runnable JavaDoc() {
905             public void run() {
906                 try {
907                     dialog.setOpenOnRun(false);
908                     setUserInterfaceActive(false);
909                     dialog.run(true, true, runnable);
910                 } catch (InvocationTargetException JavaDoc e) {
911                     invokes[0] = e;
912                 } catch (InterruptedException JavaDoc e) {
913                     interrupt[0] = e;
914                 } finally {
915                     setUserInterfaceActive(true);
916                 }
917             }
918         };
919         busyCursorWhile(dialogWaitRunnable, dialog);
920         if (invokes[0] != null) {
921             throw invokes[0];
922         }
923         if (interrupt[0] != null) {
924             throw interrupt[0];
925         }
926     }
927
928     /**
929      * Show the busy cursor while the runnable is running. Schedule a job to
930      * replace it with a progress dialog.
931      *
932      * @param dialogWaitRunnable
933      * @param dialog
934      */

935     private void busyCursorWhile(Runnable JavaDoc dialogWaitRunnable,
936             ProgressMonitorJobsDialog dialog) {
937         // create the job that will open the dialog after a delay
938
scheduleProgressMonitorJob(dialog);
939         final Display display = PlatformUI.getWorkbench().getDisplay();
940         if (display == null) {
941             return;
942         }
943         // show a busy cursor until the dialog opens
944
BusyIndicator.showWhile(display, dialogWaitRunnable);
945     }
946
947     /**
948      * Schedule the job that will open the progress monitor dialog
949      *
950      * @param dialog
951      * the dialog to open
952      */

953     private void scheduleProgressMonitorJob(
954             final ProgressMonitorJobsDialog dialog) {
955
956         final WorkbenchJob updateJob = new WorkbenchJob(
957                 ProgressMessages.ProgressManager_openJobName) {
958             /*
959              * (non-Javadoc)
960              *
961              * @see org.eclipse.ui.progress.UIJob#runInUIThread(org.eclipse.core.runtime.IProgressMonitor)
962              */

963             public IStatus runInUIThread(IProgressMonitor monitor) {
964                 setUserInterfaceActive(true);
965                 if (ProgressManagerUtil.safeToOpen(dialog, null)) {
966                     dialog.open();
967                 }
968                 return Status.OK_STATUS;
969             }
970         };
971         updateJob.setSystem(true);
972         updateJob.schedule(getLongOperationTime());
973
974     }
975
976     /**
977      * Shutdown the receiver.
978      */

979     private void shutdown() {
980         synchronized (listenersKey) {
981             this.listeners = new IJobProgressManagerListener[0];
982         }
983         Job.getJobManager().setProgressProvider(null);
984         Job.getJobManager().removeJobChangeListener(this.changeListener);
985     }
986
987     /*
988      * (non-Javadoc)
989      *
990      * @see org.eclipse.core.runtime.jobs.ProgressProvider#createProgressGroup()
991      */

992     public IProgressMonitor createProgressGroup() {
993         return new GroupInfo();
994     }
995
996     /*
997      * (non-Javadoc)
998      *
999      * @see org.eclipse.core.runtime.jobs.ProgressProvider#createMonitor(org.eclipse.core.runtime.jobs.Job,
1000     * org.eclipse.core.runtime.IProgressMonitor, int)
1001     */

1002    public IProgressMonitor createMonitor(Job job, IProgressMonitor group,
1003            int ticks) {
1004        JobMonitor monitor = progressFor(job);
1005        if (group instanceof GroupInfo) {
1006            GroupInfo groupInfo = (GroupInfo) group;
1007            JobInfo jobInfo = getJobInfo(job);
1008            jobInfo.setGroupInfo(groupInfo);
1009            jobInfo.setTicks(ticks);
1010            groupInfo.addJobInfo(jobInfo);
1011        }
1012        return monitor;
1013    }
1014
1015    /**
1016     * Add the listener to the family.
1017     *
1018     * @param family
1019     * @param listener
1020     */

1021    void addListenerToFamily(Object JavaDoc family, IJobBusyListener listener) {
1022        synchronized (familyKey) {
1023            Collection JavaDoc currentListeners;
1024            if (familyListeners.containsKey(family)) {
1025                currentListeners = (Collection JavaDoc) familyListeners.get(family);
1026            } else {
1027                currentListeners = new HashSet JavaDoc();
1028            }
1029            currentListeners.add(listener);
1030            familyListeners.put(family, currentListeners);
1031        }
1032    }
1033
1034    /**
1035     * Remove the listener from all families.
1036     *
1037     * @param listener
1038     */

1039    void removeListener(IJobBusyListener listener) {
1040        synchronized (familyKey) {
1041            Collection JavaDoc keysToRemove = new HashSet JavaDoc();
1042            Iterator JavaDoc families = familyListeners.keySet().iterator();
1043            while (families.hasNext()) {
1044                Object JavaDoc next = families.next();
1045                Collection JavaDoc currentListeners = (Collection JavaDoc) familyListeners
1046                        .get(next);
1047                if (currentListeners.contains(listener)) {
1048                    currentListeners.remove(listener);
1049                }
1050                if (currentListeners.isEmpty()) {
1051                    keysToRemove.add(next);
1052                } else {
1053                    familyListeners.put(next, currentListeners);
1054                }
1055            }
1056            // Remove any empty listeners
1057
Iterator JavaDoc keysIterator = keysToRemove.iterator();
1058            while (keysIterator.hasNext()) {
1059                familyListeners.remove(keysIterator.next());
1060            }
1061        }
1062    }
1063
1064    /**
1065     * Return the listeners for the job.
1066     *
1067     * @param job
1068     * @return Collection of IJobBusyListener
1069     */

1070    private Collection JavaDoc busyListenersForJob(Job job) {
1071        if (job.isSystem()) {
1072            return Collections.EMPTY_LIST;
1073        }
1074        synchronized (familyKey) {
1075
1076            if (familyListeners.isEmpty()) {
1077                return Collections.EMPTY_LIST;
1078            }
1079
1080            Iterator JavaDoc families = familyListeners.keySet().iterator();
1081            Collection JavaDoc returnValue = new ArrayList JavaDoc();
1082            while (families.hasNext()) {
1083                Object JavaDoc next = families.next();
1084                if (job.belongsTo(next)) {
1085                    Collection JavaDoc currentListeners = (Collection JavaDoc) familyListeners
1086                            .get(next);
1087                    returnValue.addAll(currentListeners);
1088                }
1089            }
1090            return returnValue;
1091        }
1092    }
1093
1094    /*
1095     * (non-Javadoc)
1096     *
1097     * @see org.eclipse.ui.progress.IProgressService#showInDialog(org.eclipse.swt.widgets.Shell,
1098     * org.eclipse.core.runtime.jobs.Job)
1099     */

1100    public void showInDialog(Shell shell, Job job) {
1101        if (shouldRunInBackground()) {
1102            return;
1103        }
1104
1105        final ProgressMonitorFocusJobDialog dialog = new ProgressMonitorFocusJobDialog(
1106                shell);
1107        dialog.show(job, shell);
1108    }
1109
1110    /*
1111     * (non-Javadoc)
1112     *
1113     * @see org.eclipse.jface.operation.IRunnableContext#run(boolean, boolean,
1114     * org.eclipse.jface.operation.IRunnableWithProgress)
1115     */

1116    public void run(boolean fork, boolean cancelable,
1117            IRunnableWithProgress runnable) throws InvocationTargetException JavaDoc,
1118            InterruptedException JavaDoc {
1119        if (fork == false || cancelable == false) {
1120            // backward compatible code
1121
final ProgressMonitorJobsDialog dialog = new ProgressMonitorJobsDialog(
1122                    null);
1123            dialog.run(fork, cancelable, runnable);
1124            return;
1125        }
1126
1127        busyCursorWhile(runnable);
1128    }
1129
1130    /*
1131     * (non-Javadoc)
1132     *
1133     * @see org.eclipse.ui.progress.IProgressService#runInUI(org.eclipse.jface.operation.IRunnableWithProgress,
1134     * org.eclipse.core.runtime.jobs.ISchedulingRule)
1135     */

1136    public void runInUI(final IRunnableContext context,
1137            final IRunnableWithProgress runnable, final ISchedulingRule rule)
1138            throws InvocationTargetException JavaDoc, InterruptedException JavaDoc {
1139        final IJobManager manager = Job.getJobManager();
1140        final InvocationTargetException JavaDoc[] exception = new InvocationTargetException JavaDoc[1];
1141        final InterruptedException JavaDoc[] canceled = new InterruptedException JavaDoc[1];
1142        BusyIndicator.showWhile(Display.getDefault(), new Runnable JavaDoc() {
1143            public void run() {
1144                try {
1145                    manager.beginRule(rule,
1146                            ((Workbench) PlatformUI.getWorkbench())
1147                                    .isStarting() ? new NullProgressMonitor()
1148                                    : getEventLoopMonitor());
1149                    context.run(false, false, runnable);
1150                } catch (InvocationTargetException JavaDoc e) {
1151                    exception[0] = e;
1152                } catch (InterruptedException JavaDoc e) {
1153                    canceled[0] = e;
1154                } catch (OperationCanceledException e) {
1155                    canceled[0] = new InterruptedException JavaDoc(e.getMessage());
1156                } finally {
1157                    manager.endRule(rule);
1158                }
1159            }
1160
1161            /**
1162             * Get a progress monitor that forwards to an event loop monitor.
1163             * Override #setBlocked() so that we always open the blocked dialog.
1164             *
1165             * @return the monitor on the event loop
1166             */

1167            private IProgressMonitor getEventLoopMonitor() {
1168                return new EventLoopProgressMonitor(new NullProgressMonitor()) {
1169                    /*
1170                     * (non-Javadoc)
1171                     *
1172                     * @see org.eclipse.ui.internal.dialogs.EventLoopProgressMonitor#setBlocked(org.eclipse.core.runtime.IStatus)
1173                     */

1174                    public void setBlocked(IStatus reason) {
1175
1176                        // Set a shell to open with as we want to create this
1177
// even if there is a modal shell.
1178
Dialog.getBlockedHandler().showBlocked(
1179                                ProgressManagerUtil.getDefaultParent(), this,
1180                                reason, getTaskName());
1181                    }
1182                };
1183            }
1184        });
1185        if (exception[0] != null) {
1186            throw exception[0];
1187        }
1188        if (canceled[0] != null) {
1189            throw canceled[0];
1190        }
1191    }
1192
1193    /*
1194     * (non-Javadoc)
1195     *
1196     * @see org.eclipse.ui.progress.IProgressService#getLongOperationTime()
1197     */

1198    public int getLongOperationTime() {
1199        return 800;
1200    }
1201
1202    /*
1203     * (non-Javadoc)
1204     *
1205     * @see org.eclipse.ui.progress.IProgressService#registerIconForFamily(org.eclipse.jface.resource.ImageDescriptor,
1206     * java.lang.Object)
1207     */

1208    public void registerIconForFamily(ImageDescriptor icon, Object JavaDoc family) {
1209        String JavaDoc key = IMAGE_KEY + String.valueOf(imageKeyTable.size());
1210        imageKeyTable.put(family, key);
1211        ImageRegistry registry = JFaceResources.getImageRegistry();
1212
1213        // Avoid registering twice
1214
if (registry.getDescriptor(key) == null) {
1215            registry.put(key, icon);
1216        }
1217
1218    }
1219
1220    /*
1221     * (non-Javadoc)
1222     *
1223     * @see org.eclipse.ui.progress.IProgressService#getIconFor(org.eclipse.core.runtime.jobs.Job)
1224     */

1225    public Image getIconFor(Job job) {
1226        Enumeration JavaDoc families = imageKeyTable.keys();
1227        while (families.hasMoreElements()) {
1228            Object JavaDoc next = families.nextElement();
1229            if (job.belongsTo(next)) {
1230                return JFaceResources.getImageRegistry().get(
1231                        (String JavaDoc) imageKeyTable.get(next));
1232            }
1233        }
1234        return null;
1235    }
1236
1237    /**
1238     * Iterate through all of the windows and set them to be disabled or enabled
1239     * as appropriate.'
1240     *
1241     * @param active
1242     * The set the windows will be set to.
1243     */

1244    private void setUserInterfaceActive(boolean active) {
1245        IWorkbench workbench = PlatformUI.getWorkbench();
1246        Shell[] shells = workbench.getDisplay().getShells();
1247        if (active) {
1248            for (int i = 0; i < shells.length; i++) {
1249                shells[i].setEnabled(active);
1250            }
1251        } else {
1252            // Deactive shells in reverse order
1253
for (int i = shells.length - 1; i >= 0; i--) {
1254                shells[i].setEnabled(active);
1255            }
1256        }
1257    }
1258
1259    /**
1260     * Check to see if there are any stale jobs we have not cleared out.
1261     *
1262     * @return <code>true</code> if anything was pruned
1263     */

1264    private boolean pruneStaleJobs() {
1265        Object JavaDoc[] jobsToCheck = jobs.keySet().toArray();
1266        boolean pruned = false;
1267        for (int i = 0; i < jobsToCheck.length; i++) {
1268            Job job = (Job) jobsToCheck[i];
1269            if (checkForStaleness(job)) {
1270                if (Policy.DEBUG_STALE_JOBS) {
1271                    WorkbenchPlugin.log("Stale Job " + job.getName()); //$NON-NLS-1$
1272
}
1273                pruned = true;
1274            }
1275        }
1276
1277        return pruned;
1278    }
1279
1280    /**
1281     * Check the if the job should be removed from the list as it may be stale.
1282     *
1283     * @param job
1284     * @return boolean
1285     */

1286    boolean checkForStaleness(Job job) {
1287        if (job.getState() == Job.NONE) {
1288            removeJobInfo(getJobInfo(job));
1289            return true;
1290        }
1291        return false;
1292    }
1293
1294    /**
1295     * Return whether or not dialogs should be run in the background
1296     *
1297     * @return <code>true</code> if the dialog should not be shown.
1298     */

1299    private boolean shouldRunInBackground() {
1300        return WorkbenchPlugin.getDefault().getPreferenceStore().getBoolean(
1301                IPreferenceConstants.RUN_IN_BACKGROUND);
1302    }
1303
1304    /**
1305     * Set whether or not the ProgressViewUpdater should show system jobs.
1306     *
1307     * @param showSystem
1308     */

1309    public void setShowSystemJobs(boolean showSystem) {
1310        ProgressViewUpdater updater = ProgressViewUpdater.getSingleton();
1311        updater.debug = showSystem;
1312        updater.refreshAll();
1313
1314    }
1315}
1316
Popular Tags