| /******************************************************************************* |
| * Copyright (c) 2000, 2015 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 |
| * Anton Leherbauer (Wind River) - [296800] UI build actions should not lock the workspace |
| *******************************************************************************/ |
| package org.eclipse.ui.actions; |
| |
| import org.eclipse.core.resources.IProject; |
| import org.eclipse.core.resources.IncrementalProjectBuilder; |
| import org.eclipse.core.resources.ResourcesPlugin; |
| import org.eclipse.core.runtime.Assert; |
| import org.eclipse.core.runtime.CoreException; |
| import org.eclipse.core.runtime.IProgressMonitor; |
| import org.eclipse.core.runtime.IStatus; |
| import org.eclipse.core.runtime.Status; |
| import org.eclipse.core.runtime.SubMonitor; |
| import org.eclipse.core.runtime.jobs.Job; |
| import org.eclipse.jface.action.Action; |
| import org.eclipse.jface.dialogs.ErrorDialog; |
| import org.eclipse.jface.dialogs.MessageDialog; |
| import org.eclipse.osgi.util.NLS; |
| import org.eclipse.swt.widgets.Shell; |
| import org.eclipse.ui.IWorkbench; |
| import org.eclipse.ui.IWorkbenchCommandConstants; |
| import org.eclipse.ui.IWorkbenchWindow; |
| import org.eclipse.ui.internal.ide.IDEInternalWorkbenchImages; |
| import org.eclipse.ui.internal.ide.IDEWorkbenchMessages; |
| import org.eclipse.ui.internal.ide.IDEWorkbenchPlugin; |
| import org.eclipse.ui.internal.ide.IIDEHelpContextIds; |
| import org.eclipse.ui.internal.ide.actions.BuildUtilities; |
| import org.eclipse.ui.progress.IProgressConstants2; |
| import org.eclipse.ui.statushandlers.StatusManager; |
| |
| /** |
| * Standard action for full and incremental builds of all projects within the |
| * workspace. |
| * <p> |
| * This class may be instantiated; it is not intended to be subclassed. |
| * </p> |
| * @noextend This class is not intended to be subclassed by clients. |
| */ |
| public class GlobalBuildAction extends Action implements |
| ActionFactory.IWorkbenchAction { |
| /** |
| * The type of build performed by this action. Can be either |
| * <code>IncrementalProjectBuilder.INCREMENTAL_BUILD</code> or |
| * <code>IncrementalProjectBuilder.FULL_BUILD</code>. |
| */ |
| private int buildType; |
| |
| /** |
| * The workbench window; or <code>null</code> if this action has been |
| * <code>dispose</code>d. |
| */ |
| private IWorkbenchWindow workbenchWindow; |
| |
| /** |
| * Creates a new action of the appropriate type. The action id is |
| * <code>IWorkbenchActionConstants.BUILD</code> for incremental builds and |
| * <code>IWorkbenchActionConstants.REBUILD_ALL</code> for full builds. |
| * |
| * @param workbench |
| * the active workbench |
| * @param shell |
| * the shell for any dialogs |
| * @param type |
| * the type of build; one of |
| * <code>IncrementalProjectBuilder.INCREMENTAL_BUILD</code> or |
| * <code>IncrementalProjectBuilder.FULL_BUILD</code> |
| * |
| * @deprecated use GlobalBuildAction(IWorkbenchWindow, type) instead |
| */ |
| @Deprecated |
| public GlobalBuildAction(IWorkbench workbench, Shell shell, int type) { |
| // always use active window; ignore shell |
| this(workbench.getActiveWorkbenchWindow(), type); |
| Assert.isNotNull(shell); |
| } |
| |
| /** |
| * Creates a new action of the appropriate type. The action id is |
| * <code>IWorkbenchActionConstants.BUILD</code> for incremental builds and |
| * <code>IWorkbenchActionConstants.REBUILD_ALL</code> for full builds. |
| * |
| * @param window |
| * the window in which this action appears |
| * @param type |
| * the type of build; one of |
| * <code>IncrementalProjectBuilder.INCREMENTAL_BUILD</code> or |
| * <code>IncrementalProjectBuilder.FULL_BUILD</code> |
| */ |
| public GlobalBuildAction(IWorkbenchWindow window, int type) { |
| Assert.isNotNull(window); |
| this.workbenchWindow = window; |
| setBuildType(type); |
| } |
| |
| /** |
| * Sets the build type. |
| * |
| * @param type |
| * the type of build; one of |
| * <code>IncrementalProjectBuilder.INCREMENTAL_BUILD</code> or |
| * <code>IncrementalProjectBuilder.FULL_BUILD</code> |
| */ |
| private void setBuildType(int type) { |
| // allow AUTO_BUILD as well for backwards compatibility, but treat it |
| // the same as INCREMENTAL_BUILD |
| switch (type) { |
| case IncrementalProjectBuilder.INCREMENTAL_BUILD: |
| case IncrementalProjectBuilder.AUTO_BUILD: |
| setText(IDEWorkbenchMessages.GlobalBuildAction_text); |
| setToolTipText(IDEWorkbenchMessages.GlobalBuildAction_toolTip); |
| setId("build"); //$NON-NLS-1$ |
| workbenchWindow.getWorkbench().getHelpSystem().setHelp(this, |
| IIDEHelpContextIds.GLOBAL_INCREMENTAL_BUILD_ACTION); |
| setImageDescriptor(IDEInternalWorkbenchImages |
| .getImageDescriptor(IDEInternalWorkbenchImages.IMG_ETOOL_BUILD_EXEC)); |
| setDisabledImageDescriptor(IDEInternalWorkbenchImages |
| .getImageDescriptor(IDEInternalWorkbenchImages.IMG_ETOOL_BUILD_EXEC_DISABLED)); |
| setActionDefinitionId(IWorkbenchCommandConstants.PROJECT_BUILD_ALL); |
| break; |
| case IncrementalProjectBuilder.FULL_BUILD: |
| setText(IDEWorkbenchMessages.GlobalBuildAction_rebuildText); |
| setToolTipText(IDEWorkbenchMessages.GlobalBuildAction_rebuildToolTip); |
| setId("rebuildAll"); //$NON-NLS-1$ |
| workbenchWindow.getWorkbench().getHelpSystem().setHelp(this, |
| IIDEHelpContextIds.GLOBAL_FULL_BUILD_ACTION); |
| setActionDefinitionId("org.eclipse.ui.project.rebuildAll"); //$NON-NLS-1$ |
| break; |
| default: |
| throw new IllegalArgumentException("Invalid build type"); //$NON-NLS-1$ |
| } |
| this.buildType = type; |
| } |
| |
| /** |
| * Returns the shell to use. |
| */ |
| private Shell getShell() { |
| return workbenchWindow.getShell(); |
| } |
| |
| /** |
| * Returns the operation name to use |
| */ |
| private String getOperationMessage() { |
| if (buildType == IncrementalProjectBuilder.INCREMENTAL_BUILD) { |
| return IDEWorkbenchMessages.GlobalBuildAction_buildOperationTitle; |
| } |
| return IDEWorkbenchMessages.GlobalBuildAction_rebuildAllOperationTitle; |
| } |
| |
| /** |
| * Builds all projects within the workspace. Does not save any open editors. |
| */ |
| public void doBuild() { |
| doBuildOperation(); |
| } |
| |
| /** |
| * Invokes a build on all projects within the workspace. Reports any errors |
| * with the build to the user. |
| */ |
| /* package */void doBuildOperation() { |
| Job buildJob = new Job(IDEWorkbenchMessages.GlobalBuildAction_jobTitle) { |
| @Override |
| protected IStatus run(IProgressMonitor monitor) { |
| SubMonitor subMonitor = SubMonitor.convert(monitor, getOperationMessage(), 100); |
| try { |
| ResourcesPlugin.getWorkspace().build(buildType, subMonitor.split(100)); |
| } catch (CoreException e) { |
| return e.getStatus(); |
| } |
| return Status.OK_STATUS; |
| } |
| |
| @Override |
| public boolean belongsTo(Object family) { |
| return ResourcesPlugin.FAMILY_MANUAL_BUILD == family; |
| } |
| }; |
| buildJob.setUser(true); |
| buildJob.setProperty(IProgressConstants2.SHOW_IN_TASKBAR_ICON_PROPERTY, Boolean.TRUE); |
| buildJob.schedule(); |
| } |
| |
| /** |
| * Returns an array of all projects in the workspace |
| */ |
| /* package */IProject[] getWorkspaceProjects() { |
| return ResourcesPlugin.getWorkspace().getRoot().getProjects(); |
| } |
| |
| @Override |
| public void run() { |
| if (workbenchWindow == null) { |
| // action has been disposed |
| return; |
| } |
| // Do nothing if there are no projects... |
| IProject[] roots = getWorkspaceProjects(); |
| if (roots.length < 1) { |
| return; |
| } |
| // Verify that there are builders registered on at |
| // least one project |
| if (!verifyBuildersAvailable(roots)) { |
| return; |
| } |
| if (!verifyNoManualRunning()) { |
| return; |
| } |
| // Save all resources prior to doing build |
| BuildUtilities.saveEditors(null); |
| // Perform the build on all the projects |
| doBuildOperation(); |
| } |
| |
| /** |
| * Checks that there is at least one project with a builder registered on |
| * it. |
| */ |
| /* package */boolean verifyBuildersAvailable(IProject[] roots) { |
| try { |
| for (IProject root : roots) { |
| if (root.isAccessible()) { |
| if (root.getDescription().getBuildSpec().length > 0) { |
| return true; |
| } |
| } |
| } |
| } catch (CoreException e) { |
| StatusManager.getManager().handle(e, IDEWorkbenchPlugin.IDE_WORKBENCH); |
| ErrorDialog |
| .openError( |
| getShell(), |
| IDEWorkbenchMessages.GlobalBuildAction_buildProblems, |
| NLS.bind(IDEWorkbenchMessages.GlobalBuildAction_internalError, e.getMessage()), |
| e.getStatus()); |
| return false; |
| } |
| return false; |
| } |
| |
| @Override |
| public void dispose() { |
| if (workbenchWindow == null) { |
| // action has already been disposed |
| return; |
| } |
| workbenchWindow = null; |
| } |
| |
| /** |
| * Verify that no manual build is running. If it is then give the use the |
| * option to cancel. If they cancel, cancel the jobs and return true, |
| * otherwise return false. |
| * |
| * @return whether or not there is a manual build job running. |
| */ |
| private boolean verifyNoManualRunning() { |
| Job[] buildJobs = Job.getJobManager().find( |
| ResourcesPlugin.FAMILY_MANUAL_BUILD); |
| if (buildJobs.length == 0) { |
| return true; |
| } |
| boolean cancel = MessageDialog.openQuestion(getShell(), |
| IDEWorkbenchMessages.GlobalBuildAction_BuildRunningTitle, |
| IDEWorkbenchMessages.GlobalBuildAction_BuildRunningMessage); |
| if (cancel) { |
| for (Job job : buildJobs) { |
| job.cancel(); |
| } |
| } |
| //If they cancelled get them to do it again. |
| return false; |
| } |
| } |