Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIgor Fedorenko2013-01-23 23:24:23 -0500
committerIgor Fedorenko2013-02-16 11:41:50 -0500
commite03d2925e0632053312539edef7350e37783963f (patch)
treee22c59b784215ec6512729446c198f2322c3c56a
parent293a1c09ed3ec5401093b7b3b783ea161838b6f0 (diff)
downloadm2e-core-e03d2925e0632053312539edef7350e37783963f.tar.gz
m2e-core-e03d2925e0632053312539edef7350e37783963f.tar.xz
m2e-core-e03d2925e0632053312539edef7350e37783963f.zip
initial prototype of build troubleshooting view
Signed-off-by: Igor Fedorenko <igor@ifedorenko.com>
-rw-r--r--org.eclipse.m2e.core.ui/icons/clear.gifbin0 -> 163 bytes
-rw-r--r--org.eclipse.m2e.core.ui/icons/suspend.gifbin0 -> 338 bytes
-rw-r--r--org.eclipse.m2e.core.ui/plugin.properties1
-rw-r--r--org.eclipse.m2e.core.ui/plugin.xml8
-rw-r--r--org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/MavenImages.java4
-rw-r--r--org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/Messages.java18
-rw-r--r--org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/messages.properties12
-rw-r--r--org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/views/build/BuildDebugView.java325
-rw-r--r--org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/views/build/CollectionNode.java45
-rw-r--r--org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/views/build/ContainerNode.java48
-rw-r--r--org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/views/build/MojoExecutionNode.java39
-rw-r--r--org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/views/build/Node.java19
-rw-r--r--org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/views/build/ProjectNode.java53
-rw-r--r--org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/views/build/ResourceNode.java42
-rw-r--r--org.eclipse.m2e.core/src/org/eclipse/m2e/core/internal/builder/BuildDebugHook.java39
-rw-r--r--org.eclipse.m2e.core/src/org/eclipse/m2e/core/internal/builder/MavenBuilder.java34
-rw-r--r--org.eclipse.m2e.core/src/org/eclipse/m2e/core/internal/builder/MavenBuilderImpl.java46
17 files changed, 732 insertions, 1 deletions
diff --git a/org.eclipse.m2e.core.ui/icons/clear.gif b/org.eclipse.m2e.core.ui/icons/clear.gif
new file mode 100644
index 00000000..2cd9c544
--- /dev/null
+++ b/org.eclipse.m2e.core.ui/icons/clear.gif
Binary files differ
diff --git a/org.eclipse.m2e.core.ui/icons/suspend.gif b/org.eclipse.m2e.core.ui/icons/suspend.gif
new file mode 100644
index 00000000..161e3f59
--- /dev/null
+++ b/org.eclipse.m2e.core.ui/icons/suspend.gif
Binary files differ
diff --git a/org.eclipse.m2e.core.ui/plugin.properties b/org.eclipse.m2e.core.ui/plugin.properties
index bc485714..a3a5a5d8 100644
--- a/org.eclipse.m2e.core.ui/plugin.properties
+++ b/org.eclipse.m2e.core.ui/plugin.properties
@@ -94,6 +94,7 @@ action.addplugin.label = Add Maven Plugin
action.add.plugin.tooltip = Add Maven Plugin
category.maven.name = Maven
view.repos.name = Maven Repositories
+view.build.name = Maven Workspace Build
page.maven.name = Maven
page.mappings.name = Lifecycle Mapping
lifecycleMapping.custom.name = Customizable Lifecycle Mapping
diff --git a/org.eclipse.m2e.core.ui/plugin.xml b/org.eclipse.m2e.core.ui/plugin.xml
index 117f86be..965e5522 100644
--- a/org.eclipse.m2e.core.ui/plugin.xml
+++ b/org.eclipse.m2e.core.ui/plugin.xml
@@ -485,6 +485,14 @@
class="org.eclipse.m2e.core.ui.internal.views.MavenRepositoryView"
icon="icons/maven_indexes.gif"
name="%view.repos.name"/>
+ <view
+ allowMultiple="false"
+ category="org.eclipse.m2e.core.views.repositories"
+ class="org.eclipse.m2e.core.ui.internal.views.build.BuildDebugView"
+ id="org.eclipse.m2e.core.views.MavenBuild"
+ name="%view.build.name"
+ restorable="true">
+ </view>
</extension>
<extension point="org.eclipse.ui.bindings">
diff --git a/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/MavenImages.java b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/MavenImages.java
index 2452ae70..43a2a1cc 100644
--- a/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/MavenImages.java
+++ b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/MavenImages.java
@@ -54,6 +54,10 @@ public class MavenImages {
public static final ImageDescriptor COLLAPSEALL = createDescriptor("collapseall.gif"); //$NON-NLS-1$
+ public static final ImageDescriptor SUSPEND = createDescriptor("suspend.gif"); //$NON-NLS-1$
+
+ public static final ImageDescriptor CLEAR = createDescriptor("clear.gif"); //$NON-NLS-1$
+
// object images
public static final String PATH_JAR = "jar_obj.gif"; //$NON-NLS-1$
diff --git a/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/Messages.java b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/Messages.java
index aded9ac4..7f72ea38 100644
--- a/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/Messages.java
+++ b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/Messages.java
@@ -863,6 +863,24 @@ public class Messages extends NLS {
public static String LifecycleMappingPreferencePage_this_message;
+ public static String BuildDebugView_columnName;
+
+ public static String BuildDebugView_columnBuildNumber;
+
+ public static String BuildDebugView_nodeExecutions;
+
+ public static String BuildDebugView_nodeDelta;
+
+ public static String BuildDebugView_actionSuspend;
+
+ public static String BuildDebugView_actionClear;
+
+ public static String BuildDebugView_actionCollapseAll;
+
+ public static String BuildDebugView_errorTitle;
+
+ public static String BuildDebugView_errorDescription;
+
static {
// initialize resource bundle
NLS.initializeMessages(BUNDLE_NAME, Messages.class);
diff --git a/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/messages.properties b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/messages.properties
index b56d9fbb..c01d6abf 100644
--- a/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/messages.properties
+++ b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/messages.properties
@@ -431,3 +431,15 @@ wizardProjectPageProjectTitle=New Maven project
wizardProjectPageProjectValidatorInvalidLocation=Invalid project location path
wizardProjectPageProjectValidatorProjectLocation=Enter a location for the project.
wizardProjectTitle=New Maven Project
+BuildDebugView_columnName=Name
+BuildDebugView_columnBuildNumber=Build#
+BuildDebugView_nodeExecutions=executions
+BuildDebugView_nodeDelta=delta
+BuildDebugView_actionSuspend=Suspend
+BuildDebugView_actionClear=Clear
+BuildDebugView_actionCollapseAll=Collapse All
+BuildDebugView_errorTitle=Build debug error
+BuildDebugView_errorDescription=Could not collection build log
+
+
+
diff --git a/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/views/build/BuildDebugView.java b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/views/build/BuildDebugView.java
new file mode 100644
index 00000000..81265573
--- /dev/null
+++ b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/views/build/BuildDebugView.java
@@ -0,0 +1,325 @@
+/*******************************************************************************
+ * Copyright (c) 2013 Igor Fedorenko
+ * 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:
+ * Igor Fedorenko - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.m2e.core.ui.internal.views.build;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IFolder;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IResourceDelta;
+import org.eclipse.core.resources.IResourceDeltaVisitor;
+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.jobs.Job;
+import org.eclipse.jface.action.Action;
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.action.IToolBarManager;
+import org.eclipse.jface.dialogs.ErrorDialog;
+import org.eclipse.jface.viewers.ILabelProviderListener;
+import org.eclipse.jface.viewers.ITableLabelProvider;
+import org.eclipse.jface.viewers.ITreeContentProvider;
+import org.eclipse.jface.viewers.TreeViewer;
+import org.eclipse.jface.viewers.TreeViewerColumn;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Tree;
+import org.eclipse.swt.widgets.TreeColumn;
+import org.eclipse.ui.IActionBars;
+import org.eclipse.ui.IViewSite;
+import org.eclipse.ui.PartInitException;
+import org.eclipse.ui.part.ViewPart;
+
+import org.eclipse.m2e.core.internal.builder.BuildDebugHook;
+import org.eclipse.m2e.core.internal.builder.MavenBuilder;
+import org.eclipse.m2e.core.project.IMavenProjectFacade;
+import org.eclipse.m2e.core.project.configurator.AbstractBuildParticipant;
+import org.eclipse.m2e.core.project.configurator.MojoExecutionKey;
+import org.eclipse.m2e.core.ui.internal.MavenImages;
+import org.eclipse.m2e.core.ui.internal.Messages;
+
+
+@SuppressWarnings("restriction")
+public class BuildDebugView extends ViewPart implements BuildDebugHook {
+
+ /*package*/static final Comparator<Node> NODE_COMPARATOR = new Comparator<Node>() {
+ public int compare(Node p1, Node p2) {
+ int d = p2.getBuildCount() - p1.getBuildCount();
+ if(d != 0) {
+ return d;
+ }
+ return p1.getName().compareTo(p2.getName());
+ }
+ };
+
+ /*package*/TreeViewer viewer;
+
+ /*package*/final Object projectsLock = new Object() {
+ };
+
+ /*package*/final Map<String, ProjectNode> projects = new ConcurrentHashMap<String, ProjectNode>();
+
+ /*package*/final Job refreshJob = new Job("") {
+ protected IStatus run(IProgressMonitor monitor) {
+ getSite().getShell().getDisplay().asyncExec(new Runnable() {
+ public void run() {
+ viewer.refresh();
+// for(TreeColumn column : viewer.getTree().getColumns()) {
+// column.pack();
+// }
+ }
+ });
+ return Status.OK_STATUS;
+ }
+ };
+
+ /*package*/volatile boolean suspended = true;
+
+ public void createPartControl(Composite parent) {
+ viewer = new TreeViewer(parent, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL);
+ Tree tree = viewer.getTree();
+ tree.setHeaderVisible(true);
+ tree.setLinesVisible(true);
+
+ TreeViewerColumn treeViewerColumn = new TreeViewerColumn(viewer, SWT.NONE);
+ TreeColumn trclmnName = treeViewerColumn.getColumn();
+ trclmnName.setWidth(400);
+ trclmnName.setText(Messages.BuildDebugView_columnName);
+
+ TreeViewerColumn treeViewerColumn_1 = new TreeViewerColumn(viewer, SWT.NONE);
+ TreeColumn trclmnBuildCount = treeViewerColumn_1.getColumn();
+ trclmnBuildCount.setWidth(100);
+ trclmnBuildCount.setText(Messages.BuildDebugView_columnBuildNumber);
+ viewer.setLabelProvider(new ITableLabelProvider() {
+
+ public void removeListener(ILabelProviderListener listener) {
+ }
+
+ public boolean isLabelProperty(Object element, String property) {
+ return false;
+ }
+
+ public void dispose() {
+ }
+
+ public void addListener(ILabelProviderListener listener) {
+ }
+
+ public String getColumnText(Object element, int columnIndex) {
+ if(element instanceof Node) {
+ return getColumnText((Node) element, columnIndex);
+ }
+
+ if(columnIndex == 0) {
+ return element.toString();
+ }
+
+ return null;
+ }
+
+ private String getColumnText(Node element, int columnIndex) {
+ switch(columnIndex) {
+ case 0:
+ return element.getName();
+ case 1:
+ return Integer.toString(element.getBuildCount());
+ default:
+ // fall through
+ }
+ return null;
+ }
+
+ public Image getColumnImage(Object element, int columnIndex) {
+ return null;
+ }
+ });
+
+ viewer.setContentProvider(new ITreeContentProvider() {
+
+ public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
+ }
+
+ public void dispose() {
+ }
+
+ public boolean hasChildren(Object element) {
+ if(element instanceof ContainerNode) {
+ return !((ContainerNode) element).getResources().isEmpty();
+ }
+ if(element instanceof CollectionNode<?>) {
+ return !((CollectionNode<?>) element).getMembers().isEmpty();
+ }
+ return false;
+ }
+
+ public Object getParent(Object element) {
+ return null;
+ }
+
+ public Object[] getElements(Object inputElement) {
+ if(inputElement == projects) {
+ List<ProjectNode> sorted;
+ synchronized(projectsLock) {
+ sorted = new ArrayList<ProjectNode>(projects.values());
+ }
+ Collections.sort(sorted, NODE_COMPARATOR);
+ return sorted.toArray();
+ }
+ return new Object[0];
+ }
+
+ public Object[] getChildren(Object parentElement) {
+ if(parentElement instanceof ProjectNode) {
+ ArrayList<Object> result = new ArrayList<Object>();
+
+ final ProjectNode projectNode = (ProjectNode) parentElement;
+
+ final List<ResourceNode> resources = new ArrayList<ResourceNode>(projectNode.getResources());
+ if(!resources.isEmpty()) {
+ Collections.sort(resources, NODE_COMPARATOR);
+ result.add(new CollectionNode<ResourceNode>(Messages.BuildDebugView_nodeDelta, resources));
+ }
+
+ final List<MojoExecutionNode> executions = new ArrayList<MojoExecutionNode>(projectNode.getMojoExecutions());
+ if(!executions.isEmpty()) {
+ Collections.sort(executions, NODE_COMPARATOR);
+ result.add(new CollectionNode<MojoExecutionNode>(Messages.BuildDebugView_nodeExecutions, executions));
+ }
+
+ return result.toArray();
+ } else if(parentElement instanceof CollectionNode<?>) {
+ return ((CollectionNode<?>) parentElement).getMembers().toArray();
+ } else if(parentElement instanceof ContainerNode) {
+ return ((ContainerNode) parentElement).getResources().toArray();
+ }
+ return null;
+ }
+ });
+
+ viewer.setInput(projects);
+
+ IActionBars actionBars = getViewSite().getActionBars();
+ IToolBarManager toolBar = actionBars.getToolBarManager();
+ Action suspendAction = new Action(Messages.BuildDebugView_actionSuspend, IAction.AS_CHECK_BOX) {
+ public void run() {
+ suspended = isChecked();
+ }
+ };
+ suspendAction.setImageDescriptor(MavenImages.SUSPEND);
+ suspendAction.setChecked(suspended);
+ Action clearAction = new Action(Messages.BuildDebugView_actionClear, MavenImages.CLEAR) {
+ public void run() {
+ synchronized(projectsLock) {
+ projects.clear();
+ }
+ refreshJob.schedule();
+ }
+ };
+ Action collapseAll = new Action(Messages.BuildDebugView_actionCollapseAll, MavenImages.COLLAPSEALL) {
+ public void run() {
+ viewer.collapseAll();
+ }
+ };
+ toolBar.add(collapseAll);
+ toolBar.add(clearAction);
+ toolBar.add(suspendAction);
+ actionBars.updateActionBars();
+ }
+
+ public void setFocus() {
+ }
+
+ public void init(IViewSite site) throws PartInitException {
+ super.init(site);
+ MavenBuilder.addDebugHook(this);
+ }
+
+ public void dispose() {
+ MavenBuilder.removeDebugHook(this);
+ super.dispose();
+ }
+
+ public void buildStart(IMavenProjectFacade projectFacade, int kind, Map<String, String> args,
+ Map<MojoExecutionKey, List<AbstractBuildParticipant>> participants, IResourceDelta delta, IProgressMonitor monitor) {
+
+ if(suspended) {
+ return;
+ }
+
+ final ProjectNode projectNode = getProjectNode(projectFacade);
+
+ final int buildCount = projectNode.incrementBuildCount();
+
+ try {
+ if(delta != null) {
+ delta.accept(new IResourceDeltaVisitor() {
+ public boolean visit(IResourceDelta delta) {
+ if(delta.getAffectedChildren().length == 0) {
+ IResource resource = delta.getResource();
+ if(resource instanceof IFile || resource instanceof IFolder) {
+ projectNode.addResource(resource.getProjectRelativePath()).setBuildCount(buildCount);
+ }
+ }
+ return true; // keep visiting
+ }
+ });
+ }
+ refreshJob.schedule(1000L);
+ } catch(CoreException ex) {
+ ErrorDialog.openError(getSite().getShell(), Messages.BuildDebugView_errorTitle,
+ Messages.BuildDebugView_errorDescription, ex.getStatus());
+ }
+ }
+
+ private ProjectNode getProjectNode(IMavenProjectFacade projectFacade) {
+ synchronized(projectsLock) {
+ IProject project = projectFacade.getProject();
+ ProjectNode projectNode = projects.get(project.getName());
+ if(projectNode == null) {
+ projectNode = new ProjectNode(project.getName());
+ projects.put(project.getName(), projectNode);
+ }
+ return projectNode;
+ }
+ }
+
+ public void buildParticipant(IMavenProjectFacade projectFacade, MojoExecutionKey mojoExecutionKey,
+ AbstractBuildParticipant participant, Set<File> files, IProgressMonitor monitor) {
+
+ if(suspended || files == null || files.isEmpty()) {
+ return;
+ }
+
+ final ProjectNode projectNode = getProjectNode(projectFacade);
+ final int buildCount = projectNode.getBuildCount();
+
+ // TODO secondary participants
+ // ... although they are unlikely to use BuildContext so we don't know what resources they modify
+ final MojoExecutionNode executionNode = projectNode.getMojoExecutionNode(mojoExecutionKey);
+ executionNode.setBuildCount(buildCount);
+ for(File file : files) {
+ executionNode.addResource(projectFacade.getProjectRelativePath(file.getAbsolutePath())).setBuildCount(buildCount);
+ }
+ }
+}
diff --git a/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/views/build/CollectionNode.java b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/views/build/CollectionNode.java
new file mode 100644
index 00000000..1244ea81
--- /dev/null
+++ b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/views/build/CollectionNode.java
@@ -0,0 +1,45 @@
+/*******************************************************************************
+ * Copyright (c) 2013 Igor Fedorenko
+ * 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:
+ * Igor Fedorenko - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.m2e.core.ui.internal.views.build;
+
+import java.util.Collection;
+
+
+class CollectionNode<T extends Node> implements Node {
+
+ private final String name;
+
+ private final Collection<T> members;
+
+ public CollectionNode(String name, Collection<T> members) {
+ this.name = name;
+ this.members = members;
+ }
+
+ public Collection<T> getMembers() {
+ return members;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public int getBuildCount() {
+ int result = 0;
+ for(Node member : members) {
+ if(result < member.getBuildCount()) {
+ result = member.getBuildCount();
+ }
+ }
+ return result;
+ }
+}
diff --git a/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/views/build/ContainerNode.java b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/views/build/ContainerNode.java
new file mode 100644
index 00000000..d84b0546
--- /dev/null
+++ b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/views/build/ContainerNode.java
@@ -0,0 +1,48 @@
+/*******************************************************************************
+ * Copyright (c) 2013 Igor Fedorenko
+ * 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:
+ * Igor Fedorenko - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.m2e.core.ui.internal.views.build;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.eclipse.core.runtime.IPath;
+
+
+abstract class ContainerNode implements Node {
+ private final String name;
+
+ private final Map<IPath, ResourceNode> resources = new HashMap<IPath, ResourceNode>();
+
+ protected ContainerNode(String name) {
+ this.name = name;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public synchronized ResourceNode addResource(IPath path) {
+ ResourceNode child = resources.get(path);
+ if(child == null) {
+ child = new ResourceNode(path);
+ resources.put(path, child);
+ }
+ return child;
+ }
+
+ public synchronized Collection<ResourceNode> getResources() {
+ return new ArrayList<ResourceNode>(resources.values());
+ }
+
+}
diff --git a/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/views/build/MojoExecutionNode.java b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/views/build/MojoExecutionNode.java
new file mode 100644
index 00000000..64631667
--- /dev/null
+++ b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/views/build/MojoExecutionNode.java
@@ -0,0 +1,39 @@
+/*******************************************************************************
+ * Copyright (c) 2013 Igor Fedorenko
+ * 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:
+ * Igor Fedorenko - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.m2e.core.ui.internal.views.build;
+
+import org.eclipse.m2e.core.project.configurator.MojoExecutionKey;
+
+
+class MojoExecutionNode extends ContainerNode {
+
+ private final MojoExecutionKey mojoExecutionKey;
+
+ private int buildCount;
+
+ public MojoExecutionNode(MojoExecutionKey mojoExecutionKey) {
+ super(mojoExecutionKey.toString());
+ this.mojoExecutionKey = mojoExecutionKey;
+ }
+
+ public MojoExecutionKey getMojoExecutionKey() {
+ return mojoExecutionKey;
+ }
+
+ public synchronized int getBuildCount() {
+ return buildCount;
+ }
+
+ public void setBuildCount(int buildCount) {
+ this.buildCount = buildCount;
+ }
+}
diff --git a/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/views/build/Node.java b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/views/build/Node.java
new file mode 100644
index 00000000..5376433e
--- /dev/null
+++ b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/views/build/Node.java
@@ -0,0 +1,19 @@
+/*******************************************************************************
+ * Copyright (c) 2013 Igor Fedorenko
+ * 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:
+ * Igor Fedorenko - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.m2e.core.ui.internal.views.build;
+
+interface Node {
+
+ public String getName();
+
+ public int getBuildCount();
+}
diff --git a/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/views/build/ProjectNode.java b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/views/build/ProjectNode.java
new file mode 100644
index 00000000..a5806dbb
--- /dev/null
+++ b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/views/build/ProjectNode.java
@@ -0,0 +1,53 @@
+/*******************************************************************************
+ * Copyright (c) 2013 Igor Fedorenko
+ * 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:
+ * Igor Fedorenko - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.m2e.core.ui.internal.views.build;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import org.eclipse.m2e.core.project.configurator.MojoExecutionKey;
+
+
+class ProjectNode extends ContainerNode {
+
+ private final Map<MojoExecutionKey, MojoExecutionNode> executions = new HashMap<MojoExecutionKey, MojoExecutionNode>();
+
+ private final AtomicInteger buildCount = new AtomicInteger();
+
+ public ProjectNode(String name) {
+ super(name);
+ }
+
+ public int incrementBuildCount() {
+ return buildCount.incrementAndGet();
+ }
+
+ public int getBuildCount() {
+ return buildCount.get();
+ }
+
+ public synchronized MojoExecutionNode getMojoExecutionNode(MojoExecutionKey mojoExecutionKey) {
+ MojoExecutionNode node = executions.get(mojoExecutionKey);
+ if(node == null) {
+ node = new MojoExecutionNode(mojoExecutionKey);
+ executions.put(mojoExecutionKey, node);
+ }
+ return node;
+ }
+
+ public synchronized Collection<MojoExecutionNode> getMojoExecutions() {
+ return new ArrayList<MojoExecutionNode>(executions.values());
+ }
+}
diff --git a/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/views/build/ResourceNode.java b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/views/build/ResourceNode.java
new file mode 100644
index 00000000..21009f6f
--- /dev/null
+++ b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/views/build/ResourceNode.java
@@ -0,0 +1,42 @@
+/*******************************************************************************
+ * Copyright (c) 2013 Igor Fedorenko
+ * 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:
+ * Igor Fedorenko - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.m2e.core.ui.internal.views.build;
+
+import org.eclipse.core.runtime.IPath;
+
+
+class ResourceNode implements Node {
+
+ private final IPath path;
+
+ private int buildCount;
+
+ public ResourceNode(IPath path) {
+ this.path = path;
+ }
+
+ public String getName() {
+ return path.toPortableString();
+ }
+
+ public IPath getPath() {
+ return path;
+ }
+
+ public synchronized int getBuildCount() {
+ return buildCount;
+ }
+
+ public void setBuildCount(int buildCount) {
+ this.buildCount = buildCount;
+ }
+}
diff --git a/org.eclipse.m2e.core/src/org/eclipse/m2e/core/internal/builder/BuildDebugHook.java b/org.eclipse.m2e.core/src/org/eclipse/m2e/core/internal/builder/BuildDebugHook.java
new file mode 100644
index 00000000..e81d2cf6
--- /dev/null
+++ b/org.eclipse.m2e.core/src/org/eclipse/m2e/core/internal/builder/BuildDebugHook.java
@@ -0,0 +1,39 @@
+/*******************************************************************************
+ * Copyright (c) 2013 Igor Fedorenko
+ * 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:
+ * Igor Fedorenko - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.m2e.core.internal.builder;
+
+import java.io.File;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.eclipse.core.resources.IResourceDelta;
+import org.eclipse.core.runtime.IProgressMonitor;
+
+import org.eclipse.m2e.core.project.IMavenProjectFacade;
+import org.eclipse.m2e.core.project.configurator.AbstractBuildParticipant;
+import org.eclipse.m2e.core.project.configurator.MojoExecutionKey;
+
+
+/**
+ * @noreference This internal interface can be changed or removed without notice.
+ * @since 1.4
+ */
+public interface BuildDebugHook {
+
+ public void buildStart(IMavenProjectFacade projectFacade, int kind, Map<String, String> args,
+ Map<MojoExecutionKey, List<AbstractBuildParticipant>> participants, IResourceDelta delta, IProgressMonitor monitor);
+
+ public void buildParticipant(IMavenProjectFacade projectFacade, MojoExecutionKey mojoExecutionKey,
+ AbstractBuildParticipant participant, Set<File> files, IProgressMonitor monitor);
+
+}
diff --git a/org.eclipse.m2e.core/src/org/eclipse/m2e/core/internal/builder/MavenBuilder.java b/org.eclipse.m2e.core/src/org/eclipse/m2e/core/internal/builder/MavenBuilder.java
index ae424ab9..616d2781 100644
--- a/org.eclipse.m2e.core/src/org/eclipse/m2e/core/internal/builder/MavenBuilder.java
+++ b/org.eclipse.m2e.core/src/org/eclipse/m2e/core/internal/builder/MavenBuilder.java
@@ -11,8 +11,11 @@
package org.eclipse.m2e.core.internal.builder;
+import java.util.ArrayList;
+import java.util.Collection;
import java.util.Collections;
import java.util.List;
+import java.util.ListIterator;
import java.util.Map;
import java.util.Set;
@@ -204,4 +207,35 @@ public class MavenBuilder extends IncrementalProjectBuilder implements DeltaProv
return projectFacade;
}
+
+ private static final List<BuildDebugHook> debugHooks = new ArrayList<BuildDebugHook>();
+
+ public static void addDebugHook(BuildDebugHook hook) {
+ synchronized(debugHooks) {
+ for(BuildDebugHook other : debugHooks) {
+ if(other == hook) {
+ return;
+ }
+ }
+ debugHooks.add(hook);
+ }
+ }
+
+ public static void removeDebugHook(BuildDebugHook hook) {
+ synchronized(debugHooks) {
+ ListIterator<BuildDebugHook> iter = debugHooks.listIterator();
+ while(iter.hasNext()) {
+ if(iter.next() == hook) {
+ iter.remove();
+ break;
+ }
+ }
+ }
+ }
+
+ public static Collection<BuildDebugHook> getDebugHooks() {
+ synchronized(debugHooks) {
+ return new ArrayList<BuildDebugHook>(debugHooks);
+ }
+ }
}
diff --git a/org.eclipse.m2e.core/src/org/eclipse/m2e/core/internal/builder/MavenBuilderImpl.java b/org.eclipse.m2e.core/src/org/eclipse/m2e/core/internal/builder/MavenBuilderImpl.java
index 49907418..91aeee8d 100644
--- a/org.eclipse.m2e.core/src/org/eclipse/m2e/core/internal/builder/MavenBuilderImpl.java
+++ b/org.eclipse.m2e.core/src/org/eclipse/m2e/core/internal/builder/MavenBuilderImpl.java
@@ -16,10 +16,12 @@ import static org.eclipse.core.resources.IncrementalProjectBuilder.FULL_BUILD;
import static org.eclipse.core.resources.IncrementalProjectBuilder.INCREMENTAL_BUILD;
import java.io.File;
+import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
+import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
@@ -83,6 +85,8 @@ public class MavenBuilderImpl {
public Set<IProject> build(MavenSession session, IMavenProjectFacade projectFacade, int kind,
Map<String, String> args, Map<MojoExecutionKey, List<AbstractBuildParticipant>> participants,
IProgressMonitor monitor) throws CoreException {
+ Collection<BuildDebugHook> debugHooks = MavenBuilder.getDebugHooks();
+
Set<IProject> dependencies = new HashSet<IProject>();
MavenProject mavenProject = projectFacade.getMavenProject();
@@ -106,13 +110,17 @@ public class MavenBuilderImpl {
}
}
+ debugBuildStart(debugHooks, projectFacade, kind, args, participants, delta, monitor);
+
Map<Throwable, MojoExecutionKey> buildErrors = new LinkedHashMap<Throwable, MojoExecutionKey>();
ThreadBuildContext.setThreadBuildContext(buildContext);
MavenProjectMutableState snapshot = MavenProjectMutableState.takeSnapshot(mavenProject);
try {
for(Entry<MojoExecutionKey, List<AbstractBuildParticipant>> entry : participants.entrySet()) {
+ MojoExecutionKey mojoExecutionKey = entry.getKey();
for(InternalBuildParticipant participant : entry.getValue()) {
- MojoExecutionKey mojoExecutionKey = entry.getKey();
+ Set<File> debugRefreshFiles = !debugHooks.isEmpty() ? new LinkedHashSet<File>(buildContext.getFiles()) : null;
+
log.debug("Executing build participant {} for plugin execution {}", participant.getClass().getName(),
mojoExecutionKey.toString());
String stringMojoExecutionKey = mojoExecutionKey.getKeyString();
@@ -149,6 +157,9 @@ public class MavenBuilderImpl {
processMavenSessionErrors(session, mojoExecutionKey, buildErrors);
}
+
+ debugBuildParticipant(debugHooks, projectFacade, mojoExecutionKey, (AbstractBuildParticipant) participant,
+ diff(debugRefreshFiles, buildContext.getFiles()), monitor);
}
}
} catch(Exception e) {
@@ -164,9 +175,42 @@ public class MavenBuilderImpl {
// Process errors and warnings
MavenExecutionResult result = session.getResult();
processBuildResults(project, mavenProject, result, buildContext, buildErrors);
+
+ debugBuildEnd(debugHooks, projectFacade, buildContext, monitor);
+
return dependencies;
}
+ private void debugBuildParticipant(Collection<BuildDebugHook> hooks, IMavenProjectFacade projectFacade,
+ MojoExecutionKey mojoExecutionKey, AbstractBuildParticipant participant, Set<File> files, IProgressMonitor monitor) {
+ for(BuildDebugHook hook : hooks) {
+ hook.buildParticipant(projectFacade, mojoExecutionKey, participant, files, monitor);
+ }
+ }
+
+ private Set<File> diff(Set<File> before, Set<File> after) {
+ if(before == null) {
+ return after;
+ }
+ Set<File> result = new LinkedHashSet<File>(after);
+ result.removeAll(before);
+ return result;
+ }
+
+ private void debugBuildStart(Collection<BuildDebugHook> hooks, IMavenProjectFacade projectFacade, int kind,
+ Map<String, String> args, Map<MojoExecutionKey, List<AbstractBuildParticipant>> participants,
+ IResourceDelta delta, IProgressMonitor monitor) {
+ for(BuildDebugHook hook : hooks) {
+ hook.buildStart(projectFacade, kind, args, participants, delta, monitor);
+ }
+ }
+
+ private void debugBuildEnd(Collection<BuildDebugHook> hooks, IMavenProjectFacade projectFacade,
+ AbstractEclipseBuildContext buildContext, IProgressMonitor monitor) {
+ for(BuildDebugHook hook : hooks) {
+ }
+ }
+
protected boolean isApplicable(InternalBuildParticipant participant, int kind, IResourceDelta delta) {
return FULL_BUILD == kind || delta != null || participant.callOnEmptyDelta();
}

Back to the top