484260: create commands for build toolbar
Change-Id: I8aba963dd787d6dce61e9585000844a5cc8b8e3d
Task-Url: https://bugs.eclipse.org/bugs/show_bug.cgi?id=484260
diff --git a/org.eclipse.mylyn.builds.ui/icons/eview16/web.png b/org.eclipse.mylyn.builds.ui/icons/eview16/web.png
new file mode 100644
index 0000000..94eec2c
--- /dev/null
+++ b/org.eclipse.mylyn.builds.ui/icons/eview16/web.png
Binary files differ
diff --git a/org.eclipse.mylyn.builds.ui/plugin.xml b/org.eclipse.mylyn.builds.ui/plugin.xml
index 0d863b0..041ee39 100644
--- a/org.eclipse.mylyn.builds.ui/plugin.xml
+++ b/org.eclipse.mylyn.builds.ui/plugin.xml
@@ -159,6 +159,21 @@
id="org.eclipse.mylyn.builds.ui.command.NewTaskFromTest"
name="New Task From Test">
</command>
+ <command
+ defaultHandler="org.eclipse.mylyn.internal.builds.ui.commands.BuildUrlCommandHandler$ShowTestResultsUrlHandler"
+ id="org.eclipse.mylyn.builds.ui.command.ShowTestResults.url"
+ name="Show Test Results">
+ </command>
+ <command
+ defaultHandler="org.eclipse.mylyn.internal.builds.ui.commands.BuildUrlCommandHandler$ShowBuildOutputUrlHandler"
+ id="org.eclipse.mylyn.builds.ui.command.ShowBuildOutput.url"
+ name="Show Build Output">
+ </command>
+ <command
+ defaultHandler="org.eclipse.mylyn.internal.builds.ui.commands.BuildUrlCommandHandler$OpenWithBrowserUrlHandler"
+ id="org.eclipse.mylyn.builds.ui.commands.OpenBuildElementWithBrowser.url"
+ name="Open Build with Browser">
+ </command>
</extension>
<extension
point="org.eclipse.ui.commandImages">
@@ -167,10 +182,18 @@
icon="icons/etool16/console.gif">
</image>
<image
+ commandId="org.eclipse.mylyn.builds.ui.command.ShowBuildOutput.url"
+ icon="icons/etool16/console.gif">
+ </image>
+ <image
commandId="org.eclipse.mylyn.builds.ui.command.ShowTestResults"
icon="icons/eview16/junit.gif">
</image>
<image
+ commandId="org.eclipse.mylyn.builds.ui.command.ShowTestResults.url"
+ icon="icons/eview16/junit.gif">
+ </image>
+ <image
commandId="org.eclipse.mylyn.builds.ui.command.RunBuild"
disabledIcon="icons/dtool16/run_exc.gif"
icon="icons/etool16/run_exc.gif">
@@ -834,4 +857,27 @@
id="org.eclipse.mylyn.builds.ui.urlHandler.BuildsUrlHandler">
</handler>
</extension>
+ <extension
+ point="org.eclipse.ui.menus">
+ <menuContribution
+ allPopups="false"
+ locationURI="toolbar:org.eclipse.mylyn.build.toolbar">
+ <command
+ commandId="org.eclipse.mylyn.builds.ui.command.ShowTestResults.url"
+ label="Show Test Results"
+ style="push">
+ </command>
+ <command
+ commandId="org.eclipse.mylyn.builds.ui.command.ShowBuildOutput.url"
+ label="Show Build Output"
+ style="push">
+ </command>
+ <command
+ commandId="org.eclipse.mylyn.builds.ui.commands.OpenBuildElementWithBrowser.url"
+ icon="icons/eview16/web.png"
+ label="Open Build with Browser"
+ style="push">
+ </command>
+ </menuContribution>
+ </extension>
</plugin>
diff --git a/org.eclipse.mylyn.builds.ui/src/org/eclipse/mylyn/internal/builds/ui/commands/BuildUrlCommandHandler.java b/org.eclipse.mylyn.builds.ui/src/org/eclipse/mylyn/internal/builds/ui/commands/BuildUrlCommandHandler.java
new file mode 100644
index 0000000..fd74018
--- /dev/null
+++ b/org.eclipse.mylyn.builds.ui/src/org/eclipse/mylyn/internal/builds/ui/commands/BuildUrlCommandHandler.java
@@ -0,0 +1,212 @@
+/*******************************************************************************
+ * Copyright (c) 2015 Tasktop Technologies 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:
+ * Tasktop Technologies - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.mylyn.internal.builds.ui.commands;
+
+import java.lang.ref.WeakReference;
+import java.util.Collections;
+import java.util.List;
+
+import org.eclipse.core.commands.AbstractHandler;
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.commands.ExecutionException;
+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.viewers.StructuredSelection;
+import org.eclipse.mylyn.builds.core.IBuild;
+import org.eclipse.mylyn.builds.core.IBuildPlan;
+import org.eclipse.mylyn.builds.core.IBuildServer;
+import org.eclipse.mylyn.builds.core.spi.BuildServerBehaviour;
+import org.eclipse.mylyn.builds.core.spi.GetBuildsRequest;
+import org.eclipse.mylyn.builds.core.spi.GetBuildsRequest.Scope;
+import org.eclipse.mylyn.builds.internal.core.BuildFactory;
+import org.eclipse.mylyn.builds.ui.BuildsUi;
+import org.eclipse.mylyn.commons.core.StatusHandler;
+import org.eclipse.mylyn.commons.workbench.browser.BrowserUtil;
+import org.eclipse.mylyn.internal.builds.ui.BuildsUiInternal;
+import org.eclipse.mylyn.internal.builds.ui.BuildsUiPlugin;
+import org.eclipse.mylyn.internal.builds.ui.actions.ShowBuildOutputAction;
+import org.eclipse.mylyn.internal.builds.ui.actions.ShowTestResultsAction;
+import org.eclipse.mylyn.internal.builds.ui.view.NewBuildServerAction;
+import org.eclipse.osgi.util.NLS;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.actions.BaseSelectionListenerAction;
+
+public class BuildUrlCommandHandler extends AbstractHandler {
+ public static class ShowTestResultsUrlHandler extends BuildUrlCommandHandler {
+ public ShowTestResultsUrlHandler() {
+ super(new ShowTestResultsAction());
+ }
+ }
+
+ public static class ShowBuildOutputUrlHandler extends BuildUrlCommandHandler {
+ public ShowBuildOutputUrlHandler() {
+ super(new ShowBuildOutputAction());
+ }
+ }
+
+ public static class OpenWithBrowserUrlHandler extends BuildUrlCommandHandler {
+ public OpenWithBrowserUrlHandler() {
+ super(new BaseSelectionListenerAction(Messages.BuildUrlCommandHandler_Open_with_Browser) {
+ @Override
+ public void run() {
+ Object selection = getStructuredSelection().getFirstElement();
+ if (selection instanceof String) {
+ BrowserUtil.openUrl((String) selection, BrowserUtil.NO_RICH_EDITOR);
+ }
+ }
+ });
+ setNeedsDownload(false);
+ }
+ }
+
+ private static class BuildCache {
+ private WeakReference<IBuild> lastBuild = new WeakReference<IBuild>(null);
+
+ private BuildUrlCommandHandler lastHandler;
+
+ public void put(BuildUrlCommandHandler handler, IBuild build) {
+ lastBuild = new WeakReference<IBuild>(build);
+ lastHandler = handler;
+ }
+
+ public IBuild get(BuildUrlCommandHandler handler, String buildUrl) {
+ if (lastHandler != handler) {
+ // same handler should never get the build back from the cache; clicking same button twice re-downloads
+ IBuild build = lastBuild.get();
+ if (build != null && buildUrl.equals(build.getUrl())) {
+ lastBuild.clear();// can only retrieve build once
+ return build;
+ }
+ }
+ return null;
+ }
+ }
+
+ private static BuildCache buildCache = new BuildCache();
+
+ private final BaseSelectionListenerAction action;
+
+ private boolean needsDownload = true;
+
+ public BuildUrlCommandHandler(BaseSelectionListenerAction action) {
+ this.action = action;
+ }
+
+ protected void setNeedsDownload(boolean needsDownload) {
+ this.needsDownload = needsDownload;
+ }
+
+ @Override
+ public Object execute(ExecutionEvent event) throws ExecutionException {
+ if (event.getTrigger() instanceof Event) {
+ Object data = ((Event) event.getTrigger()).widget.getData();
+ if (data instanceof String) {
+ String buildUrl = (String) data;
+ if (needsDownload) {
+ final IBuildServer buildServer = findServerForBuild(buildUrl);
+ if (buildServer != null) {
+ downloadBuildAndRunAction(buildServer, buildUrl);
+ } else {
+ new NewBuildServerAction().run();
+ }
+ } else {
+ action.selectionChanged(new StructuredSelection(buildUrl));
+ action.run();
+ }
+ }
+ }
+ return null;
+ }
+
+ private IBuildServer findServerForBuild(String buildUrl) {
+ for (IBuildServer server : BuildsUiInternal.getModel().getServers()) {
+ if (buildUrl.startsWith(server.getUrl())) {
+ return server;
+ }
+ }
+ return null;
+ }
+
+ protected void downloadBuildAndRunAction(final IBuildServer buildServer, final String buildUrl) {
+ IBuild build = buildCache.get(this, buildUrl);
+ if (build != null) {
+ action.selectionChanged(new StructuredSelection(build));
+ action.run();
+ return;
+ }
+ Job job = new Job(NLS.bind(Messages.BuildUrlCommandHandler_Downloading_Build_X, buildUrl)) {
+
+ @Override
+ protected IStatus run(IProgressMonitor monitor) {
+ try {
+ BuildServerBehaviour behaviour = BuildsUi.getConnector(buildServer.getConnectorKind())
+ .getBehaviour(buildServer.getLocation());
+ String buildUrl2 = removeEnd(buildUrl, "/"); //$NON-NLS-1$
+ String buildId = substringAfterLast(buildUrl2, "/"); //$NON-NLS-1$
+ String planId = substringAfterLast(substringBeforeLast(buildUrl2, "/"), "/"); //$NON-NLS-1$ //$NON-NLS-2$
+ IBuildPlan plan = BuildFactory.eINSTANCE.createBuildPlan();
+ plan.setId(planId);
+ plan.setName(planId);
+ GetBuildsRequest request = new GetBuildsRequest(plan, Collections.singletonList(buildId),
+ Scope.FULL);
+ @SuppressWarnings("restriction")
+ final List<IBuild> builds = behaviour.getBuilds(request,
+ new org.eclipse.mylyn.internal.commons.core.operations.NullOperationMonitor());
+ if (!builds.isEmpty()) {
+ IBuild populatedBuild = builds.get(0);
+ populatedBuild.setServer(buildServer);
+ populatedBuild.setPlan(plan);
+ buildCache.put(BuildUrlCommandHandler.this, populatedBuild);
+ action.selectionChanged(new StructuredSelection(populatedBuild));
+ PlatformUI.getWorkbench().getDisplay().asyncExec(new Runnable() {
+ public void run() {
+ action.run();
+ }
+ });
+ }
+ } catch (CoreException e) {
+ StatusHandler.log(new Status(IStatus.ERROR, BuildsUiPlugin.ID_PLUGIN, e.getMessage(), e));
+ }
+ return Status.OK_STATUS;
+ }
+ };
+ job.setUser(true);
+ job.schedule();
+ }
+
+ protected String substringBeforeLast(String s, String last) {
+ int i = s.lastIndexOf(last);
+ if (i != -1) {
+ return s.substring(0, i);
+ }
+ return s;
+ }
+
+ private String substringAfterLast(String s, String last) {
+ int i = s.lastIndexOf(last);
+ if (i != -1) {
+ return s.substring(i + last.length());
+ }
+ return s;
+ }
+
+ private String removeEnd(final String s, String end) {
+ if (s.endsWith(end)) {
+ return s.substring(0, s.length() - end.length());
+ }
+ return s;
+ }
+}
diff --git a/org.eclipse.mylyn.builds.ui/src/org/eclipse/mylyn/internal/builds/ui/commands/Messages.java b/org.eclipse.mylyn.builds.ui/src/org/eclipse/mylyn/internal/builds/ui/commands/Messages.java
new file mode 100644
index 0000000..a537842
--- /dev/null
+++ b/org.eclipse.mylyn.builds.ui/src/org/eclipse/mylyn/internal/builds/ui/commands/Messages.java
@@ -0,0 +1,29 @@
+/*******************************************************************************
+ * Copyright (c) 2015 Tasktop Technologies 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:
+ * Tasktop Technologies - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.mylyn.internal.builds.ui.commands;
+
+import org.eclipse.osgi.util.NLS;
+
+public class Messages extends NLS {
+ private static final String BUNDLE_NAME = "org.eclipse.mylyn.internal.builds.ui.commands.messages"; //$NON-NLS-1$
+
+ public static String BuildUrlCommandHandler_Downloading_Build_X;
+
+ public static String BuildUrlCommandHandler_Open_with_Browser;
+ static {
+ // initialize resource bundle
+ NLS.initializeMessages(BUNDLE_NAME, Messages.class);
+ }
+
+ private Messages() {
+ }
+}
diff --git a/org.eclipse.mylyn.builds.ui/src/org/eclipse/mylyn/internal/builds/ui/commands/messages.properties b/org.eclipse.mylyn.builds.ui/src/org/eclipse/mylyn/internal/builds/ui/commands/messages.properties
new file mode 100644
index 0000000..b487eec
--- /dev/null
+++ b/org.eclipse.mylyn.builds.ui/src/org/eclipse/mylyn/internal/builds/ui/commands/messages.properties
@@ -0,0 +1,2 @@
+BuildUrlCommandHandler_Downloading_Build_X=Downloading Build {0}
+BuildUrlCommandHandler_Open_with_Browser=Open with Browser