001: /*******************************************************************************
002: * Copyright (c) 2000, 2006 IBM Corporation and others.
003: * All rights reserved. This program and the accompanying materials
004: * are made available under the terms of the Eclipse Public License v1.0
005: * which accompanies this distribution, and is available at
006: * http://www.eclipse.org/legal/epl-v10.html
007: *
008: * Contributors:
009: * IBM Corporation - initial API and implementation
010: *******************************************************************************/package org.eclipse.ui.actions;
011:
012: import org.eclipse.core.resources.IProject;
013: import org.eclipse.core.resources.IncrementalProjectBuilder;
014: import org.eclipse.core.resources.ResourcesPlugin;
015: import org.eclipse.core.runtime.CoreException;
016: import org.eclipse.core.runtime.IProgressMonitor;
017: import org.eclipse.core.runtime.IStatus;
018: import org.eclipse.core.runtime.MultiStatus;
019: import org.eclipse.core.runtime.Platform;
020: import org.eclipse.core.runtime.SubProgressMonitor;
021: import org.eclipse.core.runtime.jobs.Job;
022: import org.eclipse.jface.action.Action;
023: import org.eclipse.jface.dialogs.ErrorDialog;
024: import org.eclipse.jface.dialogs.MessageDialog;
025: import org.eclipse.osgi.util.NLS;
026: import org.eclipse.swt.widgets.Shell;
027: import org.eclipse.ui.IWorkbench;
028: import org.eclipse.ui.IWorkbenchWindow;
029: import org.eclipse.ui.PlatformUI;
030: import org.eclipse.ui.internal.ide.IDEInternalWorkbenchImages;
031: import org.eclipse.ui.internal.ide.IDEWorkbenchMessages;
032: import org.eclipse.ui.internal.ide.IDEWorkbenchPlugin;
033: import org.eclipse.ui.internal.ide.IIDEHelpContextIds;
034: import org.eclipse.ui.internal.ide.actions.BuildUtilities;
035:
036: /**
037: * Standard action for full and incremental builds of all projects within the
038: * workspace.
039: * <p>
040: * This class may be instantiated; it is not intended to be subclassed.
041: * </p>
042: */
043: public class GlobalBuildAction extends Action implements
044: ActionFactory.IWorkbenchAction {
045: /**
046: * The type of build performed by this action. Can be either
047: * <code>IncrementalProjectBuilder.INCREMENTAL_BUILD</code> or
048: * <code>IncrementalProjectBuilder.FULL_BUILD</code>.
049: */
050: private int buildType;
051:
052: /**
053: * The workbench window; or <code>null</code> if this action has been
054: * <code>dispose</code>d.
055: */
056: private IWorkbenchWindow workbenchWindow;
057:
058: /**
059: * Creates a new action of the appropriate type. The action id is
060: * <code>IWorkbenchActionConstants.BUILD</code> for incremental builds and
061: * <code>IWorkbenchActionConstants.REBUILD_ALL</code> for full builds.
062: *
063: * @param workbench
064: * the active workbench
065: * @param shell
066: * the shell for any dialogs
067: * @param type
068: * the type of build; one of
069: * <code>IncrementalProjectBuilder.INCREMENTAL_BUILD</code> or
070: * <code>IncrementalProjectBuilder.FULL_BUILD</code>
071: *
072: * @deprecated use GlobalBuildAction(IWorkbenchWindow, type) instead
073: */
074: public GlobalBuildAction(IWorkbench workbench, Shell shell, int type) {
075: // always use active window; ignore shell
076: this (workbench.getActiveWorkbenchWindow(), type);
077: if (shell == null) {
078: throw new IllegalArgumentException();
079: }
080: }
081:
082: /**
083: * Creates a new action of the appropriate type. The action id is
084: * <code>IWorkbenchActionConstants.BUILD</code> for incremental builds and
085: * <code>IWorkbenchActionConstants.REBUILD_ALL</code> for full builds.
086: *
087: * @param window
088: * the window in which this action appears
089: * @param type
090: * the type of build; one of
091: * <code>IncrementalProjectBuilder.INCREMENTAL_BUILD</code> or
092: * <code>IncrementalProjectBuilder.FULL_BUILD</code>
093: */
094: public GlobalBuildAction(IWorkbenchWindow window, int type) {
095: if (window == null) {
096: throw new IllegalArgumentException();
097: }
098: this .workbenchWindow = window;
099: setBuildType(type);
100: }
101:
102: /**
103: * Sets the build type.
104: *
105: * @param type
106: * the type of build; one of
107: * <code>IncrementalProjectBuilder.INCREMENTAL_BUILD</code> or
108: * <code>IncrementalProjectBuilder.FULL_BUILD</code>
109: */
110: private void setBuildType(int type) {
111: // allow AUTO_BUILD as well for backwards compatibility, but treat it
112: // the same as INCREMENTAL_BUILD
113: switch (type) {
114: case IncrementalProjectBuilder.INCREMENTAL_BUILD:
115: case IncrementalProjectBuilder.AUTO_BUILD:
116: setText(IDEWorkbenchMessages.GlobalBuildAction_text);
117: setToolTipText(IDEWorkbenchMessages.GlobalBuildAction_toolTip);
118: setId("build"); //$NON-NLS-1$
119: workbenchWindow.getWorkbench().getHelpSystem().setHelp(
120: this ,
121: IIDEHelpContextIds.GLOBAL_INCREMENTAL_BUILD_ACTION);
122: setImageDescriptor(IDEInternalWorkbenchImages
123: .getImageDescriptor(IDEInternalWorkbenchImages.IMG_ETOOL_BUILD_EXEC));
124: setDisabledImageDescriptor(IDEInternalWorkbenchImages
125: .getImageDescriptor(IDEInternalWorkbenchImages.IMG_ETOOL_BUILD_EXEC_DISABLED));
126: setActionDefinitionId("org.eclipse.ui.project.buildAll"); //$NON-NLS-1$
127: break;
128: case IncrementalProjectBuilder.FULL_BUILD:
129: setText(IDEWorkbenchMessages.GlobalBuildAction_rebuildText);
130: setToolTipText(IDEWorkbenchMessages.GlobalBuildAction_rebuildToolTip);
131: setId("rebuildAll"); //$NON-NLS-1$
132: workbenchWindow.getWorkbench().getHelpSystem().setHelp(
133: this , IIDEHelpContextIds.GLOBAL_FULL_BUILD_ACTION);
134: setActionDefinitionId("org.eclipse.ui.project.rebuildAll"); //$NON-NLS-1$
135: break;
136: default:
137: throw new IllegalArgumentException("Invalid build type"); //$NON-NLS-1$
138: }
139: this .buildType = type;
140: }
141:
142: /**
143: * Returns the shell to use.
144: */
145: private Shell getShell() {
146: return workbenchWindow.getShell();
147: }
148:
149: /**
150: * Returns the operation name to use
151: */
152: private String getOperationMessage() {
153: if (buildType == IncrementalProjectBuilder.INCREMENTAL_BUILD) {
154: return IDEWorkbenchMessages.GlobalBuildAction_buildOperationTitle;
155: }
156: return IDEWorkbenchMessages.GlobalBuildAction_rebuildAllOperationTitle;
157: }
158:
159: /**
160: * Builds all projects within the workspace. Does not save any open editors.
161: */
162: public void doBuild() {
163: doBuildOperation();
164: }
165:
166: /**
167: * Invokes a build on all projects within the workspace. Reports any errors
168: * with the build to the user.
169: */
170: /* package */void doBuildOperation() {
171: Job buildJob = new Job(
172: IDEWorkbenchMessages.GlobalBuildAction_jobTitle) {
173: /*
174: * (non-Javadoc)
175: *
176: * @see org.eclipse.core.runtime.jobs.Job#run(org.eclipse.core.runtime.IProgressMonitor)
177: */
178: protected IStatus run(IProgressMonitor monitor) {
179: final MultiStatus status = new MultiStatus(
180: PlatformUI.PLUGIN_ID,
181: 0,
182: IDEWorkbenchMessages.GlobalBuildAction_buildProblems,
183: null);
184: monitor.beginTask(getOperationMessage(), 100);
185: try {
186: ResourcesPlugin.getWorkspace().build(buildType,
187: new SubProgressMonitor(monitor, 100));
188: } catch (CoreException e) {
189: status.add(e.getStatus());
190: } finally {
191: monitor.done();
192: }
193: return status;
194: }
195:
196: /*
197: * (non-Javadoc)
198: *
199: * @see org.eclipse.core.runtime.jobs.Job#belongsTo(java.lang.Object)
200: */
201: public boolean belongsTo(Object family) {
202: return ResourcesPlugin.FAMILY_MANUAL_BUILD == family;
203: }
204: };
205: buildJob.setRule(ResourcesPlugin.getWorkspace()
206: .getRuleFactory().buildRule());
207: buildJob.setUser(true);
208: buildJob.schedule();
209: }
210:
211: /**
212: * Returns an array of all projects in the workspace
213: */
214: /* package */IProject[] getWorkspaceProjects() {
215: return ResourcesPlugin.getWorkspace().getRoot().getProjects();
216: }
217:
218: /*
219: * (non-Javadoc) Method declared on IAction.
220: *
221: * Builds all projects within the workspace. Saves all editors prior to
222: * build depending on user's preference.
223: */
224: public void run() {
225: if (workbenchWindow == null) {
226: // action has been disposed
227: return;
228: }
229: // Do nothing if there are no projects...
230: IProject[] roots = getWorkspaceProjects();
231: if (roots.length < 1) {
232: return;
233: }
234: // Verify that there are builders registered on at
235: // least one project
236: if (!verifyBuildersAvailable(roots)) {
237: return;
238: }
239: if (!verifyNoManualRunning()) {
240: return;
241: }
242: // Save all resources prior to doing build
243: BuildUtilities.saveEditors(null);
244: // Perform the build on all the projects
245: doBuildOperation();
246: }
247:
248: /**
249: * Checks that there is at least one project with a builder registered on
250: * it.
251: */
252: /* package */boolean verifyBuildersAvailable(IProject[] roots) {
253: try {
254: for (int i = 0; i < roots.length; i++) {
255: if (roots[i].isAccessible()) {
256: if (roots[i].getDescription().getBuildSpec().length > 0) {
257: return true;
258: }
259: }
260: }
261: } catch (CoreException e) {
262: IDEWorkbenchPlugin.log(getClass(),
263: "verifyBuildersAvailable", e); //$NON-NLS-1$
264: ErrorDialog
265: .openError(
266: getShell(),
267: IDEWorkbenchMessages.GlobalBuildAction_buildProblems,
268: NLS
269: .bind(
270: IDEWorkbenchMessages.GlobalBuildAction_internalError,
271: e.getMessage()), e
272: .getStatus());
273: return false;
274: }
275: return false;
276: }
277:
278: /*
279: * (non-Javadoc) Method declared on ActionFactory.IWorkbenchAction.
280: *
281: * @since 3.0
282: */
283: public void dispose() {
284: if (workbenchWindow == null) {
285: // action has already been disposed
286: return;
287: }
288: workbenchWindow = null;
289: }
290:
291: /**
292: * Verify that no manual build is running. If it is then give the use the
293: * option to cancel. If they cancel, cancel the jobs and return true,
294: * otherwise return false.
295: *
296: * @return whether or not there is a manual build job running.
297: */
298: private boolean verifyNoManualRunning() {
299: Job[] buildJobs = Platform.getJobManager().find(
300: ResourcesPlugin.FAMILY_MANUAL_BUILD);
301: if (buildJobs.length == 0) {
302: return true;
303: }
304: boolean cancel = MessageDialog
305: .openQuestion(
306: workbenchWindow.getShell(),
307: IDEWorkbenchMessages.GlobalBuildAction_BuildRunningTitle,
308: IDEWorkbenchMessages.GlobalBuildAction_BuildRunningMessage);
309: if (cancel) {
310: for (int i = 0; i < buildJobs.length; i++) {
311: Job job = buildJobs[i];
312: job.cancel();
313: }
314: }
315: //If they cancelled get them to do it again.
316: return false;
317: }
318: }
|