/*******************************************************************************
* Copyright (c) 2006, 2014 Texas Instruments Incorporated 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:
* Texas Instruments - initial API and implementation
* Sergey Prigogin (Google)
*******************************************************************************/
package org.eclipse.cdt.managedbuilder.internal.ui.commands;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import org.eclipse.cdt.internal.core.AdapterUtil;
import org.eclipse.cdt.internal.ui.util.AbstractResourceActionHandler;
import org.eclipse.cdt.managedbuilder.core.IManagedBuildInfo;
import org.eclipse.cdt.managedbuilder.core.ManagedBuildManager;
import org.eclipse.cdt.managedbuilder.internal.core.GeneratedMakefileBuilder;
import org.eclipse.cdt.managedbuilder.makegen.IManagedBuilderMakefileGenerator;
import org.eclipse.core.commands.ExecutionEvent;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.core.resources.ICommand;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.core.runtime.preferences.IPreferencesService;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.ui.internal.ide.actions.BuildUtilities;
public class BuildFilesHandler extends AbstractResourceActionHandler {
@Override
public Object execute(ExecutionEvent event) throws ExecutionException {
List<IFile> selectedFiles = getSelectedFiles(event);
if (selectedFiles.isEmpty())
return null;
Job buildFilesJob = new BuildFilesJob(selectedFiles);
Collection<IProject> projects = getProjectsToBuild(selectedFiles);
BuildUtilities.saveEditors(projects); // Save all resources prior to doing build.
buildFilesJob.schedule();
return null;
}
@Override
public void setEnabled(Object evaluationContext) {
super.setEnabled(evaluationContext);
setBaseEnabled(shouldBeEnabled());
}
private boolean shouldBeEnabled() {
// Fix for bug 139663.
// If build automatically is turned on, then this command should be turned off as
// it will trigger the auto build.
IPreferencesService preferences = Platform.getPreferencesService();
if (preferences.getBoolean(ResourcesPlugin.PI_RESOURCES, ResourcesPlugin.PREF_AUTO_BUILDING,
false, null)) {
// Auto building is on - do not enable the command.
return false;
}
IStructuredSelection selection = getSelection();
if (selection.isEmpty())
return false;
for (Iterator<?> elements = selection.iterator(); elements.hasNext();) {
IFile file = AdapterUtil.adapt(elements.next(), IFile.class);
if (file == null)
return false;
// We only add files that we can actually build.
if (!ManagedBuildManager.manages(file.getProject()))
return false;
IManagedBuildInfo buildInfo = ManagedBuildManager.getBuildInfo(file.getProject());
if (buildInfo == null || !buildInfo.isValid()
|| buildInfo.getDefaultConfiguration() == null
|| !buildInfo.getDefaultConfiguration().isManagedBuildOn()) {
return false;
}
IManagedBuilderMakefileGenerator buildfileGenerator =
ManagedBuildManager.getBuildfileGenerator(buildInfo.getDefaultConfiguration());
if (buildfileGenerator == null)
return false;
// Make sure build file generator is initialized.
buildfileGenerator.initialize(file.getProject(), buildInfo, new NullProgressMonitor());
// If we have no build info or we can't build the file, then disable the command.
if (!buildInfo.buildsFileType(file.getFileExtension())
|| buildfileGenerator.isGeneratedResource(file)) {
return false;
}
}
return true;
}
private List<IFile> getSelectedFiles(ExecutionEvent event) throws ExecutionException {
Collection<IResource> selectedResources = getSelectedResources(event);
List<IFile> files = new ArrayList<>(selectedResources.size());
for (IResource resource : selectedResources) {
if (resource instanceof IFile)
files.add((IFile) resource);
}
return files;
}
/*
* Returns the projects to build. These are the projects which have builders,
* across all selected resources.
*/
private Collection<IProject> getProjectsToBuild(List<IFile> selectedFiles) {
Set<IProject> projectsToBuild = new HashSet<IProject>();
for (IFile file : selectedFiles) {
IProject project = file.getProject();
if (!projectsToBuild.contains(project)) {
if (hasBuilder(project)) {
projectsToBuild.add(project);
}
}
}
return projectsToBuild;
}
/*
* Checks whether there are builders configured on the given project.
*
* @return {@code true} if it has builders, {@code false} if not, or if this couldn't be
* determined
*/
private boolean hasBuilder(IProject project) {
if (!project.isAccessible())
return false;
try {
ICommand[] commands = project.getDescription().getBuildSpec();
if (commands.length > 0)
return true;
} catch (CoreException e) {
// This method is called when selection changes, so just fall through if it
// fails. This shouldn't happen anyway, since the list of selected resources
// has already been checked for accessibility before this is called.
}
return false;
}
private static class BuildFilesJob extends Job {
private final List<IFile> files;
BuildFilesJob(List<IFile> filesToBuild) {
super(Messages.BuildFilesHandler_buildingSelectedFiles);
files = filesToBuild;
}
@Override
protected IStatus run(IProgressMonitor monitor) {
GeneratedMakefileBuilder builder = new GeneratedMakefileBuilder();
return builder.invokeInternalBuilder(files, monitor);
}
@Override
public boolean belongsTo(Object family) {
return ResourcesPlugin.FAMILY_MANUAL_BUILD == family;
}
}
}