/*******************************************************************************
 * Copyright (c) 2003, 2005 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.ui.internal.progress;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.InvocationTargetException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.Map;

import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IProgressMonitorWithBlocking;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.QualifiedName;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.IJobChangeEvent;
import org.eclipse.core.runtime.jobs.IJobChangeListener;
import org.eclipse.core.runtime.jobs.IJobManager;
import org.eclipse.core.runtime.jobs.ISchedulingRule;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.core.runtime.jobs.JobChangeAdapter;
import org.eclipse.core.runtime.jobs.ProgressProvider;
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.operation.IRunnableContext;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.resource.ImageRegistry;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.swt.custom.BusyIndicator;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.ImageData;
import org.eclipse.swt.graphics.ImageLoader;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.IWorkbench;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.internal.IPreferenceConstants;
import org.eclipse.ui.internal.Workbench;
import org.eclipse.ui.internal.WorkbenchPlugin;
import org.eclipse.ui.internal.dialogs.EventLoopProgressMonitor;
import org.eclipse.ui.internal.dialogs.WorkbenchDialogBlockedHandler;
import org.eclipse.ui.internal.misc.Policy;
import org.eclipse.ui.internal.util.BundleUtility;
import org.eclipse.ui.progress.IProgressConstants;
import org.eclipse.ui.progress.IProgressService;
import org.eclipse.ui.progress.WorkbenchJob;

/**
 * JobProgressManager provides the progress monitor to the job manager and
 * informs any ProgressContentProviders of changes.
 */
public class ProgressManager extends ProgressProvider implements
        IProgressService {
    /**
     * A property to determine if the job was run in the dialog.
     * Kept for backwards compatability.
     * @deprecated 
     * @see IProgressConstants#PROPERTY_IN_DIALOG
     */
    public static final QualifiedName PROPERTY_IN_DIALOG = IProgressConstants.PROPERTY_IN_DIALOG;
    
    private static ProgressManager singleton;

    final private Map jobs = Collections.synchronizedMap(new HashMap());

    final private Map familyListeners = Collections
            .synchronizedMap(new HashMap());

    final Object familyKey = new Object();

    private IJobProgressManagerListener[] listeners = new IJobProgressManagerListener[0];
    
    final Object listenersKey = new Object();

    final ErrorNotificationManager errorManager = new ErrorNotificationManager();

    IJobChangeListener changeListener;

    static final String PROGRESS_VIEW_NAME = "org.eclipse.ui.views.ProgressView"; //$NON-NLS-1$

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

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

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

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

    /**
     * The key for the sleeping job icon.
     */
    public static final String SLEEPING_JOB_KEY = "SLEEPING_JOB"; //$NON-NLS-1$

    /**
     * The key for the waiting job icon.
     */
    public static final String WAITING_JOB_KEY = "WAITING_JOB"; //$NON-NLS-1$

    /**
     * The key for the locked job icon.
     */
    public static final String BLOCKED_JOB_KEY = "LOCKED_JOB"; //$NON-NLS-1$

    final Map runnableMonitors = Collections.synchronizedMap(new HashMap());

    final Object monitorKey = new Object();
    
    FinishedJobs finishedJobs;

    //A table that maps families to keys in the Jface image
    //table
    private Hashtable imageKeyTable = new Hashtable();

    private static final String IMAGE_KEY = "org.eclipse.ui.progress.images"; //$NON-NLS-1$

    /**
     * Get the progress manager currently in use.
     * 
     * @return JobProgressManager
     */
    public static ProgressManager getInstance() {
        if (singleton == null) {
			singleton = new ProgressManager();
		}
        return singleton;
    }

    /**
     * Shutdown the singleton if there is one.
     */
    public static void shutdownProgressManager() {
        if (singleton == null) {
			return;
		}
        singleton.shutdown();
    }

    /**
     * The JobMonitor is the inner class that handles the IProgressMonitor
     * integration with the ProgressMonitor.
     */
    class JobMonitor implements IProgressMonitorWithBlocking {
        Job job;

        String currentTaskName;

        IProgressMonitorWithBlocking listener;

        /**
         * Create a monitor on the supplied job.
         * 
         * @param newJob
         */
        JobMonitor(Job newJob) {
            job = newJob;
        }

        /**
         * Add monitor as another monitor that
         * 
         * @param monitor
         */
        void addProgressListener(IProgressMonitorWithBlocking monitor) {
            listener = monitor;
            JobInfo info = getJobInfo(job);
            TaskInfo currentTask = info.getTaskInfo();
            if (currentTask != null) {
                listener.beginTask(currentTaskName, currentTask.totalWork);
                listener.internalWorked(currentTask.preWork);
            }
        }

        /*
         * (non-Javadoc)
         * 
         * @see org.eclipse.core.runtime.IProgressMonitor#beginTask(java.lang.String,
         *      int)
         */
        public void beginTask(String taskName, int totalWork) {
            JobInfo info = getJobInfo(job);
            info.beginTask(taskName, totalWork);
            refreshJobInfo(info);
            currentTaskName = taskName;
            if (listener != null) {
				listener.beginTask(taskName, totalWork);
			}
        }

        /*
         * (non-Javadoc)
         * 
         * @see org.eclipse.core.runtime.IProgressMonitor#done()
         */
        public void done() {
            JobInfo info = getJobInfo(job);
            info.clearTaskInfo();
            info.clearChildren();
            runnableMonitors.remove(job);
            if (listener != null) {
				listener.done();
			}
        }

        /*
         * (non-Javadoc)
         * 
         * @see org.eclipse.core.runtime.IProgressMonitor#internalWorked(double)
         */
        public void internalWorked(double work) {
            JobInfo info = getJobInfo(job);
            if (info.hasTaskInfo()) {
                info.addWork(work);
                refreshJobInfo(info);
            }
            if (listener != null) {
				listener.internalWorked(work);
			}
        }

        /*
         * (non-Javadoc)
         * 
         * @see org.eclipse.core.runtime.IProgressMonitor#isCanceled()
         */
        public boolean isCanceled() {
            JobInfo info = getJobInfo(job);
            return info.isCanceled();
        }

        /*
         * (non-Javadoc)
         * 
         * @see org.eclipse.core.runtime.IProgressMonitor#setCanceled(boolean)
         */
        public void setCanceled(boolean value) {
            JobInfo info = getJobInfo(job);
            //Don't bother cancelling twice
            if (value && !info.isCanceled()){
                info.cancel();
                //Only inform the first time
                if (listener != null) {
					listener.setCanceled(value);
				}
            }
        }

        /*
         * (non-Javadoc)
         * 
         * @see org.eclipse.core.runtime.IProgressMonitor#setTaskName(java.lang.String)
         */
        public void setTaskName(String taskName) {
            JobInfo info = getJobInfo(job);
            if (info.hasTaskInfo()) {
				info.setTaskName(taskName);
			} else {
                beginTask(taskName, 100);
                return;
            }
            info.clearChildren();
            refreshJobInfo(info);
            currentTaskName = taskName;
            if (listener != null) {
				listener.setTaskName(taskName);
			}
        }

        /*
         * (non-Javadoc)
         * 
         * @see org.eclipse.core.runtime.IProgressMonitor#subTask(java.lang.String)
         */
        public void subTask(String name) {
            if (name == null || name.length() == 0) {
				return;
			}
            JobInfo info = getJobInfo(job);
            info.clearChildren();
            info.addSubTask(name);
            refreshJobInfo(info);
            if (listener != null) {
				listener.subTask(name);
			}
        }

        /*
         * (non-Javadoc)
         * 
         * @see org.eclipse.core.runtime.IProgressMonitor#worked(int)
         */
        public void worked(int work) {
            internalWorked(work);
        }

        /*
         * (non-Javadoc)
         * 
         * @see org.eclipse.core.runtime.IProgressMonitorWithBlocking#clearBlocked()
         */
        public void clearBlocked() {
            JobInfo info = getJobInfo(job);
            info.setBlockedStatus(null);
            refreshJobInfo(info);
            if (listener != null) {
				listener.clearBlocked();
			}
        }

        /*
         * (non-Javadoc)
         * 
         * @see org.eclipse.core.runtime.IProgressMonitorWithBlocking#setBlocked(org.eclipse.core.runtime.IStatus)
         */
        public void setBlocked(IStatus reason) {
            JobInfo info = getJobInfo(job);
            info.setBlockedStatus(null);
            refreshJobInfo(info);
            if (listener != null) {
				listener.setBlocked(reason);
			}
        }
    }

    /**
     * Create a new instance of the receiver.
     */
    ProgressManager() {
        Platform.getJobManager().setProgressProvider(this);
        Dialog.setBlockedHandler(new WorkbenchDialogBlockedHandler());
        createChangeListener();
        Platform.getJobManager().addJobChangeListener(this.changeListener);
        URL iconsRoot = BundleUtility.find(PlatformUI.PLUGIN_ID,
                ProgressManager.PROGRESS_FOLDER);
        try {
            setUpImage(iconsRoot, SLEEPING_JOB, SLEEPING_JOB_KEY);
            setUpImage(iconsRoot, WAITING_JOB, WAITING_JOB_KEY);
            setUpImage(iconsRoot, BLOCKED_JOB, BLOCKED_JOB_KEY);
            //Let the error manager set up its own icons
            errorManager.setUpImages(iconsRoot);
        } catch (MalformedURLException e) {
            ProgressManagerUtil.logException(e);
        }
    }

    /**
     * Create the IJobChangeListener registered with the Job manager.
     */
    private void createChangeListener() {
        changeListener = new JobChangeAdapter() {
        	
        	
            /*
             * (non-Javadoc)
             * 
             * @see org.eclipse.core.runtime.jobs.JobChangeAdapter#aboutToRun(org.eclipse.core.runtime.jobs.IJobChangeEvent)
             */
            public void aboutToRun(IJobChangeEvent event) {
                JobInfo info = getJobInfo(event.getJob());
                refreshJobInfo(info);
                Iterator startListeners = busyListenersForJob(event.getJob())
                        .iterator();
                while (startListeners.hasNext()) {
                    IJobBusyListener next = (IJobBusyListener) startListeners
                            .next();
                    next.incrementBusy(event.getJob());
                }
            }

            /*
             * (non-Javadoc)
             * 
             * @see org.eclipse.core.runtime.jobs.JobChangeAdapter#done(org.eclipse.core.runtime.jobs.IJobChangeEvent)
             */
            public void done(IJobChangeEvent event) {
                if (!PlatformUI.isWorkbenchRunning()) {
					return;
				}
                Iterator startListeners = busyListenersForJob(event.getJob())
                        .iterator();
                while (startListeners.hasNext()) {
                    IJobBusyListener next = (IJobBusyListener) startListeners
                            .next();
                    next.decrementBusy(event.getJob());
                }
                JobInfo info = getJobInfo(event.getJob());
                if (event.getResult() != null
                        && event.getResult().getSeverity() == IStatus.ERROR) {
                    errorManager.addError(event.getResult(), event.getJob());
                }
                jobs.remove(event.getJob());
                //Only refresh if we are showing it
                removeJobInfo(info);
                //If there are no more left then refresh all on the last
                // displayed one.
                if (hasNoRegularJobInfos()
                        && !isNonDisplayableJob(event.getJob(), false)) {
					refreshAll();
				}
            }

            /*
             * (non-Javadoc)
             * 
             * @see org.eclipse.core.runtime.jobs.JobChangeAdapter#scheduled(org.eclipse.core.runtime.jobs.IJobChangeEvent)
             */
            public void scheduled(IJobChangeEvent event) {
                updateFor(event);
                if (event.getJob().isUser()) {
                    boolean noDialog = shouldRunInBackground();
                    if (!noDialog) {
                        final IJobChangeEvent finalEvent = event;
                        WorkbenchJob showJob = new WorkbenchJob(
                                ProgressMessages.ProgressManager_showInDialogName) { 
                            /*
                             * (non-Javadoc)
                             * 
                             * @see org.eclipse.ui.progress.UIJob#runInUIThread(org.eclipse.core.runtime.IProgressMonitor)
                             */
                            public IStatus runInUIThread(
                                    IProgressMonitor monitor) {
                                showInDialog(null, finalEvent.getJob());
                                return Status.OK_STATUS;
                            }
                        };
                        showJob.setSystem(true);
                        showJob.schedule();
                        return;
                    }
                }
            }

            /**
             * Update the listeners for the receiver for the event.
             * @param event
             */
            private void updateFor(IJobChangeEvent event) {
                if (isNeverDisplayedJob(event.getJob())) {
					return;
				}
                if (jobs.containsKey(event.getJob())) {
					refreshJobInfo(getJobInfo(event.getJob()));
				} else {
                    addJobInfo(new JobInfo(event.getJob()));
                }
            }

            /* (non-Javadoc)
             * @see org.eclipse.core.runtime.jobs.JobChangeAdapter#awake(org.eclipse.core.runtime.jobs.IJobChangeEvent)
             */
            public void awake(IJobChangeEvent event) {
                updateFor(event);
            }

            /* (non-Javadoc)
             * @see org.eclipse.core.runtime.jobs.JobChangeAdapter#sleeping(org.eclipse.core.runtime.jobs.IJobChangeEvent)
             */
            public void sleeping(IJobChangeEvent event) {
                updateFor(event);
            }
        };
    }

    /**
     * Set up the image in the image regsitry.
     * 
     * @param iconsRoot
     * @param fileName
     * @param key
     * @throws MalformedURLException
     */
    private void setUpImage(URL iconsRoot, String fileName, String key)
            throws MalformedURLException {
        JFaceResources.getImageRegistry().put(key,
                ImageDescriptor.createFromURL(new URL(iconsRoot, fileName)));
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.eclipse.core.runtime.jobs.ProgressProvider#createMonitor(org.eclipse.core.runtime.jobs.Job)
     */
    public IProgressMonitor createMonitor(Job job) {
        return progressFor(job);
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.eclipse.core.runtime.jobs.ProgressProvider#getDefaultMonitor()
     */
    public IProgressMonitor getDefaultMonitor() {
        //only need a default monitor for operations the UI thread
        //and only if there is a display
        Display display;
        if (PlatformUI.isWorkbenchRunning() && !((Workbench)PlatformUI.getWorkbench()).isStarting()) {
            display = PlatformUI.getWorkbench().getDisplay();
            if (!display.isDisposed()
                    && (display.getThread() == Thread.currentThread())) {
				return new EventLoopProgressMonitor(new NullProgressMonitor());
			}
        }
        return super.getDefaultMonitor();
    }

    /**
     * Return a monitor for the job. Check if we cached a monitor for this job
     * previously for a long operation timeout check.
     * 
     * @param job
     * @return IProgressMonitor
     */
    public JobMonitor progressFor(Job job) {

        synchronized (monitorKey) {
            if (runnableMonitors.containsKey(job)) {
				return (JobMonitor) runnableMonitors.get(job);
			}
            JobMonitor monitor = new JobMonitor(job);
            runnableMonitors.put(job, monitor);
            return monitor;
        }

    }

    /**
     * Add an IJobProgressManagerListener to listen to the changes.
     * 
     * @param listener
     */
    void addListener(IJobProgressManagerListener listener) {
    	
    	synchronized (listenersKey){
    		ArrayList newListeners = new ArrayList(listeners.length + 1);
    		for (int i = 0; i < listeners.length; i++) {
				newListeners.add(listeners[i]);
			}
    		newListeners.add(listener);
    		listeners = new IJobProgressManagerListener[newListeners.size()];
    		newListeners.toArray(listeners);
    	}
    	
    }

    /**
     * Remove the supplied IJobProgressManagerListener from the list of
     * listeners.
     * 
     * @param listener
     */
    void removeListener(IJobProgressManagerListener listener){
    	synchronized (listenersKey){
    		ArrayList newListeners = new ArrayList();
    		for (int i = 0; i < listeners.length; i++) {
				if(listeners[i].equals(listener)) {
					continue;
				}
				newListeners.add(listeners[i]);
			}
    		listeners = new IJobProgressManagerListener[newListeners.size()];
    		newListeners.toArray(listeners);
    	}
    }

    /**
     * Get the JobInfo for the job. If it does not exist create it.
     * 
     * @param job
     * @return JobInfo
     */
    JobInfo getJobInfo(Job job) {
        JobInfo info = (JobInfo) jobs.get(job);
        if (info == null) {
            info = new JobInfo(job);
            jobs.put(job, info);
        }
        return info;
    }

    /**
     * Refresh the IJobProgressManagerListeners as a result of a change in info.
     * 
     * @param info
     */
    public void refreshJobInfo(JobInfo info) {
        GroupInfo group = info.getGroupInfo();
        if (group != null) {
			refreshGroup(group);
		}
       
        synchronized (listenersKey) {
        	for (int i = 0; i < listeners.length; i++) {
        		IJobProgressManagerListener listener = listeners[i];
        		if (!isNonDisplayableJob(info.getJob(), listener.showsDebug())) {
					listener.refreshJobInfo(info);
				}
        	}
        }
    }

    /**
     * Refresh the IJobProgressManagerListeners as a result of a change in info.
     * 
     * @param info
     */
    public void refreshGroup(GroupInfo info) {

    	synchronized (listenersKey) {
    		for (int i = 0; i < listeners.length; i++) {
            	listeners[i].refreshGroup(info);
        	}
    	}
    }

    /**
     * Refresh all the IJobProgressManagerListener as a result of a change in
     * the whole model.
     */
    public void refreshAll() {

        pruneStaleJobs();
        synchronized (listenersKey) {
        	 for (int i = 0; i < listeners.length; i++) {
                listeners[i].refreshAll();
            }
		}
       
    }

    /**
     * Refresh the content providers as a result of a deletion of info.
     * 
     * @param info
     *            JobInfo
     */
    public void removeJobInfo(JobInfo info) {

        Job job = info.getJob();
        jobs.remove(job);
        synchronized (monitorKey) {
            if (runnableMonitors.containsKey(job)) {
				runnableMonitors.remove(job);
			}
        }

        synchronized (listenersKey) {
        	for (int i = 0; i < listeners.length; i++) {
        		IJobProgressManagerListener listener = listeners[i];
        		if (!isNonDisplayableJob(info.getJob(), listener.showsDebug())) {
					listener.removeJob(info);
				}
        	}
        }

    }

    /**
     * Remove the group from the roots and inform the listeners.
     * 
     * @param group
     *            GroupInfo
     */
    public void removeGroup(GroupInfo group) {

    	synchronized (listenersKey) {
    		for (int i = 0; i < listeners.length; i++) {
    			listeners[i].removeGroup(group);
    		}
    	}
    }

    /**
     * Refresh the content providers as a result of an addition of info.
     * 
     * @param info
     */
    public void addJobInfo(JobInfo info) {
        GroupInfo group = info.getGroupInfo();
        if (group != null) {
			refreshGroup(group);
		}

        jobs.put(info.getJob(), info);
       synchronized (listenersKey) {
       		for (int i = 0; i < listeners.length; i++) {
       			IJobProgressManagerListener listener = listeners[i];
       			if (!isNonDisplayableJob(info.getJob(), listener.showsDebug())) {
					listener.addJob(info);
				}
       		}
       }
       }

    /**
     * Refresh the content providers as a result of an addition of info.
     * 
     * @param info
     */
    public void addGroup(GroupInfo info) {

    	synchronized (listenersKey) {
    		for (int i = 0; i < listeners.length; i++) {
    			listeners[i].addGroup(info);
    		}
    	}
    }

    /**
     * Return whether or not this job is currently displayable.
     * 
     * @param job
     * @param debug
     *            If the listener is in debug mode.
     * @return boolean <code>true</code> if the job is not 
     * displayed.
     */
    boolean isNonDisplayableJob(Job job, boolean debug) {
        if (isNeverDisplayedJob(job)) {
			return true;
		}
        if (debug) {
			return false;
		}
        return job.isSystem() || job.getState() == Job.SLEEPING;
    }

    /**
     * Return whether or not this job is ever displayable.
     * 
     * @param job
     * @return boolean <code>true</code> if it is never
     * displayed.
     */
    private boolean isNeverDisplayedJob(Job job) {
        return job == null;
    }

    /**
     * Return the current job infos filtered on debug mode.
     * 
     * @param debug
     * @return JobInfo[] 
     */
    public JobInfo[] getJobInfos(boolean debug) {
        synchronized (jobs) {
            Iterator iterator = jobs.keySet().iterator();
            Collection result = new ArrayList();
            while (iterator.hasNext()) {
                Job next = (Job) iterator.next();
                if (!isNonDisplayableJob(next, debug)) {
					result.add(jobs.get(next));
				}
            }
            JobInfo[] infos = new JobInfo[result.size()];
            result.toArray(infos);
            return infos;
        }
    }

    /**
     * Return the current root elements filtered on the debug mode.
     * 
     * @param debug
     * @return JobTreeElement[]
     */
    public JobTreeElement[] getRootElements(boolean debug) {
        synchronized (jobs) {
            Iterator iterator = jobs.keySet().iterator();
            Collection result = new HashSet();
            while (iterator.hasNext()) {
                Job next = (Job) iterator.next();
                if (!isNonDisplayableJob(next, debug)) {
                    JobInfo jobInfo = (JobInfo) jobs.get(next);
                    GroupInfo group = jobInfo.getGroupInfo();
                    if (group == null) {
						result.add(jobInfo);
					} else {
						result.add(group);
					}
                }
            }
            JobTreeElement[] infos = new JobTreeElement[result.size()];
            result.toArray(infos);
            return infos;
        }
    }

    /**
     * Return whether or not there are any jobs being displayed.
     * 
     * @return boolean
     */
    public boolean hasJobInfos() {
        synchronized (jobs) {
            Iterator iterator = jobs.keySet().iterator();
            while (iterator.hasNext()) {
                return true;
            }
            return false;
        }
    }

    /**
     * Return true if there are no jobs or they are all debug.
     * 
     * @return boolean
     */
    private boolean hasNoRegularJobInfos() {
        synchronized (jobs) {
            Iterator iterator = jobs.keySet().iterator();
            while (iterator.hasNext()) {
                Job next = (Job) iterator.next();
                if (!isNonDisplayableJob(next, false)) {
					return false;
				}
            }
            return true;
        }
    }

    /**
     * Returns the image descriptor with the given relative path.
     * 
     * @param source
     * @return Image
     */
    Image getImage(ImageData source) {
        ImageData mask = source.getTransparencyMask();
        return new Image(null, source, mask);
    }

    /**
     * Returns the image descriptor with the given relative path.
     * 
     * @param fileSystemPath
     *            The URL for the file system to the image.
     * @param loader -
     *            the loader used to get this data
     * @return ImageData[]
     */
    ImageData[] getImageData(URL fileSystemPath, ImageLoader loader) {
        try {
            InputStream stream = fileSystemPath.openStream();
            ImageData[] result = loader.load(stream);
            stream.close();
            return result;
        } catch (FileNotFoundException exception) {
            ProgressManagerUtil.logException(exception);
            return null;
        } catch (IOException exception) {
            ProgressManagerUtil.logException(exception);
            return null;
        }
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.eclipse.ui.progress.IProgressService#busyCursorWhile(org.eclipse.jface.operation.IRunnableWithProgress)
     */
    public void busyCursorWhile(final IRunnableWithProgress runnable)
            throws InvocationTargetException, InterruptedException {
        final ProgressMonitorJobsDialog dialog = new ProgressMonitorJobsDialog(
                ProgressManagerUtil.getDefaultParent());
        dialog.setOpenOnRun(false);
        final InvocationTargetException[] invokes = new InvocationTargetException[1];
        final InterruptedException[] interrupt = new InterruptedException[1];
        //show a busy cursor until the dialog opens
        Runnable dialogWaitRunnable = new Runnable() {
            public void run() {
                try {
                    dialog.setOpenOnRun(false);
                    setUserInterfaceActive(false);
                    dialog.run(true, true, runnable);
                } catch (InvocationTargetException e) {
                    invokes[0] = e;
                } catch (InterruptedException e) {
                    interrupt[0] = e;
                } finally {
                    setUserInterfaceActive(true);
                }
            }
        };
        busyCursorWhile(dialogWaitRunnable, dialog);
        if (invokes[0] != null) {
            throw invokes[0];
        }
        if (interrupt[0] != null) {
            throw interrupt[0];
        }
    }

    /**
     * Show the busy cursor while the runnable is running. Schedule a job to
     * replace it with a progress dialog.
     * 
     * @param dialogWaitRunnable
     * @param dialog
     */
    private void busyCursorWhile(Runnable dialogWaitRunnable,
            ProgressMonitorJobsDialog dialog) {
        //create the job that will open the dialog after a delay
        scheduleProgressMonitorJob(dialog);
        final Display display = PlatformUI.getWorkbench().getDisplay();
        if (display == null) {
			return;
		}
        //show a busy cursor until the dialog opens
        BusyIndicator.showWhile(display, dialogWaitRunnable);
    }

    /**
     * Schedule the job that will open the progress monitor dialog
     * 
     * @param dialog
     *            the dialog to open
     */
    private void scheduleProgressMonitorJob(
            final ProgressMonitorJobsDialog dialog) {

        final WorkbenchJob updateJob = new WorkbenchJob(ProgressMessages.ProgressManager_openJobName) {
            /*
             * (non-Javadoc)
             * 
             * @see org.eclipse.ui.progress.UIJob#runInUIThread(org.eclipse.core.runtime.IProgressMonitor)
             */
            public IStatus runInUIThread(IProgressMonitor monitor) {
                setUserInterfaceActive(true);
                if (ProgressManagerUtil.safeToOpen(dialog,null)) {
					dialog.open();
				}
                return Status.OK_STATUS;
            }
        };
        updateJob.setSystem(true);
        updateJob.schedule(getLongOperationTime());

    }

    /**
     * Shutdown the receiver.
     */
    private void shutdown() {
    	synchronized (listenersKey) {
    		this.listeners = new IJobProgressManagerListener[0];
    	}
        Platform.getJobManager().setProgressProvider(null);
        Platform.getJobManager().removeJobChangeListener(this.changeListener);
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.eclipse.core.runtime.jobs.ProgressProvider#createProgressGroup()
     */
    public IProgressMonitor createProgressGroup() {
        return new GroupInfo();
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.eclipse.core.runtime.jobs.ProgressProvider#createMonitor(org.eclipse.core.runtime.jobs.Job,
     *      org.eclipse.core.runtime.IProgressMonitor, int)
     */
    public IProgressMonitor createMonitor(Job job, IProgressMonitor group,
            int ticks) {
        JobMonitor monitor = progressFor(job);
        if (group instanceof GroupInfo) {
            GroupInfo groupInfo = (GroupInfo) group;
            JobInfo jobInfo = getJobInfo(job);
            jobInfo.setGroupInfo(groupInfo);
            jobInfo.setTicks(ticks);
            groupInfo.addJobInfo(jobInfo);
        }
        return monitor;
    }

    /**
     * Add the listener to the family.
     * 
     * @param family
     * @param listener
     */
    void addListenerToFamily(Object family, IJobBusyListener listener) {
        synchronized (familyKey) {
            Collection currentListeners;
            if (familyListeners.containsKey(family)) {
				currentListeners = (Collection) familyListeners.get(family);
			} else {
				currentListeners = new HashSet();
			}
            currentListeners.add(listener);
            familyListeners.put(family, currentListeners);
        }
    }

    /**
     * Remove the listener from all families.
     * 
     * @param listener
     */
    void removeListener(IJobBusyListener listener) {
        synchronized (familyKey) {
            Collection keysToRemove = new HashSet();
            Iterator families = familyListeners.keySet().iterator();
            while (families.hasNext()) {
                Object next = families.next();
                Collection currentListeners = (Collection) familyListeners
                        .get(next);
                if (currentListeners.contains(listener)) {
					currentListeners.remove(listener);
				}
                if (currentListeners.isEmpty()) {
					keysToRemove.add(next);
				} else {
					familyListeners.put(next, currentListeners);
				}
            }
            //Remove any empty listeners
            Iterator keysIterator = keysToRemove.iterator();
            while (keysIterator.hasNext()) {
                familyListeners.remove(keysIterator.next());
            }
        }
    }

    /**
     * Return the listeners for the job.
     * 
     * @param job
     * @return Collection of IJobBusyListener
     */
    private Collection busyListenersForJob(Job job) {
        if (job.isSystem()) {
			return Collections.EMPTY_LIST;
		} 
        synchronized (familyKey) {
            
            if(familyListeners.isEmpty()) {
				return Collections.EMPTY_LIST;
			}
            
            Iterator families = familyListeners.keySet().iterator();
            Collection returnValue = new ArrayList();
            while (families.hasNext()) {
                Object next = families.next();
                if (job.belongsTo(next)) {
                    Collection currentListeners = (Collection) familyListeners
                            .get(next);
                    returnValue.addAll(currentListeners);
                }
            }
            return returnValue;
        }
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.eclipse.ui.progress.IProgressService#showInDialog(org.eclipse.swt.widgets.Shell,
     *      org.eclipse.core.runtime.jobs.Job)
     */
    public void showInDialog(Shell shell, Job job) {
        if (shouldRunInBackground()) {
			return;
		}

        final ProgressMonitorFocusJobDialog dialog = new ProgressMonitorFocusJobDialog(
                shell);
        dialog.show(job,shell);
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.eclipse.jface.operation.IRunnableContext#run(boolean, boolean,
     *      org.eclipse.jface.operation.IRunnableWithProgress)
     */
    public void run(boolean fork, boolean cancelable,
            IRunnableWithProgress runnable) throws InvocationTargetException,
            InterruptedException {
        if (fork == false || cancelable == false) {
            //backward compatible code
            final ProgressMonitorJobsDialog dialog = new ProgressMonitorJobsDialog(
                    null);
            dialog.run(fork, cancelable, runnable);
            return;
        }

        busyCursorWhile(runnable);
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.eclipse.ui.progress.IProgressService#runInUI(org.eclipse.jface.operation.IRunnableWithProgress,
     *      org.eclipse.core.runtime.jobs.ISchedulingRule)
     */
    public void runInUI(final IRunnableContext context,
            final IRunnableWithProgress runnable, final ISchedulingRule rule)
            throws InvocationTargetException, InterruptedException {
        final IJobManager manager = Platform.getJobManager();
        final InvocationTargetException[] exception = new InvocationTargetException[1];
        final InterruptedException[] canceled = new InterruptedException[1];
        BusyIndicator.showWhile(Display.getDefault(), new Runnable() {
            public void run() {
                try {
                    manager.beginRule(rule, ((Workbench)PlatformUI.getWorkbench()).isStarting() ? new NullProgressMonitor() : getEventLoopMonitor());
                    context.run(false, false, runnable);
                } catch (InvocationTargetException e) {
                    exception[0] = e;
                } catch (InterruptedException e) {
                    canceled[0] = e;
                } catch (OperationCanceledException e) {
                    canceled[0] = new InterruptedException(e.getMessage());
                } finally {
                    manager.endRule(rule);
                }
            }

            /**
             * Get a progress monitor that forwards to an
             * event loop monitor. Override #setBlocked()
             * so that we always open the blocked dialog.
             * @return the monitor on the event loop
             */
            private IProgressMonitor getEventLoopMonitor() {
                return new EventLoopProgressMonitor(new NullProgressMonitor()) {
                    /*
                     * (non-Javadoc)
                     * 
                     * @see org.eclipse.ui.internal.dialogs.EventLoopProgressMonitor#setBlocked(org.eclipse.core.runtime.IStatus)
                     */
                    public void setBlocked(IStatus reason) {

                        //Set a shell to open with as we want to create this
                        //even if there is a modal shell.
                        Dialog.getBlockedHandler().showBlocked(
                                ProgressManagerUtil.getDefaultParent(), this,
                                reason, getTaskName());
                    }
                };
            }
        });
        if (exception[0] != null) {
			throw exception[0];
		}
        if (canceled[0] != null) {
			throw canceled[0];
		}
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.eclipse.ui.progress.IProgressService#getLongOperationTime()
     */
    public int getLongOperationTime() {
        return 800;
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.eclipse.ui.progress.IProgressService#registerIconForFamily(org.eclipse.jface.resource.ImageDescriptor,
     *      java.lang.Object)
     */
    public void registerIconForFamily(ImageDescriptor icon, Object family) {
        String key = IMAGE_KEY + String.valueOf(imageKeyTable.size());
        imageKeyTable.put(family, key);
        ImageRegistry registry = JFaceResources.getImageRegistry();

        //Avoid registering twice
        if (registry.getDescriptor(key) == null) {
			registry.put(key, icon);
		}

    }

    /*
     * (non-Javadoc)
     * 
     * @see org.eclipse.ui.progress.IProgressService#getIconFor(org.eclipse.core.runtime.jobs.Job)
     */
    public Image getIconFor(Job job) {
        Enumeration families = imageKeyTable.keys();
        while (families.hasMoreElements()) {
            Object next = families.nextElement();
            if (job.belongsTo(next)) {
				return JFaceResources.getImageRegistry().get(
                        (String) imageKeyTable.get(next));
			}
        }
        return null;
    }

    /**
     * Iterate through all of the windows and set them to be disabled or enabled
     * as appropriate.'
     * 
     * @param active
     *            The set the windows will be set to.
     */
    private void setUserInterfaceActive(boolean active) {
        IWorkbench workbench = PlatformUI.getWorkbench();
        Shell[] shells = workbench.getDisplay().getShells();
        if (active) {
	        for (int i = 0; i < shells.length; i++) {
	            shells[i].setEnabled(active);
	        }
        }
        else {
        	// Deactive shells in reverse order
	        for (int i = shells.length-1; i >= 0; i--) {
	            shells[i].setEnabled(active);
	        }
        }
    }

    /**
     * Check to see if there are any stale jobs we have not cleared out.
     * 
     * @return <code>true</code> if anything was pruned
     */
    private boolean pruneStaleJobs() {
        Object[] jobsToCheck = jobs.keySet().toArray();
        boolean pruned = false;
        for (int i = 0; i < jobsToCheck.length; i++) {
            Job job = (Job) jobsToCheck[i];
            if(checkForStaleness(job)){
            	if (Policy.DEBUG_STALE_JOBS) {
					WorkbenchPlugin.log("Stale Job " + job.getName()); //$NON-NLS-1$
				}
            	pruned = true;
            }
        }

        return pruned;
    }

    /**
     * Check the if the job should be removed from the
     * list as it may be stale.
	 * @param job
	 * @return boolean
	 */
	boolean checkForStaleness(Job job) {
		if (job.getState() == Job.NONE) {
		    removeJobInfo(getJobInfo(job));
		   return true;
		}
		return false;
	}

	/**
     * Return whether or not dialogs should be run in the background
     * @return <code>true</code> if the dialog should not be shown.
     */
    private boolean shouldRunInBackground() {
        return WorkbenchPlugin.getDefault().getPreferenceStore().getBoolean(
                IPreferenceConstants.RUN_IN_BACKGROUND);
    }

	/**
	 * Set whether or not the ProgressViewUpdater
	 * should show system jobs.
	 * @param showSystem
	 */
	public void setShowSystemJobs(boolean showSystem) {
		ProgressViewUpdater updater = ProgressViewUpdater.getSingleton();
		updater.debug = showSystem;
		updater.refreshAll();
		
	}
}
