/******************************************************************************* * Copyright (c) 2014 Pivotal Software, Inc. * 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: * Pivotal Software, Inc. - initial API and implementation *******************************************************************************/ package org.springsource.ide.eclipse.gradle.ui.taskview; import java.util.ArrayList; import java.util.List; import org.eclipse.core.runtime.Assert; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import org.eclipse.jface.viewers.ITreeContentProvider; import org.eclipse.jface.viewers.TreeViewer; import org.eclipse.jface.viewers.Viewer; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Tree; import org.eclipse.swt.widgets.TreeColumn; import org.gradle.tooling.model.GradleTask; import org.gradle.tooling.model.UnsupportedMethodException; import org.gradle.tooling.model.eclipse.EclipseProject; import org.gradle.tooling.model.gradle.BuildInvocations; import org.springsource.ide.eclipse.gradle.core.GradleCore; import org.springsource.ide.eclipse.gradle.core.GradleProject; import org.springsource.ide.eclipse.gradle.core.classpathcontainer.FastOperationFailedException; import org.springsource.ide.eclipse.gradle.core.modelmanager.IGradleModelListener; import org.springsource.ide.eclipse.gradle.core.util.ProjectTasksVisibility; /** * Content provider for displaying tasks tree * * @author Kris De Volder * @author Alex Boyko * */ public class TaskTreeContentProvider implements ITreeContentProvider { private static final Object[] NO_ELEMENTS = new Object[0]; private TreeViewer viewer; private GradleProject currentProject; private boolean isLocalTasks; private boolean isHideInternalTasks; public TaskTreeContentProvider(TreeViewer viewer) { this.viewer = viewer; } public void dispose() { try { if (currentProject!=null) { if (modelListener!=null) { currentProject.removeModelListener(modelListener); } } } finally { currentProject=null; modelListener=null; } } private IGradleModelListener modelListener = new IGradleModelListener() { @Override public <T> void modelChanged(GradleProject p, Class<T> type, T model) { if (currentProject==p && (model instanceof BuildInvocations || model instanceof EclipseProject)) { Display.getDefault().asyncExec(new Runnable() { public void run() { if (viewer!=null) { viewer.refresh(); Tree tree = viewer.getTree(); for (TreeColumn col : tree.getColumns()) { col.pack(); } } } }); } } }; public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { Assert.isTrue(this.viewer == viewer); Assert.isTrue(newInput==null || newInput instanceof GradleProject); setProject((GradleProject)newInput); } private void setProject(GradleProject project) { if (currentProject != project) { if (currentProject != null) { currentProject.removeModelListener(modelListener); } currentProject = project; if (currentProject != null) { currentProject.addModelListener(modelListener); } } } public Object[] getElements(Object inputElement) { GradleProject root = (GradleProject) inputElement; if (root==null) { return NO_ELEMENTS; } else { try { boolean modelNotAvailable = false; /* * Request EclipseProject and BuildInvocations models in * parallel. Swallow the exception and proceed to the next model * request if previous throws FastOperationException */ try { root.requestModel(BuildInvocations.class); } catch (FastOperationFailedException e) { modelNotAvailable = true; } try { root.requestGradleModel(); } catch (FastOperationFailedException e) { modelNotAvailable = true; } GradleTask[] gradleTasks = getGradleTasks(root); return modelNotAvailable ? new Object[] {"model not yet available"} : gradleTasks; } catch (CoreException e) { GradleCore.log(e); return new Object[] {"ERROR: "+e.getMessage()+"", "See error log for details"}; } } } private GradleTask[] getGradleTasks(GradleProject project) { try { EclipseProject eclipseProjectModel = project.getGradleModel(); BuildInvocations buildInvocationsModel = project.getModel(BuildInvocations.class); ProjectTasksVisibility tasksVisibility = null; try { tasksVisibility = new ProjectTasksVisibility(buildInvocationsModel); } catch (UnsupportedMethodException e) { /* * Make all tasks public if Gradle runtime does for the project does not support visibility feature */ GradleTasksViewPlugin .getDefault() .getLog() .log(new Status( IStatus.WARNING, GradleTasksViewPlugin.PLUGIN_ID, "All tasks for project '" + project.getName() + "' will be shown as public because visibility property is unavailable. (Old version of Gradle set for the project)", e)); } List<GradleTask> tasksCollection = new ArrayList<GradleTask>(Math.max(buildInvocationsModel.getTasks().size(), buildInvocationsModel.getTaskSelectors().size())); for (final GradleTask task : isLocalTasks ? GradleProject.getTasks(eclipseProjectModel) : GradleProject.getAggregateTasks(eclipseProjectModel).values()) { boolean publicTask = true; if (tasksVisibility != null) { try { publicTask = isLocalTasks ? tasksVisibility.isTaskPublic(task.getName()) : tasksVisibility.isTaskSelectorPublic(task.getName()); } catch (IllegalArgumentException e) { /* * Swallow exception - it means task is not in the * BuildInvocations model for the project and there is * no visibility property for it */ GradleTasksViewPlugin .getDefault() .getLog() .log(new Status( IStatus.WARNING, GradleTasksViewPlugin.PLUGIN_ID, "Task '" + task.getPath() + "' is displayed as public because visibility property is unavailable for it", e)); } } final boolean isPublic = publicTask; if (!isHideInternalTasks || isPublic) { tasksCollection.add( new GradleTask() { @Override public String getPath() { return task.getPath(); } @Override public String getName() { return task.getName(); } @Override public String getDescription() { return task.getDescription(); } @Override public String getDisplayName() { return task.getDisplayName(); } @Override public boolean isPublic() { return isPublic; } @Override public org.gradle.tooling.model.GradleProject getProject() { return task.getProject(); } } ); } } return tasksCollection.toArray(new GradleTask[tasksCollection.size()]); } catch (FastOperationFailedException e) { return new GradleTask[0]; } catch (CoreException e) { return new GradleTask[0]; } } public Object[] getChildren(Object parentElement) { return NO_ELEMENTS; } public Object getParent(Object element) { return null; } public boolean hasChildren(Object element) { return false; } public void setLocalTasks(boolean isLocalTasks) { this.isLocalTasks = isLocalTasks; } public void setHideInternalTasks(boolean isHideInternalTasks) { this.isHideInternalTasks = isHideInternalTasks; } }