[65379] Deadlock with start remote vm between ui thread and build thread.
diff --git a/plugins/org.eclipse.jem.beaninfo/beaninfo/org/eclipse/jem/internal/beaninfo/adapters/BeaninfoNature.java b/plugins/org.eclipse.jem.beaninfo/beaninfo/org/eclipse/jem/internal/beaninfo/adapters/BeaninfoNature.java index ba520eb..30befeb 100644 --- a/plugins/org.eclipse.jem.beaninfo/beaninfo/org/eclipse/jem/internal/beaninfo/adapters/BeaninfoNature.java +++ b/plugins/org.eclipse.jem.beaninfo/beaninfo/org/eclipse/jem/internal/beaninfo/adapters/BeaninfoNature.java
@@ -11,7 +11,7 @@ *******************************************************************************/ /* * $RCSfile: BeaninfoNature.java,v $ - * $Revision: 1.17 $ $Date: 2004/06/02 19:42:39 $ + * $Revision: 1.18 $ $Date: 2004/06/04 15:29:34 $ */ import java.io.*; @@ -355,22 +355,29 @@ /* * This is <package-protected> so that only the appropriate create job in this * package can call it. This is because this must be controlled to only be - * done in UI thread. + * done when build not in progress and serial access. + * If waitForBuild is passed onto launching the registry. If we suspended the builds, then we must not + * wait, or a deadlock will occur. */ - void createRegistry(IProgressMonitor pm) { - synchronized (this) { - if (fRegistry != null) - return; // It had already gotton created. Could of because UI and a thread were racing to do the creation, and one got there first. + synchronized void createRegistry(IProgressMonitor pm, boolean waitForBuild) { + pm.beginTask(BeanInfoAdapterMessages.getString("UICreateRegistryJobHandler.StartBeaninfoRegistry"), 100); //$NON-NLS-1$ + // synchronized on this nature so that only one can create on this particular project at a time. + if (fRegistry != null) { + pm.done(); + return; // It had already been created. Could of been because threads were racing to do the creation, and one got there first. } + try { ConfigurationContributor configurationContributor = (ConfigurationContributor) getConfigurationContributor(); configurationContributor.setNature(this); fRegistry = ProxyLaunchSupport.startImplementation(fProject, "Beaninfo", //$NON-NLS-1$ - new IConfigurationContributor[] { configurationContributor}, pm); + new IConfigurationContributor[] { configurationContributor}, waitForBuild, new SubProgressMonitor(pm, 100)); fRegistry.addRegistryListener(registryListener); } catch (CoreException e) { BeaninfoPlugin.getPlugin().getLogger().log(e.getStatus()); - } + } finally { + pm.done(); + } } public synchronized boolean isRegistryCreated() { @@ -426,7 +433,7 @@ } catch (CoreException e) { BeaninfoPlugin.getPlugin().getLogger().log(e.getStatus()); } catch (Exception e) { - BeaninfoPlugin.getPlugin().getLogger().log(new Status(IStatus.WARNING, BeaninfoPlugin.PI_BEANINFO_PLUGINID, 0, "", e)); + BeaninfoPlugin.getPlugin().getLogger().log(new Status(IStatus.WARNING, BeaninfoPlugin.PI_BEANINFO_PLUGINID, 0, "", e)); //$NON-NLS-1$ } return bdoc; }
diff --git a/plugins/org.eclipse.jem.beaninfo/beaninfo/org/eclipse/jem/internal/beaninfo/adapters/CreateRegistryJobHandler.java b/plugins/org.eclipse.jem.beaninfo/beaninfo/org/eclipse/jem/internal/beaninfo/adapters/CreateRegistryJobHandler.java index a5509a7..196deee 100644 --- a/plugins/org.eclipse.jem.beaninfo/beaninfo/org/eclipse/jem/internal/beaninfo/adapters/CreateRegistryJobHandler.java +++ b/plugins/org.eclipse.jem.beaninfo/beaninfo/org/eclipse/jem/internal/beaninfo/adapters/CreateRegistryJobHandler.java
@@ -10,17 +10,19 @@ *******************************************************************************/ /* * $RCSfile: CreateRegistryJobHandler.java,v $ - * $Revision: 1.3 $ $Date: 2004/06/02 19:42:39 $ + * $Revision: 1.4 $ $Date: 2004/06/04 15:29:34 $ */ package org.eclipse.jem.internal.beaninfo.adapters; +import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.*; +import org.eclipse.core.runtime.jobs.*; /** * This class is used by BeaninfoNature to handle the creation of the registry, * either as a job queued off to the UI thread, or directly in case either in - * UI or UI not started. + * UI or UI not started. This class will be a singleton. * @since 1.0.0 */ class CreateRegistryJobHandler { @@ -58,15 +60,10 @@ * @since 1.0.0 */ protected void processCreateRegistry(BeaninfoNature nature) { - // sync on nature because we aren't in the UI environment, so we can't sequentially do the create requests. - // We would get a race condition in non UI environment. In UI environment we can be sure that the - // create request will be processed sequentially (through the UI thread) and so not have a race. In that - // case we mustn't get the hold on nature. - synchronized (nature) { - doCreateRegistry(nature, new NullProgressMonitor()); - } + doCreateRegistry(nature, new NullProgressMonitor()); } + private int suspendedCount = 0; // Number of nested suspends. Resume will occur only when it goes back to zero. /* * Do the creation. * @@ -76,7 +73,49 @@ * @since 1.0.0 */ protected final void doCreateRegistry(BeaninfoNature nature, IProgressMonitor pm) { - nature.createRegistry(pm); + pm.beginTask("", 400); //$NON-NLS-1$ + IJobManager jobManager = Platform.getJobManager(); + Job currentJob = jobManager.currentJob(); + ISchedulingRule suspendedBuildRule = null; // The build rule. This will be null if I don't suspend. + try { + if (currentJob == null || (!currentJob.belongsTo(ResourcesPlugin.FAMILY_AUTO_BUILD) && !currentJob.belongsTo(ResourcesPlugin.FAMILY_MANUAL_BUILD))) { + // We are not in the build, so suspend the rule. But first, wait for the builds to complete. This + // is because we need the builds to be completed (so that we see the changed files), but we can't + // let it happen later. This is because there can be a deadlock between the build and this thread + // if we let the build (through some builder which is trying to do introspection) lock on this + // project after we've locked on this project. Therefor we need to complete the build, and then + // stop it from running again until we've completed on this project. + if (jobManager.find(ResourcesPlugin.FAMILY_AUTO_BUILD).length > 0 || jobManager.find(ResourcesPlugin.FAMILY_MANUAL_BUILD).length >0) { + try { + jobManager.join(ResourcesPlugin.FAMILY_AUTO_BUILD, new SubProgressMonitor(pm, 100)); + jobManager.join(ResourcesPlugin.FAMILY_MANUAL_BUILD, new SubProgressMonitor(pm, 100)); + } catch (InterruptedException e) { + // Canceled, go on. + } + } else + pm.worked(200); + + synchronized(this) { + ++suspendedCount; // We need to keep track of nesting of suspends because Eclipse doesn't. The first resume will cause it to resume. + suspendedBuildRule = ResourcesPlugin.getWorkspace().getRuleFactory().buildRule(); + jobManager.suspend(suspendedBuildRule, new SubProgressMonitor(pm, 100)); + } + } else + pm.worked(300); + // Don't wait for the build to finish. Either we suspended the build, or we are in the build. In either case + // we can't wait for the build or we would deadlock. + nature.createRegistry(new SubProgressMonitor(pm, 100), false); + } finally { + synchronized (this) { + if (suspendedBuildRule != null) { + if (--suspendedCount<= 0) { + suspendedCount = 0; // Just to be safe. + jobManager.resume(suspendedBuildRule); + } + } + } + pm.done(); + } } }
diff --git a/plugins/org.eclipse.jem.beaninfo/beaninfo/org/eclipse/jem/internal/beaninfo/adapters/UICreateRegistryJobHandler.java b/plugins/org.eclipse.jem.beaninfo/beaninfo/org/eclipse/jem/internal/beaninfo/adapters/UICreateRegistryJobHandler.java index ef99d63..4927c34 100644 --- a/plugins/org.eclipse.jem.beaninfo/beaninfo/org/eclipse/jem/internal/beaninfo/adapters/UICreateRegistryJobHandler.java +++ b/plugins/org.eclipse.jem.beaninfo/beaninfo/org/eclipse/jem/internal/beaninfo/adapters/UICreateRegistryJobHandler.java
@@ -10,15 +10,19 @@ *******************************************************************************/ /* * $RCSfile: UICreateRegistryJobHandler.java,v $ - * $Revision: 1.2 $ $Date: 2004/06/02 19:42:39 $ + * $Revision: 1.3 $ $Date: 2004/06/04 15:29:34 $ */ package org.eclipse.jem.internal.beaninfo.adapters; -import org.eclipse.core.runtime.*; -import org.eclipse.core.runtime.NullProgressMonitor; -import org.eclipse.core.runtime.jobs.Job; +import java.lang.reflect.InvocationTargetException; +import java.util.logging.Level; + +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.jface.operation.IRunnableWithProgress; import org.eclipse.swt.widgets.Display; import org.eclipse.ui.PlatformUI; + +import org.eclipse.jem.internal.beaninfo.core.BeaninfoPlugin; /** @@ -26,8 +30,8 @@ * loaded except if ui plugin is available. * * It will check to see if UI is running, and if it is not, then let super class handle. - * If it is running, then if this is the UI thread, just do the creation, else if not - * UI thread, create a job that will do a syncexec to the ui thread to do it. + * If it is running, then if this is the UI thread, use progress service, else if not then + * let super handle it normally. * * @since 1.0.0 */ @@ -40,30 +44,25 @@ */ protected void processCreateRegistry(final BeaninfoNature nature) { if (PlatformUI.isWorkbenchRunning()) { - final Display display = PlatformUI.getWorkbench().getDisplay(); - if (display.getThread() == Thread.currentThread()) - doCreateRegistry(nature, new NullProgressMonitor()); // We are in the UI thread, so just do it. + if (Display.getCurrent() == null) + super.processCreateRegistry(nature); // We are not in the UI thread. Do normal. else { - // We are not in the UI thread, so farm it off to a job to syncit. - // Use it as a job so that if it takes long enough, the progress view will be shown. - Job createJob = new Job(BeanInfoAdapterMessages.getString("UICreateRegistryJobHandler.StartBeaninfoRegistry")) { //$NON-NLS-1$ - protected IStatus run(final IProgressMonitor monitor) { - display.syncExec(new Runnable() { - public void run() { - doCreateRegistry(nature, monitor); - } - }); - return Status.OK_STATUS; - } - }; - createJob.schedule(); - while (true) { - try { - createJob.join(); - break; - } catch (InterruptedException e) { - } + // We are in the UI, so use the progress service to farm off to another thread and keep the UI active, though disabled. + try { + PlatformUI.getWorkbench().getProgressService().busyCursorWhile(new IRunnableWithProgress() { + + public void run(IProgressMonitor monitor) throws InterruptedException { + doCreateRegistry(nature, monitor); + if (monitor.isCanceled()) + throw new InterruptedException(); + } + }); + } catch (InvocationTargetException e) { + BeaninfoPlugin.getPlugin().getLogger().log(e.getCause(), Level.WARNING); + } catch (InterruptedException e) { + // It was cancelled, so we just go on and launch. } + } } else super.processCreateRegistry(nature); // Workbench not running, do default.
diff --git a/plugins/org.eclipse.jem.beaninfo/plugin.xml b/plugins/org.eclipse.jem.beaninfo/plugin.xml index c122fc7..027d8b2 100644 --- a/plugins/org.eclipse.jem.beaninfo/plugin.xml +++ b/plugins/org.eclipse.jem.beaninfo/plugin.xml
@@ -28,6 +28,7 @@ <import plugin="org.eclipse.osgi"/> <import plugin="org.eclipse.ui" optional="true"/> <import plugin="org.eclipse.core.runtime"/> + <import plugin="org.eclipse.debug.core"/> </requires>
diff --git a/plugins/org.eclipse.jem.proxy/plugin.xml b/plugins/org.eclipse.jem.proxy/plugin.xml index 2ab3d62..c5a95ec 100644 --- a/plugins/org.eclipse.jem.proxy/plugin.xml +++ b/plugins/org.eclipse.jem.proxy/plugin.xml
@@ -37,10 +37,11 @@ <import plugin="org.eclipse.core.resources"/> <import plugin="org.eclipse.jdt.launching"/> <import plugin="org.eclipse.jdt.core"/> - <import plugin="org.eclipse.debug.core" export="true"/> + <import plugin="org.eclipse.debug.core"/> <import plugin="com.ibm.wtp.common.util"/> <import plugin="org.eclipse.pde.core"/> <import plugin="org.eclipse.core.runtime"/> + <import plugin="org.eclipse.ui" optional="true"/> </requires>
diff --git a/plugins/org.eclipse.jem.proxy/proxy/org/eclipse/jem/internal/proxy/core/IUIRunner.java b/plugins/org.eclipse.jem.proxy/proxy/org/eclipse/jem/internal/proxy/core/IUIRunner.java new file mode 100644 index 0000000..351a9c7 --- /dev/null +++ b/plugins/org.eclipse.jem.proxy/proxy/org/eclipse/jem/internal/proxy/core/IUIRunner.java
@@ -0,0 +1,40 @@ +/******************************************************************************* + * Copyright (c) 2004 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +/* + * $RCSfile: IUIRunner.java,v $ + * $Revision: 1.1 $ $Date: 2004/06/04 15:29:38 $ + */ +package org.eclipse.jem.internal.proxy.core; + +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IProgressMonitor; + + +/** + * Interface that doesn't require UI. The implementation will. This will + * only be used if within UI environment. + * + * <package-protected> because should only be used within here. + * + * @since 1.0.0 + */ +interface IUIRunner { + /** + * Handle the build. If not in UI thread, just call back to ProxyLaunchSupport + * to handle the build. If on UI thread, then use the IProgressService to do it. + * This will keep the UI from "locking", though it will be disabled it won't deadlock. + * + * @param pm + * + * @since 1.0.0 + */ + public void handleBuild(IProgressMonitor pm) throws CoreException; +}
diff --git a/plugins/org.eclipse.jem.proxy/proxy/org/eclipse/jem/internal/proxy/core/ProxyLaunchSupport.java b/plugins/org.eclipse.jem.proxy/proxy/org/eclipse/jem/internal/proxy/core/ProxyLaunchSupport.java index 43b3a07..ee5450b 100644 --- a/plugins/org.eclipse.jem.proxy/proxy/org/eclipse/jem/internal/proxy/core/ProxyLaunchSupport.java +++ b/plugins/org.eclipse.jem.proxy/proxy/org/eclipse/jem/internal/proxy/core/ProxyLaunchSupport.java
@@ -10,15 +10,17 @@ *******************************************************************************/ /* * $RCSfile: ProxyLaunchSupport.java,v $ - * $Revision: 1.9 $ $Date: 2004/06/02 19:58:49 $ + * $Revision: 1.10 $ $Date: 2004/06/04 15:29:38 $ */ package org.eclipse.jem.internal.proxy.core; import java.text.MessageFormat; import java.util.*; +import java.util.logging.Level; import org.eclipse.core.resources.*; import org.eclipse.core.runtime.*; +import org.eclipse.core.runtime.jobs.IJobManager; import org.eclipse.core.runtime.jobs.Job; import org.eclipse.debug.core.*; import org.eclipse.jdt.core.*; @@ -197,23 +199,52 @@ /** * Start an implementation using the default config for the given project. + * <p> + * This will wait for build. If you + * know the build has been suspended by your thread, then you must use the other method that takes a waitForThread + * boolean, and you must pass in false. Otherwise it will deadlock. * * @param project The project. It must be a java project, and it cannot be <code>null</code>. - * @param vmTitle + * @param vmTitle title for VM. It may be <code>null</code>. * @param aContribs The contributions array. It may be <code>null</code>. * @param pm * @return The created registry. * @throws CoreException * + * @see ProxyLaunchSupport#startImplementation(IProject, String, IConfigurationContributor[], boolean, IProgressMonitor) + * @since 1.0.0 + */ + public static ProxyFactoryRegistry startImplementation( + IProject project, + String vmTitle, + IConfigurationContributor[] aContribs, + IProgressMonitor pm) + throws CoreException { + return startImplementation(project, vmTitle, aContribs, true, pm); + } + + /** + * Start an implementation using the default config for the given project. + * <p> + * If you know the build has been suspended by your thread, then you must use call this with false for waitForThread. Otherwise it will deadlock. + * + * @param project The project. It must be a java project, and it cannot be <code>null</code>. + * @param vmTitle title for VM. It may be <code>null</code>. + * @param aContribs The contributions array. It may be <code>null</code>. + * @param waitForBuild wait for the build. If caller knows that the build has been suspended by this thread, then it must call this with false. Otherwise a deadlock will occur. + * @param pm + * @return The created registry. + * @throws CoreException + * * @since 1.0.0 */ public static ProxyFactoryRegistry startImplementation( IProject project, String vmTitle, IConfigurationContributor[] aContribs, + boolean waitForBuild, IProgressMonitor pm) throws CoreException { - // First find the appropriate launch configuration to use for this project. // The process is: // 1) See if the project's persistent property has a setting for "proxyLaunchConfiguration", if it does, @@ -257,18 +288,24 @@ config = configwc; } - return startImplementation(config, vmTitle, aContribs, pm); + return startImplementation(config, vmTitle, aContribs, waitForBuild, pm); } /** * Launch a registry using the given configuration. + * <p> + * This will wait for build. If you + * know the build has been suspended by your thread, then you must use the other method that takes a waitForThread + * boolean, and you must pass in false. Otherwise it will deadlock. + * * @param config - * @param vmTitle + * @param vmTitle title for VM. It may be <code>null</code>. * @param aContribs The contributions array. It may be <code>null</code>. * @param pm * @return The registry from this configuration. * @throws CoreException * + * @see ProxyLaunchSupport#startImplementation(ILaunchConfiguration, String, IConfigurationContributor[], boolean, IProgressMonitor) * @since 1.0.0 */ public static ProxyFactoryRegistry startImplementation( @@ -277,18 +314,47 @@ IConfigurationContributor[] aContribs, IProgressMonitor pm) throws CoreException { - + return startImplementation(config, vmTitle, aContribs, true, pm); + } + + /** + * Launch a registry using the given configuration. + * <p> + * If you know the build has been suspended by your thread, then you must use you must pass in false for waitForThread. Otherwise it will deadlock. + * + * @param config + * @param vmTitle title for VM. It may be <code>null</code>. + * @param aContribs The contributions array. It may be <code>null</code>. + * @param waitForBuild wait for the build. If caller knows that the build has been suspended by this thread, then it must call this with false. Otherwise a deadlock will occur. + * @param pm + * @return The registry from this configuration. + * @throws CoreException + * + * @since 1.0.0 + */ + public static ProxyFactoryRegistry startImplementation( + ILaunchConfiguration config, + String vmTitle, + IConfigurationContributor[] aContribs, + boolean waitForBuild, + IProgressMonitor pm) + throws CoreException { + if (pm == null) pm = new NullProgressMonitor(); final ILaunchConfigurationWorkingCopy configwc = config.getWorkingCopy(); - // See if build needed or waiting or inprogress, if so, wait for it to complete. We've - // decided - // too difficult to determine if build would affect us or not, so just wait. pm.beginTask("", 400); - pm.subTask(ProxyMessages.getString("ProxyLaunch")); //$NON-NLS-1$ - handleBuild(new SubProgressMonitor(pm, 100)); + pm.subTask(ProxyMessages.getString("ProxyLaunch")); //$NON-NLS-1$ + if (waitForBuild) { + // See if build needed or waiting or inprogress, if so, wait for it to complete. We've + // decided too difficult to determine if build would affect us or not, so just wait. + if (UI_RUNNER != null) + UI_RUNNER.handleBuild(new SubProgressMonitor(pm, 100)); + else + runBuild(new SubProgressMonitor(pm, 100)); + } if (aContribs != null) { IConfigurationContributor[] newContribs = new IConfigurationContributor[aContribs.length+1]; @@ -439,20 +505,35 @@ return launchInfo.resultRegistry; } - private static void handleBuild(IProgressMonitor pm) throws CoreException { + /* + * Run the build. If the original launch was in the UI thread, this will + * be called under control of an IProgressService so that it is in a separate + * thread and the UI will remain responsive (in that either a busy cursor comes + * up or eventually a progress dialog). + * <package-protected> so that only the UI handler will access it. + */ + static void runBuild(IProgressMonitor pm) throws CoreException { boolean autobuilding = ResourcesPlugin.getWorkspace().isAutoBuilding(); if (!autobuilding) { // We are not autobuilding. So kick off a build right here and - // wait for it. + // wait for it. (If we already within a build on this thread, then this + // will return immediately without building. We will take that risk. If + // some other thread is building, we will wait for it finish before we + // can get it and do our build. ResourcesPlugin.getWorkspace().build(IncrementalProjectBuilder.INCREMENTAL_BUILD, pm); } else { - Job[] build = Platform.getJobManager().find(ResourcesPlugin.FAMILY_AUTO_BUILD); - pm.beginTask("", 100); - if (build.length == 1) { - if (build[0].getState() == Job.RUNNING || build[0].getState() == Job.WAITING || build[0].getState() == Job.SLEEPING) { + pm.beginTask("", 200); //$NON-NLS-1$ + IJobManager jobManager = Platform.getJobManager(); + Job currentJob = jobManager.currentJob(); + if (currentJob == null || (!currentJob.belongsTo(ResourcesPlugin.FAMILY_AUTO_BUILD) && !currentJob.belongsTo(ResourcesPlugin.FAMILY_MANUAL_BUILD))) { + if (jobManager.find(ResourcesPlugin.FAMILY_AUTO_BUILD).length > 0 || jobManager.find(ResourcesPlugin.FAMILY_MANUAL_BUILD).length >0) { + // We are not within a build job. If we were, then we don't do the build. We will take + // that risk. The problem is that if within the build, we can't wait for it to finish because + // we would stop the thread and so the build would not complete. pm.subTask(ProxyMessages.getString("ProxyWaitForBuild")); //$NON-NLS-1$ try { - build[0].join(); + jobManager.join(ResourcesPlugin.FAMILY_AUTO_BUILD, new SubProgressMonitor(pm, 100)); + jobManager.join(ResourcesPlugin.FAMILY_MANUAL_BUILD, new SubProgressMonitor(pm, 100)); } catch (InterruptedException e) { throw new CoreException( new Status(IStatus.ERROR, ProxyPlugin.getPlugin().getBundle().getSymbolicName(), IStatus.ERROR, "", e)); //$NON-NLS-1$ @@ -470,6 +551,7 @@ * public but only so that launch delegate can get to it. */ public static String ATTR_PRIVATE; + private static IUIRunner UI_RUNNER = null; static { ATTR_PRIVATE = null; try { @@ -479,6 +561,16 @@ Class debugUIConstants = debuguiBundle.loadClass("org.eclipse.debug.ui.IDebugUIConstants"); //$NON-NLS-1$ ATTR_PRIVATE = (String) debugUIConstants.getField("ATTR_PRIVATE").get(null); //$NON-NLS-1$ } + + Bundle uiBundle = Platform.getBundle("org.eclipse.ui"); //$NON-NLS-1$ + if (uiBundle != null) { + try { + // We have a UI bundle, so we can load our UIRunner class and it will load fine. + UI_RUNNER = (IUIRunner) Class.forName("org.eclipse.jem.internal.proxy.core.UIRunner").newInstance(); //$NON-NLS-1$ + } catch (InstantiationException e1) { + ProxyPlugin.getPlugin().getLogger().log(e1, Level.WARNING); + } + } } catch (SecurityException e) { } catch (ClassNotFoundException e) { } catch (NoSuchFieldException e) {
diff --git a/plugins/org.eclipse.jem.proxy/proxy/org/eclipse/jem/internal/proxy/core/UIRunner.java b/plugins/org.eclipse.jem.proxy/proxy/org/eclipse/jem/internal/proxy/core/UIRunner.java new file mode 100644 index 0000000..ebccc77 --- /dev/null +++ b/plugins/org.eclipse.jem.proxy/proxy/org/eclipse/jem/internal/proxy/core/UIRunner.java
@@ -0,0 +1,69 @@ +/******************************************************************************* + * Copyright (c) 2004 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +/* + * $RCSfile: UIRunner.java,v $ + * $Revision: 1.1 $ $Date: 2004/06/04 15:29:37 $ + */ +package org.eclipse.jem.internal.proxy.core; + +import java.lang.reflect.InvocationTargetException; +import java.util.logging.Level; + +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.jface.operation.IRunnableWithProgress; +import org.eclipse.swt.widgets.Display; +import org.eclipse.ui.PlatformUI; + + +/** + * The actual implementation of IUIRunner to run the build under + * IProgressService control if in the UI thread. + * + * <package-protected> because should only be used within here. + * + * @since 1.0.0 + */ +class UIRunner implements IUIRunner, IRunnableWithProgress { + /* (non-Javadoc) + * @see org.eclipse.jem.internal.proxy.core.IUIRunner#handleBuild(org.eclipse.core.runtime.IProgressMonitor) + */ + public void handleBuild(IProgressMonitor pm) throws CoreException { + if (!PlatformUI.isWorkbenchRunning() || Display.getCurrent() == null) { + ProxyLaunchSupport.runBuild(pm); + } else { + pm.beginTask("", 100); //$NON-NLS-1$ + try { + PlatformUI.getWorkbench().getProgressService().busyCursorWhile(this); + } catch (InvocationTargetException e) { + if (e.getCause() instanceof CoreException) + throw (CoreException) e.getCause(); + ProxyPlugin.getPlugin().getLogger().log(e.getCause(), Level.WARNING); + } catch (InterruptedException e) { + // It was cancelled, so we just go on and launch. + } + pm.done(); + } + } + /* (non-Javadoc) + * @see org.eclipse.jface.operation.IRunnableWithProgress#run(org.eclipse.core.runtime.IProgressMonitor) + */ + public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException { + try { + ProxyLaunchSupport.runBuild(monitor); + } catch (CoreException e) { + throw new InvocationTargetException(e); + } + if (monitor.isCanceled()) { + throw new InterruptedException(); + } + } +}