/******************************************************************************* * Copyright (c) 2007 Exadel, Inc. and Red Hat, Inc. * Distributed under license by Red Hat, Inc. All rights reserved. * This program is 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: * Exadel, Inc. and Red Hat, Inc. - initial API and implementation ******************************************************************************/ package org.jboss.tools.common.model; import java.util.*; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.resources.WorkspaceJob; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.MultiStatus; import org.eclipse.core.runtime.NullProgressMonitor; import org.eclipse.core.runtime.Platform; import org.eclipse.core.runtime.Status; import org.eclipse.core.runtime.jobs.Job; import org.eclipse.ui.internal.decorators.DecoratorManager; import org.eclipse.ui.progress.UIJob; import org.jboss.tools.common.model.plugin.ModelPlugin; public class XJob extends WorkspaceJob { public static Object FAMILY_XJOB = new Object(); private static boolean suspended = false; public interface XRunnable extends Runnable { public String getId(); } static XJob JOB = new XJob(); public static void addRunnable(XRunnable runnable) { JOB.addRunnableInternal(runnable); } public static void addRunnableWithPriority(XRunnable runnable) { JOB.addRunnableInternalWithPriority(runnable); } public static void waitForJob() throws InterruptedException { waitForJob(false); } public static void shutdown() { setSuspended(true); synchronized (JOB) { JOB.ids.clear(); JOB.list.clear(); } if(JOB.isRunning()) { JOB.cancel(); } } public static void waitForJob(boolean immediateOnly) throws InterruptedException { Object[] o = { XJob.FAMILY_XJOB, ResourcesPlugin.FAMILY_AUTO_REFRESH, ResourcesPlugin.FAMILY_AUTO_BUILD }; while(true) { boolean stop = true; for (int i = 0; i < o.length; i++) { Job[] js = Platform.getJobManager().find(o[i]); if(js != null && js.length > 0) { Platform.getJobManager().join(o[i], new NullProgressMonitor()); stop = false; } } if(stop && !immediateOnly) { Job running = getJobRunning(10); if(running != null) { running.join(); stop = false; } } if(stop) break; } } public static Job getJobRunning(int iterationLimit) { Job[] js = Platform.getJobManager().find(null); Job dm = null; if(js != null) for (int i = 0; i < js.length; i++) { if(js[i].getState() == Job.RUNNING && js[i].getThread() != Thread.currentThread()) { if(js[i] instanceof UIJob) continue; if(js[i].belongsTo(DecoratorManager.FAMILY_DECORATE)) { dm = js[i]; continue; } //TODO keep watching return js[i]; } } if(dm != null) { try { Thread.sleep(1000); } catch (InterruptedException e) { //ignore } if(iterationLimit > 0) return getJobRunning(iterationLimit - 1); } return null; } Set<String> ids = new HashSet<String>(); List<XRunnable> list = new ArrayList<XRunnable>(); public XJob() { super("JBoss Tools Model Update"); setSystem(true); } public boolean belongsTo(Object family) { return family == FAMILY_XJOB; } void addRunnableInternal(XRunnable runnable) { if (!isSuspended()) { synchronized (this) { if (ids.contains(runnable.getId())) return; ids.add(runnable.getId()); list.add(runnable); } if (getState() == Job.NONE || !isRunning()) { schedule(1000); } } } private boolean isRunning() { synchronized(this) { return running; } } void addRunnableInternalWithPriority(XRunnable runnable) { if (!isSuspended()) { synchronized (this) { if (ids.contains(runnable.getId())) return; ids.add(runnable.getId()); list.add(0, runnable); } if (getState() == Job.NONE || !isRunning()) { schedule(0); } } } boolean running = false; @Override public IStatus runInWorkspace(IProgressMonitor monitor) throws CoreException { synchronized(this) { running = true; } while(true) { XRunnable r = null; synchronized (this) { if(list.size() == 0) { running = false; break; } r = list.remove(0); } // monitor.subTask(r.getId()) is irrelevant for system jobs //monitor.subTask(r.getId()); // XJob is a class from the org.jboss.tools.common.model plugin. This plugin must be active //int state = 0; //Bundle b = Platform.getBundle("org.jboss.tools.common.model"); //state = b==null ? -1 : b.getState(); //if(state == Bundle.ACTIVE) { synchronized (this) { ids.remove(r.getId()); } if(monitor.isCanceled()) { break; } if (!isSuspended()) { try { r.run(); } catch (Exception e) { if(e instanceof RuntimeException) { synchronized(this) { running = false; } throw (RuntimeException)e; } ModelPlugin.getDefault().logError("Error in job " + r.getId(), e); } } //} } return Status.OK_STATUS; } public static boolean isSuspended() { return suspended; } public static void setSuspended(boolean suspended) { XJob.suspended = suspended; } }