blob: fd740184c0ed01f9115dbd6c65670b8122e63d05 [file] [log] [blame]
/*******************************************************************************
* 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;
}
}