blob: 19c4601f1e2bcc15d2735307735828a2b59912ca [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2003, 2012 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 - Initial API and implementation
*******************************************************************************/
package org.eclipse.core.internal.jobs;
import org.eclipse.core.internal.runtime.RuntimeLog;
import org.eclipse.core.runtime.*;
import org.eclipse.core.runtime.jobs.*;
import org.eclipse.osgi.util.NLS;
/**
* Responsible for notifying all job listeners about job lifecycle events. Uses a
* specialized iterator to ensure the complex iteration logic is contained in one place.
*/
class JobListeners {
interface IListenerDoit {
public void notify(IJobChangeListener listener, IJobChangeEvent event);
}
private final IListenerDoit aboutToRun = new IListenerDoit() {
public void notify(IJobChangeListener listener, IJobChangeEvent event) {
listener.aboutToRun(event);
}
};
private final IListenerDoit awake = new IListenerDoit() {
public void notify(IJobChangeListener listener, IJobChangeEvent event) {
listener.awake(event);
}
};
private final IListenerDoit done = new IListenerDoit() {
public void notify(IJobChangeListener listener, IJobChangeEvent event) {
listener.done(event);
}
};
private final IListenerDoit running = new IListenerDoit() {
public void notify(IJobChangeListener listener, IJobChangeEvent event) {
listener.running(event);
}
};
private final IListenerDoit scheduled = new IListenerDoit() {
public void notify(IJobChangeListener listener, IJobChangeEvent event) {
listener.scheduled(event);
}
};
private final IListenerDoit sleeping = new IListenerDoit() {
public void notify(IJobChangeListener listener, IJobChangeEvent event) {
listener.sleeping(event);
}
};
/**
* The global job listeners.
*/
protected final ListenerList global = new ListenerList(ListenerList.IDENTITY);
/**
* TODO Could use an instance pool to re-use old event objects
*/
static JobChangeEvent newEvent(Job job) {
JobChangeEvent instance = new JobChangeEvent();
instance.job = job;
return instance;
}
static JobChangeEvent newEvent(Job job, IStatus result) {
JobChangeEvent instance = new JobChangeEvent();
instance.job = job;
instance.result = result;
return instance;
}
static JobChangeEvent newEvent(Job job, long delay) {
JobChangeEvent instance = new JobChangeEvent();
instance.job = job;
instance.delay = delay;
return instance;
}
/**
* Process the given doit for all global listeners and all local listeners
* on the given job.
*/
private void doNotify(final IListenerDoit doit, final IJobChangeEvent event) {
//notify all global listeners
Object[] listeners = global.getListeners();
int size = listeners.length;
for (int i = 0; i < size; i++) {
try {
if (listeners[i] != null)
doit.notify((IJobChangeListener) listeners[i], event);
} catch (Exception e) {
handleException(listeners[i], e);
} catch (LinkageError e) {
handleException(listeners[i], e);
}
}
//notify all local listeners
ListenerList list = ((InternalJob) event.getJob()).getListeners();
listeners = list == null ? null : list.getListeners();
if (listeners == null)
return;
size = listeners.length;
for (int i = 0; i < size; i++) {
try {
if (listeners[i] != null)
doit.notify((IJobChangeListener) listeners[i], event);
} catch (Exception e) {
handleException(listeners[i], e);
} catch (LinkageError e) {
handleException(listeners[i], e);
}
}
}
private void handleException(Object listener, Throwable e) {
//this code is roughly copied from InternalPlatform.run(ISafeRunnable),
//but in-lined here for performance reasons
if (e instanceof OperationCanceledException)
return;
String pluginId = JobOSGiUtils.getDefault().getBundleId(listener);
if (pluginId == null)
pluginId = JobManager.PI_JOBS;
String message = NLS.bind(JobMessages.meta_pluginProblems, pluginId);
RuntimeLog.log(new Status(IStatus.ERROR, pluginId, JobManager.PLUGIN_ERROR, message, e));
}
public void add(IJobChangeListener listener) {
global.add(listener);
}
public void remove(IJobChangeListener listener) {
global.remove(listener);
}
public void aboutToRun(Job job) {
doNotify(aboutToRun, newEvent(job));
}
public void awake(Job job) {
doNotify(awake, newEvent(job));
}
public void done(Job job, IStatus result, boolean reschedule) {
JobChangeEvent event = newEvent(job, result);
event.reschedule = reschedule;
doNotify(done, event);
}
public void running(Job job) {
doNotify(running, newEvent(job));
}
public void scheduled(Job job, long delay, boolean reschedule) {
JobChangeEvent event = newEvent(job, delay);
event.reschedule = reschedule;
doNotify(scheduled, event);
}
public void sleeping(Job job) {
doNotify(sleeping, newEvent(job));
}
}