Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.
View | Details | Raw Unified | Return to bug 165581 | Differences between
and this patch

Collapse All | Expand All

(-)src/org/eclipse/mylar/tasks/core/AbstractRepositoryConnector.java (-8 / +16 lines)
Lines 26-32 Link Here
26
26
27
/**
27
/**
28
 * Operations on a task repository
28
 * Operations on a task repository
29
 * 
29
 *
30
 * @author Mik Kersten
30
 * @author Mik Kersten
31
 * @author Rob Elves
31
 * @author Rob Elves
32
 */
32
 */
Lines 45-51 Link Here
45
	protected TaskList taskList;
45
	protected TaskList taskList;
46
46
47
	public void init(TaskList taskList) {
47
	public void init(TaskList taskList) {
48
		this.taskList = taskList;		
48
		this.taskList = taskList;
49
	}
49
	}
50
50
51
	/**
51
	/**
Lines 58-65 Link Here
58
	 */
58
	 */
59
	public abstract IOfflineTaskHandler getOfflineTaskHandler();
59
	public abstract IOfflineTaskHandler getOfflineTaskHandler();
60
60
61
	public abstract String getRepositoryUrlFromTaskUrl(String url);
61
	public abstract String getRepositoryUrlFromTaskUrl(String taskFullUrl);
62
62
63
	public abstract String getTaskIdFromTaskUrl(String taskFullUrl);
64
65
	public abstract String getTaskWebUrl(String repositoryUrl, String taskId);
66
	
63
	public abstract boolean canCreateTaskFromKey(TaskRepository repository);
67
	public abstract boolean canCreateTaskFromKey(TaskRepository repository);
64
68
65
	public abstract boolean canCreateNewTask(TaskRepository repository);
69
	public abstract boolean canCreateNewTask(TaskRepository repository);
Lines 78-84 Link Here
78
82
79
	/**
83
	/**
80
	 * Implementors must execute query synchronously.
84
	 * Implementors must execute query synchronously.
81
	 * 
85
	 *
82
	 * @param query
86
	 * @param query
83
	 * @param repository
87
	 * @param repository
84
	 *            TODO
88
	 *            TODO
Lines 128-134 Link Here
128
	 * Implementors of this repositoryOperations must perform it locally without
132
	 * Implementors of this repositoryOperations must perform it locally without
129
	 * going to the server since it is used for frequent repositoryOperations
133
	 * going to the server since it is used for frequent repositoryOperations
130
	 * such as decoration.
134
	 * such as decoration.
131
	 * 
135
	 *
132
	 * @return an empty set if no contexts
136
	 * @return an empty set if no contexts
133
	 */
137
	 */
134
	public final Set<RepositoryAttachment> getContextAttachments(TaskRepository repository, AbstractRepositoryTask task) {
138
	public final Set<RepositoryAttachment> getContextAttachments(TaskRepository repository, AbstractRepositoryTask task) {
Lines 155-161 Link Here
155
159
156
	/**
160
	/**
157
	 * Attaches the associated context to <code>task</code>.
161
	 * Attaches the associated context to <code>task</code>.
158
	 * 
162
	 *
159
	 * @return false, if operation is not supported by repository
163
	 * @return false, if operation is not supported by repository
160
	 */
164
	 */
161
	public final boolean attachContext(TaskRepository repository, AbstractRepositoryTask task, String longComment) throws CoreException {
165
	public final boolean attachContext(TaskRepository repository, AbstractRepositoryTask task, String longComment) throws CoreException {
Lines 185-191 Link Here
185
	/**
189
	/**
186
	 * Retrieves a context stored in <code>attachment</code> from
190
	 * Retrieves a context stored in <code>attachment</code> from
187
	 * <code>task</code>.
191
	 * <code>task</code>.
188
	 * 
192
	 *
189
	 * @return false, if operation is not supported by repository
193
	 * @return false, if operation is not supported by repository
190
	 */
194
	 */
191
	public final boolean retrieveContext(TaskRepository repository, AbstractRepositoryTask task,
195
	public final boolean retrieveContext(TaskRepository repository, AbstractRepositoryTask task,
Lines 216-221 Link Here
216
		return templates;
220
		return templates;
217
	}
221
	}
218
222
223
	public void removeTemplate(RepositoryTemplate template) {
224
		this.templates.remove(template);
225
	}
226
219
	/** returns null if template not found */
227
	/** returns null if template not found */
220
	public RepositoryTemplate getTemplate(String label) {
228
	public RepositoryTemplate getTemplate(String label) {
221
		for (RepositoryTemplate template : getTemplates()) {
229
		for (RepositoryTemplate template : getTemplates()) {
Lines 233-239 Link Here
233
	/**
241
	/**
234
	 * Reset and update the repository attributes from the server (e.g.
242
	 * Reset and update the repository attributes from the server (e.g.
235
	 * products, components)
243
	 * products, components)
236
	 * 
244
	 *
237
	 * TODO: remove?
245
	 * TODO: remove?
238
	 */
246
	 */
239
	public abstract void updateAttributes(TaskRepository repository, IProgressMonitor monitor) throws CoreException;
247
	public abstract void updateAttributes(TaskRepository repository, IProgressMonitor monitor) throws CoreException;
(-)src/org/eclipse/mylar/tasks/tests/connector/MockRepositoryConnector.java (+11 lines)
Lines 81-88 Link Here
81
		// ignore
81
		// ignore
82
		return null;
82
		return null;
83
	}
83
	}
84
	
85
	@Override
86
	public String getTaskIdFromTaskUrl(String url) {
87
		// ignore
88
		return null;
89
	}
84
90
85
	@Override
91
	@Override
92
	public String getTaskWebUrl(String repositoryUrl, String taskId) {
93
		return null;
94
	}
95
	
96
	@Override
86
	public List<String> getSupportedVersions() {
97
	public List<String> getSupportedVersions() {
87
		// ignore
98
		// ignore
88
		return null;
99
		return null;
(-)src/org/eclipse/mylar/ide/tests/OpenCorrespondingTaskActionTest.java (-3 / +3 lines)
Lines 13-19 Link Here
13
13
14
import junit.framework.TestCase;
14
import junit.framework.TestCase;
15
15
16
import org.eclipse.mylar.internal.team.ui.actions.OpenCorrespondingTaskAction;
16
import org.eclipse.mylar.internal.team.LinkedTaskInfoAdapterFactory;
17
17
18
/**
18
/**
19
 * @author Mik Kersten
19
 * @author Mik Kersten
Lines 34-46 Link Here
34
34
35
	public void test07LegacyMatching() {
35
	public void test07LegacyMatching() {
36
		String label = "Progress on: 123: foo \nhttps://bugs.eclipse.org";
36
		String label = "Progress on: 123: foo \nhttps://bugs.eclipse.org";
37
		String id = OpenCorrespondingTaskAction.getTaskIdFromLegacy07Label(label);
37
		String id = LinkedTaskInfoAdapterFactory.getTaskIdFromLegacy07Label(label);
38
		assertEquals("123", id);
38
		assertEquals("123", id);
39
	}
39
	}
40
	
40
	
41
	public void testUrlMatching() {
41
	public void testUrlMatching() {
42
		String label = "bla bla\nhttp://foo.bar-123 bla bla";
42
		String label = "bla bla\nhttp://foo.bar-123 bla bla";
43
		String id = OpenCorrespondingTaskAction.getUrlFromComment(label);
43
		String id = LinkedTaskInfoAdapterFactory.getUrlFromComment(label);
44
		assertEquals("http://foo.bar-123", id);
44
		assertEquals("http://foo.bar-123", id);
45
	}
45
	}
46
	
46
	
(-).classpath (-1 / +1 lines)
Lines 2-8 Link Here
2
<classpath>
2
<classpath>
3
	<classpathentry exported="true" kind="lib" path="lib/ws-commons-util-1.0.1.jar" sourcepath="lib/ws-commons-util-1.0.1-sources.jar"/>
3
	<classpathentry exported="true" kind="lib" path="lib/ws-commons-util-1.0.1.jar" sourcepath="lib/ws-commons-util-1.0.1-sources.jar"/>
4
	<classpathentry exported="true" kind="lib" path="lib/commons-codec-1.3.jar"/>
4
	<classpathentry exported="true" kind="lib" path="lib/commons-codec-1.3.jar"/>
5
	<classpathentry exported="true" kind="lib" path="lib/commons-httpclient-3.0.jar"/>
5
	<classpathentry exported="true" kind="lib" path="lib/commons-httpclient-3.0.jar" sourcepath="lib/commons-httpclient-3.0-src.zip"/>
6
	<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
6
	<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
7
	<classpathentry kind="src" path="src"/>
7
	<classpathentry kind="src" path="src"/>
8
	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/J2SE-1.5">
8
	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/J2SE-1.5">
(-)src/org/eclipse/mylar/internal/bugzilla/core/BugzillaRepositoryConnector.java (-7 / +16 lines)
Lines 193-206 Link Here
193
	public String getRepositoryUrlFromTaskUrl(String url) {
193
	public String getRepositoryUrlFromTaskUrl(String url) {
194
		if (url == null) {
194
		if (url == null) {
195
			return null;
195
			return null;
196
		} else {
197
			int index = url.indexOf(IBugzillaConstants.URL_GET_SHOW_BUG);
198
			if (index != -1) {
199
				return url.substring(0, index);
200
			} else {
201
				return null;
202
			}
203
		}
196
		}
197
		int index = url.indexOf(IBugzillaConstants.URL_GET_SHOW_BUG);
198
		return index == -1 ? null : url.substring(0, index);
199
	}
200
201
	@Override
202
	public String getTaskIdFromTaskUrl(String url) {
203
		if (url == null) {
204
			return null;
205
		}
206
		int index = url.indexOf(IBugzillaConstants.URL_GET_SHOW_BUG);
207
		return index == -1 ? null : url.substring(index + IBugzillaConstants.URL_GET_SHOW_BUG.length());
208
	}
209
	
210
	@Override
211
	public String getTaskWebUrl(String repositoryUrl, String taskId) {
212
		return repositoryUrl + IBugzillaConstants.URL_GET_SHOW_BUG + taskId;
204
	}
213
	}
205
214
206
	// @Override
215
	// @Override
(-)src/org/eclipse/mylar/internal/tasks/web/WebRepositoryConnector.java (-6 / +34 lines)
Lines 149-162 Link Here
149
149
150
	@Override
150
	@Override
151
	public String getRepositoryUrlFromTaskUrl(String url) {
151
	public String getRepositoryUrlFromTaskUrl(String url) {
152
		if (url == null) {
153
			return null;
154
		}
155
152
		// lookup repository using task prefix url
156
		// lookup repository using task prefix url
153
		TaskRepositoryManager repositoryManager = TasksUiPlugin.getRepositoryManager();
157
		TaskRepositoryManager repositoryManager = TasksUiPlugin.getRepositoryManager();
154
		for (TaskRepository repository : repositoryManager.getAllRepositories()) {
158
		for (TaskRepository repository : repositoryManager.getRepositories(getRepositoryType())) {
155
			if (getRepositoryType().equals(repository.getKind())) {
159
			String start = evaluateParams(repository.getProperty(PROPERTY_TASK_URL), repository);
156
				String start = evaluateParams(repository.getProperty(PROPERTY_TASK_URL), repository);
160
			if (start != null && url.startsWith(start)) {
157
				if (start != null && url.startsWith(start)) {
161
				return repository.getUrl();
158
					return repository.getUrl();
159
				}
160
			}
162
			}
161
		}
163
		}
162
164
Lines 173-179 Link Here
173
				}
175
				}
174
			}
176
			}
175
		}
177
		}
178
		return null;
179
	}
180
181
	@Override
182
	public String getTaskIdFromTaskUrl(String url) {
183
		if (url == null) {
184
			return null;
185
		}
176
186
187
		TaskRepositoryManager repositoryManager = TasksUiPlugin.getRepositoryManager();
188
		for (TaskRepository repository : repositoryManager.getRepositories(getRepositoryType())) {
189
			String start = evaluateParams(repository.getProperty(PROPERTY_TASK_URL), repository);
190
			if (start != null && url.startsWith(start)) {
191
				return url.substring(start.length());
192
			}
193
		}
194
		return null;
195
	}
196
	
197
	@Override
198
	public String getTaskWebUrl(String repositoryUrl, String taskId) {
199
		TaskRepositoryManager repositoryManager = TasksUiPlugin.getRepositoryManager();
200
		TaskRepository repository = repositoryManager.getRepository(getRepositoryType(), repositoryUrl);
201
		if (repository != null) {
202
			String prefix = evaluateParams(repository.getProperty(PROPERTY_TASK_URL), repository);
203
			return prefix + taskId;
204
		}
177
		return null;
205
		return null;
178
	}
206
	}
179
207
(-)src/org/eclipse/mylar/internal/tasks/ui/TaskUiUtil.java (-13 / +19 lines)
Lines 39-44 Link Here
39
import org.eclipse.mylar.tasks.core.Task;
39
import org.eclipse.mylar.tasks.core.Task;
40
import org.eclipse.mylar.tasks.core.TaskCategory;
40
import org.eclipse.mylar.tasks.core.TaskCategory;
41
import org.eclipse.mylar.tasks.core.TaskRepository;
41
import org.eclipse.mylar.tasks.core.TaskRepository;
42
import org.eclipse.mylar.tasks.core.TaskRepositoryManager;
42
import org.eclipse.mylar.tasks.ui.AbstractRepositoryConnectorUi;
43
import org.eclipse.mylar.tasks.ui.AbstractRepositoryConnectorUi;
43
import org.eclipse.mylar.tasks.ui.TasksUiPlugin;
44
import org.eclipse.mylar.tasks.ui.TasksUiPlugin;
44
import org.eclipse.swt.graphics.Image;
45
import org.eclipse.swt.graphics.Image;
Lines 110-138 Link Here
110
		} else {
111
		} else {
111
			AbstractRepositoryConnectorUi connectorUi = TasksUiPlugin.getRepositoryUi(repository.getKind());
112
			AbstractRepositoryConnectorUi connectorUi = TasksUiPlugin.getRepositoryUi(repository.getKind());
112
			if (connectorUi != null) {
113
			if (connectorUi != null) {
113
				connectorUi.openRemoteTask(repository.getUrl(), taskId);
114
				opened = connectorUi.openRemoteTask(repository.getUrl(), taskId);
114
				opened = true;
115
			}
115
			}
116
		}
116
		}
117
		return opened;
117
		return opened;
118
	}
118
	}
119
119
120
	/**
120
	/**
121
	 * Either pass in a repository and id, or fullUrl, or all of them
121
	 * Either pass in a repositoryUrl and taskId, or fullUrl, or all of them
122
	 */
122
	 */
123
	public static boolean openRepositoryTask(String repositoryUrl, String taskId, String fullUrl) {
123
	public static boolean openRepositoryTask(String repositoryUrl, String taskId, String fullUrl) {
124
		boolean opened = false;
124
		TaskRepositoryManager repositoryManager = TasksUiPlugin.getRepositoryManager();
125
		AbstractRepositoryConnector connector = repositoryManager.getConnectorForRepositoryTaskUrl(fullUrl);
126
		if (taskId == null && connector != null) {
127
			taskId = connector.getTaskIdFromTaskUrl(fullUrl);
128
		}
129
		if (repositoryUrl == null && connector != null) {
130
			repositoryUrl = connector.getRepositoryUrlFromTaskUrl(fullUrl);
131
		}
132
125
		ITask task = null;
133
		ITask task = null;
126
		if (taskId != null) {
134
		if (taskId != null) {
127
			String handle = AbstractRepositoryTask.getHandle(repositoryUrl, taskId);
135
			String handle = AbstractRepositoryTask.getHandle(repositoryUrl, taskId);
128
			task = TasksUiPlugin.getTaskListManager().getTaskList().getTask(handle);
136
			task = TasksUiPlugin.getTaskListManager().getTaskList().getTask(handle);
129
		}
137
		}
130
		if (task == null) {
138
		if (task == null && fullUrl != null) {
131
			// search for it
139
			// search by fullUrl
132
			for (ITask currTask : TasksUiPlugin.getTaskListManager().getTaskList().getAllTasks()) {
140
			for (ITask currTask : TasksUiPlugin.getTaskListManager().getTaskList().getAllTasks()) {
133
				if (currTask instanceof AbstractRepositoryTask) {
141
				if (currTask instanceof AbstractRepositoryTask) {
134
					String currUrl = ((AbstractRepositoryTask) currTask).getUrl();
142
					String currUrl = ((AbstractRepositoryTask) currTask).getUrl();
135
					if (currUrl != null && !currUrl.equals("") && currUrl.equals(fullUrl)) {
143
					if (fullUrl.equals(currUrl)) {
136
						task = currTask;
144
						task = currTask;
137
						break;
145
						break;
138
					}
146
					}
Lines 140-158 Link Here
140
			}
148
			}
141
		}
149
		}
142
150
151
		boolean opened = false;
143
		if (task != null) {
152
		if (task != null) {
144
			TaskUiUtil.refreshAndOpenTaskListElement(task);
153
			TaskUiUtil.refreshAndOpenTaskListElement(task);
145
			opened = true;
154
			opened = true;
146
		} else {
155
		} else if (connector != null) {
147
			AbstractRepositoryConnector connector = TasksUiPlugin.getRepositoryManager()
148
					.getConnectorForRepositoryTaskUrl(fullUrl);
149
			AbstractRepositoryConnectorUi connectorUi = TasksUiPlugin.getRepositoryUi(connector.getRepositoryType());
156
			AbstractRepositoryConnectorUi connectorUi = TasksUiPlugin.getRepositoryUi(connector.getRepositoryType());
150
157
			if (connectorUi != null) {
151
			if (connector != null) {
152
				opened = connectorUi.openRemoteTask(repositoryUrl, taskId);
158
				opened = connectorUi.openRemoteTask(repositoryUrl, taskId);
153
			}
159
			}
154
		}
160
		}
155
		if (!opened) {
161
		if (!opened && fullUrl != null) {
156
			TaskUiUtil.openUrl(fullUrl);
162
			TaskUiUtil.openUrl(fullUrl);
157
			opened = true;
163
			opened = true;
158
		}
164
		}
(-)src/org/eclipse/mylar/tasks/ui/AbstractRepositoryConnectorUi.java (-5 / +13 lines)
Lines 14-23 Link Here
14
import org.eclipse.jface.wizard.WizardDialog;
14
import org.eclipse.jface.wizard.WizardDialog;
15
import org.eclipse.jface.wizard.WizardPage;
15
import org.eclipse.jface.wizard.WizardPage;
16
import org.eclipse.mylar.context.core.MylarStatusHandler;
16
import org.eclipse.mylar.context.core.MylarStatusHandler;
17
import org.eclipse.mylar.internal.tasks.ui.TaskUiUtil;
17
import org.eclipse.mylar.internal.tasks.ui.wizards.AbstractRepositorySettingsPage;
18
import org.eclipse.mylar.internal.tasks.ui.wizards.AbstractRepositorySettingsPage;
18
import org.eclipse.mylar.internal.tasks.ui.wizards.CommonAddExistingTaskWizard;
19
import org.eclipse.mylar.internal.tasks.ui.wizards.CommonAddExistingTaskWizard;
20
import org.eclipse.mylar.tasks.core.AbstractRepositoryConnector;
19
import org.eclipse.mylar.tasks.core.AbstractRepositoryQuery;
21
import org.eclipse.mylar.tasks.core.AbstractRepositoryQuery;
20
import org.eclipse.mylar.tasks.core.TaskRepository;
22
import org.eclipse.mylar.tasks.core.TaskRepository;
23
import org.eclipse.mylar.tasks.core.TaskRepositoryManager;
21
import org.eclipse.swt.widgets.Shell;
24
import org.eclipse.swt.widgets.Shell;
22
import org.eclipse.ui.PlatformUI;
25
import org.eclipse.ui.PlatformUI;
23
26
Lines 82-94 Link Here
82
85
83
	/**
86
	/**
84
	 * Only override if task should be opened by a custom editor, default
87
	 * Only override if task should be opened by a custom editor, default
85
	 * beahvior is to open with browser.
88
	 * behavior is to open with browser.
86
	 * 
89
	 * 
87
	 * @return	true if the task was successfully opened
90
	 * @return true if the task was successfully opened
88
	 */
91
	 */
89
	public boolean openRemoteTask(String repositoryUrl, String idString) {
92
	public boolean openRemoteTask(String repositoryUrl, String idString) {
90
		return false;
93
		TaskRepositoryManager repositoryManager = TasksUiPlugin.getRepositoryManager();
91
//		MessageDialog.openInformation(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(),
94
		AbstractRepositoryConnector connector = repositoryManager.getRepositoryConnector(getRepositoryType());
92
//				TasksUiPlugin.TITLE_DIALOG, "Not supported by connector: " + this.getClass().getSimpleName());
95
		TaskUiUtil.openUrl(connector.getTaskWebUrl(repositoryUrl, idString));
96
97
		return true;
98
		// MessageDialog.openInformation(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(),
99
		// TasksUiPlugin.TITLE_DIALOG, "Not supported by connector: " +
100
		// this.getClass().getSimpleName());
93
	}
101
	}
94
}
102
}
(-)src/org/eclipse/mylar/internal/jira/core/JiraRepositoryConnector.java (-3 / +14 lines)
Lines 198-207 Link Here
198
			return null;
198
			return null;
199
		}
199
		}
200
		int index = url.indexOf(DELIM_URL);
200
		int index = url.indexOf(DELIM_URL);
201
		if (index != -1) {
201
		return index == -1 ? null : url.substring(0, index);
202
			return url.substring(0, index);
202
	}
203
204
	@Override
205
	public String getTaskIdFromTaskUrl(String url) {
206
		if (url == null) {
207
			return null;
203
		}
208
		}
204
		return null;
209
		int index = url.indexOf(DELIM_URL);
210
		return index == -1 ? null : url.substring(index + DELIM_URL.length());
211
	}
212
	
213
	@Override
214
	public String getTaskWebUrl(String repositoryUrl, String taskId) {
215
		return repositoryUrl + DELIM_URL + taskId;
205
	}
216
	}
206
217
207
	public static void updateTaskDetails(String repositoryUrl, JiraTask task, Issue issue, boolean notifyOfChange) {
218
	public static void updateTaskDetails(String repositoryUrl, JiraTask task, Issue issue, boolean notifyOfChange) {
(-)src/org/eclipse/mylar/internal/jira/core/JiraServerFacade.java (-2 / +5 lines)
Lines 53-60 Link Here
53
			String serverHostname = getServerHost(repository);
53
			String serverHostname = getServerHost(repository);
54
			JiraServer server = serverManager.getServer(serverHostname);
54
			JiraServer server = serverManager.getServer(serverHostname);
55
			if (server == null) {
55
			if (server == null) {
56
				server = serverManager.createServer(serverHostname, repository.getUrl(), false,
56
				String userName = repository.getUserName();
57
						repository.getUserName(), repository.getPassword());
57
				String password = repository.getPassword();
58
				server = serverManager.createServer(serverHostname, repository.getUrl(), false, //
59
						userName == null ? "" : userName, //
60
						password == null ? "" : password);
58
				serverManager.addServer(server);
61
				serverManager.addServer(server);
59
			}
62
			}
60
			return server;
63
			return server;
(-)src/org/eclipse/mylar/internal/team/ui/actions/OpenCorrespondingTaskAction.java (-200 / +267 lines)
Lines 11-253 Link Here
11
11
12
package org.eclipse.mylar.internal.team.ui.actions;
12
package org.eclipse.mylar.internal.team.ui.actions;
13
13
14
import org.eclipse.compare.structuremergeviewer.IDiffElement;
15
import org.eclipse.core.resources.IProject;
16
import org.eclipse.core.resources.IResource;
17
import org.eclipse.core.resources.IWorkspaceRoot;
18
import org.eclipse.core.resources.ResourcesPlugin;
19
import org.eclipse.core.runtime.IAdaptable;
14
import org.eclipse.core.runtime.IAdaptable;
20
import org.eclipse.core.runtime.Path;
15
import org.eclipse.core.runtime.Platform;
21
import org.eclipse.jface.action.Action;
16
import org.eclipse.jface.action.Action;
22
import org.eclipse.jface.action.IAction;
17
import org.eclipse.jface.action.IAction;
23
import org.eclipse.jface.viewers.ISelection;
18
import org.eclipse.jface.viewers.ISelection;
24
import org.eclipse.jface.viewers.StructuredSelection;
19
import org.eclipse.jface.viewers.StructuredSelection;
25
import org.eclipse.mylar.internal.tasks.ui.TaskListImages;
20
import org.eclipse.mylar.internal.tasks.ui.TaskListImages;
26
import org.eclipse.mylar.internal.tasks.ui.TaskUiUtil;
21
import org.eclipse.mylar.internal.tasks.ui.TaskUiUtil;
27
import org.eclipse.mylar.internal.team.ContextChangeSet;
22
import org.eclipse.mylar.internal.team.ILinkedTaskInfo;
28
import org.eclipse.mylar.tasks.core.AbstractRepositoryConnector;
29
import org.eclipse.mylar.tasks.core.AbstractRepositoryTask;
30
import org.eclipse.mylar.tasks.core.ITask;
31
import org.eclipse.mylar.tasks.core.TaskRepository;
23
import org.eclipse.mylar.tasks.core.TaskRepository;
32
import org.eclipse.mylar.tasks.ui.AbstractRepositoryConnectorUi;
33
import org.eclipse.mylar.tasks.ui.TasksUiPlugin;
24
import org.eclipse.mylar.tasks.ui.TasksUiPlugin;
34
import org.eclipse.mylar.team.MylarTeamPlugin;
35
import org.eclipse.team.core.history.IFileRevision;
36
import org.eclipse.team.core.variants.IResourceVariant;
37
import org.eclipse.team.internal.ccvs.core.client.listeners.LogEntry;
38
import org.eclipse.team.internal.ccvs.core.mapping.CVSCheckedInChangeSet;
39
import org.eclipse.team.internal.ccvs.core.resources.RemoteResource;
40
import org.eclipse.team.internal.core.subscribers.DiffChangeSet;
41
import org.eclipse.team.internal.ui.synchronize.ChangeSetDiffNode;
42
import org.eclipse.team.internal.ui.synchronize.SynchronizeModelElement;
43
import org.eclipse.ui.IViewActionDelegate;
25
import org.eclipse.ui.IViewActionDelegate;
44
import org.eclipse.ui.IViewPart;
26
import org.eclipse.ui.IViewPart;
45
import org.eclipse.ui.internal.ObjectPluginAction;
27
import org.eclipse.ui.internal.ObjectPluginAction;
46
28
47
/**
29
/**
48
 * @author Mik Kersten
30
 * @author Mik Kersten
31
 * @author Eugene Kuleshov
49
 */
32
 */
50
public class OpenCorrespondingTaskAction extends Action implements IViewActionDelegate {
33
public class OpenCorrespondingTaskAction extends Action implements IViewActionDelegate {
51
34
52
	private static final String LABEL = "Open Corresponding Task";
35
    private static final String LABEL = "Open Corresponding Task";
53
36
54
	private ISelection selection;
37
    private ISelection selection;
55
38
56
	private static final String PREFIX_HTTP = "http://";
39
//    private static final String PREFIX_HTTP = "http://";
57
40
58
	private static final String PREFIX_HTTPS = "https://";
41
//    private static final String PREFIX_HTTPS = "https://";
59
42
60
	public OpenCorrespondingTaskAction() {
43
    public OpenCorrespondingTaskAction() {
61
		setText(LABEL);
44
        setText(LABEL);
62
		setToolTipText(LABEL);
45
        setToolTipText(LABEL);
63
		setImageDescriptor(TaskListImages.TASK_REPOSITORY);
46
        setImageDescriptor(TaskListImages.TASK_REPOSITORY);
64
	}
47
    }
65
48
66
	public void init(IViewPart view) {
49
    public void init(IViewPart view) {
67
		// ignore
50
        // ignore
68
	}
51
    }
69
52
70
	@Override
53
    @Override
71
	public void run() {
54
    public void run() {
72
		if (selection instanceof StructuredSelection) {
55
        if (selection instanceof StructuredSelection) {
73
			run((StructuredSelection) selection);
56
            run((StructuredSelection) selection);
57
        }
58
    }
59
60
    public void run(IAction action) {
61
        if (action instanceof ObjectPluginAction) {
62
            ObjectPluginAction objectAction = (ObjectPluginAction) action;
63
            if (objectAction.getSelection() instanceof StructuredSelection) {
64
                StructuredSelection selection = (StructuredSelection) objectAction.getSelection();
65
                run(selection);
66
            }
67
        }
68
    }
69
70
    private void run(StructuredSelection selection) {
71
        Object element = selection.getFirstElement();
72
        
73
        ILinkedTaskInfo info = null;
74
		if (element instanceof IAdaptable) {
75
			info = (ILinkedTaskInfo) ((IAdaptable) element).getAdapter(ILinkedTaskInfo.class);
74
		}
76
		}
75
	}
77
		if (info == null) {
76
78
			info = (ILinkedTaskInfo) Platform.getAdapterManager().getAdapter(element, ILinkedTaskInfo.class);
77
	public void run(IAction action) {
78
		if (action instanceof ObjectPluginAction) {
79
			ObjectPluginAction objectAction = (ObjectPluginAction) action;
80
			if (objectAction.getSelection() instanceof StructuredSelection) {
81
				StructuredSelection selection = (StructuredSelection) objectAction.getSelection();
82
				run(selection);
83
			}
84
		}
79
		}
85
	}
80
		
86
81
		if (info != null) {
87
	private void run(StructuredSelection selection) {
82
			if(info.getTask()!=null) {
88
		Object element = selection.getFirstElement();
83
				// TODO Which one to use?
89
		boolean opened = false;
84
				// TaskUiUtil.openEditor(info.getTask(), false);
90
85
				TaskUiUtil.refreshAndOpenTaskListElement(info.getTask());
91
		if (element instanceof ChangeSetDiffNode) {
86
				return;
92
			ChangeSetDiffNode diffNode = (ChangeSetDiffNode) element;
93
			if (diffNode.getSet() instanceof ContextChangeSet) {
94
				ITask task = ((ContextChangeSet) diffNode.getSet()).getTask();
95
				TaskUiUtil.openEditor(task, false);
96
				opened = true;
97
			} 
98
		} else if (element instanceof ContextChangeSet) {
99
			ITask task = ((ContextChangeSet) element).getTask();
100
			if (task != null) {
101
				TaskUiUtil.openEditor(task, false);
102
				opened = true;
103
			}
87
			}
104
		}
88
			if(info.getRepositoryUrl()!=null && info.getTaskId()!=null) {
105
89
				TaskRepository repository = TasksUiPlugin.getRepositoryManager().getRepository(info.getRepositoryUrl());
106
		if (!opened) {
90
				if(repository!=null) {
107
			IProject project = findCorrespondingProject(element);
91
					if(TaskUiUtil.openRepositoryTask(repository, info.getTaskId())) {
108
			String comment = getCommentFromSelection(element);
92
						return;
109
			
93
					}
110
			if (comment != null) {
111
				String id = MylarTeamPlugin.getDefault().getCommitTemplateManager()
112
						.getTaskIdFromCommentOrLabel(comment);
113
				if (id == null) {
114
					id = getTaskIdFromLegacy07Label(comment);
115
				}
94
				}
116
				
95
			}
96
			if(info.getTaskFullUrl()!=null) {
97
				TaskUiUtil.openUrl(info.getTaskFullUrl());
98
				return;
99
			}
100
		}
101
		
102
		// XXX show open remote task dialog  
103
		
104
		return;
105
/*        
106
        if (element instanceof ChangeSetDiffNode) {
107
            ChangeSetDiffNode diffNode = (ChangeSetDiffNode) element;
108
            ChangeSet set = diffNode.getSet();
109
            if (set instanceof ContextChangeSet) {
110
                ITask task = ((ContextChangeSet) set).getTask();
111
                TaskUiUtil.openEditor(task, false);
112
                return;
113
            } else {
114
                if(set.getClass().getName().startsWith("org.tigris")) {
115
                    if(openIssueFromSubclipseChangeset(diffNode, set)) {
116
                        return;
117
                    }
118
                }
119
            }
120
        } else if (element instanceof ContextChangeSet) {
121
            ITask task = ((ContextChangeSet) element).getTask();
122
            if (task != null) {
123
                TaskUiUtil.openEditor(task, false);
124
                return;
125
            }
126
        }
127
128
        String comment = getCommentFromSelection(element);
129
        if (comment != null) {
130
            String id = MylarTeamPlugin.getDefault().getCommitTemplateManager()
131
                    .getTaskIdFromCommentOrLabel(comment);
132
            if (id == null) {
133
                id = getTaskIdFromLegacy07Label(comment);
134
            }
135
136
            boolean opened = false;
137
            if (id != null) {
138
				IProject project = findCorrespondingProject(element);
117
				if (project != null) {
139
				if (project != null) {
118
					TaskRepository repository = TasksUiPlugin.getDefault().getRepositoryForResource(project, false);
140
					TaskRepository repository = TasksUiPlugin.getDefault().getRepositoryForResource(project, false);
119
					if (repository != null) {
141
					if (repository != null) {
120
						AbstractRepositoryConnectorUi connectorUi = TasksUiPlugin.getRepositoryUi(repository.getKind());
142
						opened = TaskUiUtil.openRepositoryTask(repository, id);
121
						if (connectorUi != null && id != null) {
122
							opened = TaskUiUtil.openRepositoryTask(repository, id);
123
						}
124
					}
143
					}
125
				}
144
				}
145
			}
126
146
127
				// try opening via URL if present
147
            // try opening via URL if present
128
				if (!opened) {
148
            if (!opened) {
129
					String fullUrl = getUrlFromComment(comment);
149
                String fullUrl = getUrlFromComment(comment);
130
150
131
					String repositoryUrl = null;
151
                String repositoryUrl = null;
132
					if (fullUrl != null) {
152
                if (fullUrl != null) {
133
						AbstractRepositoryConnector connector = TasksUiPlugin.getRepositoryManager()
153
                    AbstractRepositoryConnector connector = TasksUiPlugin.getRepositoryManager()
134
								.getConnectorForRepositoryTaskUrl(fullUrl);
154
                            .getConnectorForRepositoryTaskUrl(fullUrl);
135
						if (connector != null) {
155
                    if (connector != null) {
136
							repositoryUrl = connector.getRepositoryUrlFromTaskUrl(fullUrl);
156
                        repositoryUrl = connector.getRepositoryUrlFromTaskUrl(fullUrl);
137
						}
157
                    }
138
					} else {
158
                } else {
139
						ITask task = TasksUiPlugin.getTaskListManager().getTaskList().getActiveTask();
159
                    // WTF?! opening a random task?
140
						if (task instanceof AbstractRepositoryTask) {
160
                	ITask task = TasksUiPlugin.getTaskListManager().getTaskList().getActiveTask();
141
							repositoryUrl = ((AbstractRepositoryTask) task).getRepositoryUrl();
161
                    if (task instanceof AbstractRepositoryTask) {
142
						} else if (TasksUiPlugin.getRepositoryManager().getAllRepositories().size() == 1) {
162
                        repositoryUrl = ((AbstractRepositoryTask) task).getRepositoryUrl();
143
							repositoryUrl = TasksUiPlugin.getRepositoryManager().getAllRepositories().get(0).getUrl();
163
                    } else if (TasksUiPlugin.getRepositoryManager().getAllRepositories().size() == 1) {
144
						}
164
                        repositoryUrl = TasksUiPlugin.getRepositoryManager().getAllRepositories().get(0).getUrl();
145
					}
165
                    }
166
                }
146
167
168
                if ((repositoryUrl != null && id != null) || fullUrl != null) {
147
					opened = TaskUiUtil.openRepositoryTask(repositoryUrl, id, fullUrl);
169
					opened = TaskUiUtil.openRepositoryTask(repositoryUrl, id, fullUrl);
148
					if (!opened) {
170
					if (!opened && fullUrl != null) {
149
						TaskUiUtil.openUrl(fullUrl);
171
						TaskUiUtil.openUrl(fullUrl);
150
					}
172
					}
151
				}
173
				}
152
			}
174
            }
153
		}
175
        }
154
	}
176
*/        
177
    }
155
178
156
	private String getCommentFromSelection(Object element) {
179
/*
157
		if (element instanceof DiffChangeSet) {
180
    private boolean openIssueFromSubclipseChangeset(ChangeSetDiffNode diff, ChangeSet set) {
158
			return ((CVSCheckedInChangeSet) element).getComment();
159
		} else if (element instanceof ChangeSetDiffNode) {
160
			return ((ChangeSetDiffNode) element).getName();
161
		} else if (element instanceof LogEntry) {
162
			return ((LogEntry) element).getComment();
163
		} else if (element instanceof IFileRevision) {
164
			return ((IFileRevision) element).getComment();
165
		}
166
		return null;
167
	}
168
169
	private IProject findCorrespondingProject(Object element) {
170
		if (element instanceof DiffChangeSet) {
171
			IResource[] resources = ((DiffChangeSet) element).getResources();
172
			if (resources.length > 0) {
173
				// TODO: only checks first resource
174
				return resources[0].getProject();
175
			}
176
		} else if (element instanceof SynchronizeModelElement) {
177
			SynchronizeModelElement modelElement = (SynchronizeModelElement)element;
178
			IResource resource = modelElement.getResource();
179
			if (resource != null) {
180
				return resource.getProject();
181
			} else {
182
				IDiffElement[] elements = modelElement.getChildren();
183
				if (elements.length > 0) {
184
					// TODO: only checks first diff
185
					if (elements[0] instanceof SynchronizeModelElement) {
186
						return ((SynchronizeModelElement)elements[0]).getResource().getProject();
187
					}
188
				}
189
			}
190
		} else if (element instanceof IAdaptable) {
191
			// TODO: there must be a better way to get at the local resource
192
			IResourceVariant resourceVariant = (IResourceVariant) ((IAdaptable) element)
193
					.getAdapter(IResourceVariant.class);
194
			if (resourceVariant != null && resourceVariant instanceof RemoteResource) {
195
				RemoteResource remoteResource = (RemoteResource) resourceVariant;
196
				String path = remoteResource.getRepositoryRelativePath();
197
				IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
198
				return root.getProject(new Path(path).removeFirstSegments(1).uptoSegment(1).toString());
199
			}
200
		} else {
201
			
202
		}
203
		return null;
204
	}
205
181
206
	public static String getUrlFromComment(String comment) {
182
        SynchronizeModelElement diffContainer = (SynchronizeModelElement) diff.getChildren()[0];
207
		int httpIndex = comment.indexOf(PREFIX_HTTP);
208
		int httpsIndex = comment.indexOf(PREFIX_HTTPS);
209
		int idStart = -1;
210
		if (httpIndex != -1) {
211
			idStart = httpIndex;
212
		} else if (httpsIndex != -1) {
213
			idStart = httpsIndex;
214
		}
215
		if (idStart != -1) {
216
			int idEnd = comment.indexOf(' ', idStart);
217
			if (idEnd == -1) {
218
				return comment.substring(idStart);
219
			} else if (idEnd != -1 && idStart < idEnd) {
220
				return comment.substring(idStart, idEnd);
221
			}
222
		}
223
		return null;
224
	}
225
183
226
	public static String getTaskIdFromLegacy07Label(String comment) {
184
        IResource res = diffContainer.getResource();
227
		String PREFIX_DELIM = ":";
185
228
		String PREFIX_START_1 = "Progress on:";
186
        SyncInfoModelElement melement = (SyncInfoModelElement) diffContainer.getChildren()[0];
229
		String PREFIX_START_2 = "Completed:";
187
230
		String usedPrefix = PREFIX_START_1;
188
        // Specific to Subclipse
231
		int firstDelimIndex = comment.indexOf(PREFIX_START_1);
189
        SVNStatusSyncInfo info = (SVNStatusSyncInfo) melement.getSyncInfo();
232
		if (firstDelimIndex == -1) {
190
233
			firstDelimIndex = comment.indexOf(PREFIX_START_2);
191
        ISVNRemoteResource remoteResource = (ISVNRemoteResource) info.getRemote();
234
			usedPrefix = PREFIX_START_2;
192
        SVNRevision rev = remoteResource.getLastChangedRevision();
235
		}
193
236
		if (firstDelimIndex != -1) {
194
		String comment;
237
			int idStart = firstDelimIndex + usedPrefix.length();
195
		try {
238
			int idEnd = comment.indexOf(PREFIX_DELIM, firstDelimIndex + usedPrefix.length());// comment.indexOf(PREFIX_DELIM);
196
			ISVNLogMessage[] messages = remoteResource.getLogMessages(rev, rev, SVNRevision.START, false, false, 1);
239
			if (idEnd != -1 && idStart < idEnd) {
197
			comment = messages[0].getMessage();
240
				String id = comment.substring(idStart, idEnd);
198
		} catch (TeamException ex) {
241
				if (id != null) {
199
			comment = diff.getSet().getComment();
242
					return id.trim();
200
		}
243
				}
201
            
244
			} else {
202
		ProjectProperties props = null;
245
				return comment.substring(0, firstDelimIndex);
203
		try {
246
			}
204
			props = ProjectProperties.getProjectProperties(res);
205
		} catch (TeamException ex) {
206
			// ignore?
207
		}
208
		String[] urls = null;
209
		if(props!=null) {
210
			urls = props.getLinkList(comment).getUrls();
247
		}
211
		}
248
		return null;
212
		if (urls == null || urls.length == 0) {
249
	}
213
			urls = ProjectProperties.getUrls(comment).getUrls();
250
	
214
		}
215
		if (urls != null && urls.length > 0) {
216
			String taskUrl = urls[0];
217
			TaskUiUtil.openRepositoryTask(null, null, taskUrl);
218
			return true;
219
		}
220
		return false;
221
    }
222
223
    private String getCommentFromSelection(Object element) {
224
        if (element instanceof DiffChangeSet) {
225
            return ((CVSCheckedInChangeSet) element).getComment();
226
        } else if (element instanceof ChangeSetDiffNode) {
227
            return ((ChangeSetDiffNode) element).getName();
228
        } else if (element instanceof LogEntry) {
229
            return ((LogEntry) element).getComment();
230
        } else if (element instanceof IFileRevision) {
231
            return ((IFileRevision) element).getComment();
232
        }
233
        return null;
234
    }
235
236
    private IProject findCorrespondingProject(Object element) {
237
        if (element instanceof DiffChangeSet) {
238
            IResource[] resources = ((DiffChangeSet) element).getResources();
239
            if (resources.length > 0) {
240
                // TODO: only checks first resource
241
                return resources[0].getProject();
242
            }
243
        } else if (element instanceof SynchronizeModelElement) {
244
            SynchronizeModelElement modelElement = (SynchronizeModelElement)element;
245
            IResource resource = modelElement.getResource();
246
            if (resource != null) {
247
                return resource.getProject();
248
            } else {
249
                IDiffElement[] elements = modelElement.getChildren();
250
                if (elements.length > 0) {
251
                    // TODO: only checks first diff
252
                    if (elements[0] instanceof SynchronizeModelElement) {
253
                        return ((SynchronizeModelElement)elements[0]).getResource().getProject();
254
                    }
255
                }
256
            }
257
        } else if (element instanceof IAdaptable) {
258
            // TODO: there must be a better way to get at the local resource
259
            IResourceVariant resourceVariant = (IResourceVariant) ((IAdaptable) element)
260
                    .getAdapter(IResourceVariant.class);
261
            if (resourceVariant != null && resourceVariant instanceof RemoteResource) {
262
                RemoteResource remoteResource = (RemoteResource) resourceVariant;
263
                String path = remoteResource.getRepositoryRelativePath();
264
                IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
265
                return root.getProject(new Path(path).removeFirstSegments(1).uptoSegment(1).toString());
266
            }
267
        } else {
268
269
        }
270
        return null;
271
    }
272
273
    public static String getUrlFromComment(String comment) {
274
        int httpIndex = comment.indexOf(PREFIX_HTTP);
275
        int httpsIndex = comment.indexOf(PREFIX_HTTPS);
276
        int idStart = -1;
277
        if (httpIndex != -1) {
278
            idStart = httpIndex;
279
        } else if (httpsIndex != -1) {
280
            idStart = httpsIndex;
281
        }
282
        if (idStart != -1) {
283
            int idEnd = comment.indexOf(' ', idStart);
284
            if (idEnd == -1) {
285
                return comment.substring(idStart);
286
            } else if (idEnd != -1 && idStart < idEnd) {
287
                return comment.substring(idStart, idEnd);
288
            }
289
        }
290
        return null;
291
    }
292
293
    public static String getTaskIdFromLegacy07Label(String comment) {
294
        String PREFIX_DELIM = ":";
295
        String PREFIX_START_1 = "Progress on:";
296
        String PREFIX_START_2 = "Completed:";
297
        String usedPrefix = PREFIX_START_1;
298
        int firstDelimIndex = comment.indexOf(PREFIX_START_1);
299
        if (firstDelimIndex == -1) {
300
            firstDelimIndex = comment.indexOf(PREFIX_START_2);
301
            usedPrefix = PREFIX_START_2;
302
        }
303
        if (firstDelimIndex != -1) {
304
            int idStart = firstDelimIndex + usedPrefix.length();
305
            int idEnd = comment.indexOf(PREFIX_DELIM, firstDelimIndex + usedPrefix.length());// comment.indexOf(PREFIX_DELIM);
306
            if (idEnd != -1 && idStart < idEnd) {
307
                String id = comment.substring(idStart, idEnd);
308
                if (id != null) {
309
                    return id.trim();
310
                }
311
            } else {
312
                return comment.substring(0, firstDelimIndex);
313
            }
314
        }
315
        return null;
316
    }
317
*/
251
318
252
//	private Object findParent(ISynchronizeModelElement element) {
319
//	private Object findParent(ISynchronizeModelElement element) {
253
//		if (element instanceof ChangeSetDiffNode) {
320
//		if (element instanceof ChangeSetDiffNode) {
Lines 257-266 Link Here
257
//		}
324
//		}
258
//		return null;
325
//		return null;
259
//	}
326
//	}
260
	
261
327
262
	public void selectionChanged(IAction action, ISelection selection) {
328
263
		this.selection = selection;
329
    public void selectionChanged(IAction action, ISelection selection) {
264
	}
330
        this.selection = selection;
331
    }
265
332
266
}
333
}
(-)src/org/eclipse/mylar/team/MylarTeamPlugin.java (+5 lines)
Lines 13-18 Link Here
13
13
14
import org.eclipse.mylar.context.core.MylarStatusHandler;
14
import org.eclipse.mylar.context.core.MylarStatusHandler;
15
import org.eclipse.mylar.internal.team.ContextChangeSetManager;
15
import org.eclipse.mylar.internal.team.ContextChangeSetManager;
16
import org.eclipse.mylar.internal.team.LinkedTaskInfoAdapterFactory;
16
import org.eclipse.mylar.internal.team.template.CommitTemplateManager;
17
import org.eclipse.mylar.internal.team.template.CommitTemplateManager;
17
import org.eclipse.ui.IStartup;
18
import org.eclipse.ui.IStartup;
18
import org.eclipse.ui.PlatformUI;
19
import org.eclipse.ui.PlatformUI;
Lines 60-65 Link Here
60
				}
61
				}
61
			}
62
			}
62
		});
63
		});
64
		
65
		LinkedTaskInfoAdapterFactory.registerAdapters();
63
	}
66
	}
64
67
65
	public void earlyStartup() {
68
	public void earlyStartup() {
Lines 71-76 Link Here
71
		INSTANCE = null;
74
		INSTANCE = null;
72
		super.stop(context);
75
		super.stop(context);
73
		changeSetManager.disable();
76
		changeSetManager.disable();
77
78
		LinkedTaskInfoAdapterFactory.unregisterAdapters();
74
	}
79
	}
75
80
76
	private void initPreferenceDefaults() {
81
	private void initPreferenceDefaults() {
(-)plugin.xml (+16 lines)
Lines 68-73 Link Here
68
	           tooltip="Open Corresponding Task"> 
68
	           tooltip="Open Corresponding Task"> 
69
	  		</action> 
69
	  		</action> 
70
	    </objectContribution>
70
	    </objectContribution>
71
		
72
		<!-- Subclipse History view -->
73
		<objectContribution
74
            objectClass="org.tigris.subversion.subclipse.core.history.LogEntry"
75
            id="org.eclipse.mylar.ui.team.synchronize.open.report">
76
         <action
77
	           class="org.eclipse.mylar.internal.team.ui.actions.OpenCorrespondingTaskAction"
78
	           enablesFor="1" 
79
	           icon="icons/elcl16/task-repository.gif"
80
	           id="org.eclipse.mylar.ui.team.synchronize.contribution.open.report"
81
	           label="Open Corresponding Task"
82
	           menubarPath="mylar"
83
	           tooltip="Open Corresponding Task">
84
	  		</action> 
85
	    </objectContribution>
86
	    
71
	    <!--
87
	    <!--
72
		<objectContribution
88
		<objectContribution
73
            objectClass="org.eclipse.team.internal.ui.synchronize.ChangeSetDiffNode"
89
            objectClass="org.eclipse.team.internal.ui.synchronize.ChangeSetDiffNode"
(-)src/org/eclipse/mylar/internal/team/ILinkedTaskInfo.java (+33 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2004 - 2006 University Of British Columbia and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 *
8
 * Contributors:
9
 *     Eugene Kuleshov - initial API and implementation
10
 *******************************************************************************/
11
12
package org.eclipse.mylar.internal.team;
13
14
import org.eclipse.mylar.tasks.core.ITask;
15
16
/**
17
 * Task information linked to artifacts from version control integration 
18
 * 
19
 * TODO move to mylar core?
20
 * 
21
 * @author Eugene Kuleshov
22
 */
23
public interface ILinkedTaskInfo {
24
25
	String getTaskId();
26
27
	String getTaskFullUrl();
28
29
	String getRepositoryUrl();
30
	
31
	ITask getTask();
32
	
33
}
(-)src/org/eclipse/mylar/internal/team/LinkedTaskInfo.java (+120 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2004 - 2006 University Of British Columbia and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 *
8
 * Contributors:
9
 *     Eugene Kuleshov - initial API and implementation
10
 *******************************************************************************/
11
12
package org.eclipse.mylar.internal.team;
13
14
import org.eclipse.mylar.tasks.core.AbstractRepositoryConnector;
15
import org.eclipse.mylar.tasks.core.AbstractRepositoryTask;
16
import org.eclipse.mylar.tasks.core.ITask;
17
import org.eclipse.mylar.tasks.core.TaskRepository;
18
import org.eclipse.mylar.tasks.core.TaskRepositoryManager;
19
import org.eclipse.mylar.tasks.ui.TasksUiPlugin;
20
21
/**
22
 * Default implementation of {@link ILinkedTaskInfo}
23
 * 
24
 * @author Eugene Kuleshov
25
 */
26
public class LinkedTaskInfo implements ILinkedTaskInfo {
27
28
	private String taskId;
29
30
	private String taskFullUrl;
31
32
	private String repositoryUrl;
33
34
	private ITask task;
35
36
	public LinkedTaskInfo(ITask task) {
37
		init(task, //
38
				AbstractRepositoryTask.getRepositoryUrl(task.getHandleIdentifier()), //
39
				AbstractRepositoryTask.getTaskId(task.getHandleIdentifier()), //
40
				task.getUrl());
41
	}
42
43
	public LinkedTaskInfo(String taskFullUrl) {
44
		init(null, null, null, taskFullUrl);
45
	}
46
47
	public LinkedTaskInfo(String repositoryUrl, String taskId, String taskFullUrl) {
48
		init(null, repositoryUrl, taskId, taskFullUrl);
49
	}
50
51
	private void init(ITask task, String repositoryUrl, String taskId, String taskFullUrl) {
52
		// TODO should this even be here?
53
54
		TaskRepositoryManager repositoryManager = TasksUiPlugin.getRepositoryManager();
55
		AbstractRepositoryConnector connector = repositoryManager.getConnectorForRepositoryTaskUrl(taskFullUrl);
56
		if (connector == null && repositoryUrl != null) {
57
			TaskRepository repository = repositoryManager.getRepository(repositoryUrl);
58
			if (repository != null) {
59
				connector = repositoryManager.getRepositoryConnector(repository.getKind());
60
			}
61
		}
62
63
		if (repositoryUrl == null && connector != null) {
64
			repositoryUrl = connector.getRepositoryUrlFromTaskUrl(taskFullUrl);
65
		}
66
67
		if (taskId == null && connector != null) {
68
			taskId = connector.getTaskIdFromTaskUrl(taskFullUrl);
69
		}
70
71
		if (taskFullUrl == null && repositoryUrl != null && taskId != null && connector != null) {
72
			taskFullUrl = connector.getTaskWebUrl(repositoryUrl, taskId);
73
		}
74
		
75
		if (task == null) {
76
			if (taskId != null && repositoryUrl != null) {
77
				String handle = AbstractRepositoryTask.getHandle(repositoryUrl, taskId);
78
				task = TasksUiPlugin.getTaskListManager().getTaskList().getTask(handle);
79
			}
80
			if (task == null && taskFullUrl != null) {
81
				// search by fullUrl
82
				for (ITask currTask : TasksUiPlugin.getTaskListManager().getTaskList().getAllTasks()) {
83
					if (currTask instanceof AbstractRepositoryTask) {
84
						String currUrl = ((AbstractRepositoryTask) currTask).getUrl();
85
						if (taskFullUrl.equals(currUrl)) {
86
							task = currTask;
87
							break;
88
						}
89
					}
90
				}
91
			}
92
		}
93
94
		if (taskFullUrl == null && task != null) {
95
			taskFullUrl = task.getUrl();
96
		}
97
98
		this.task = task;
99
		this.repositoryUrl = repositoryUrl;
100
		this.taskId = taskId;
101
		this.taskFullUrl = taskFullUrl;
102
	}
103
104
	public String getRepositoryUrl() {
105
		return repositoryUrl;
106
	}
107
108
	public ITask getTask() {
109
		return task;
110
	}
111
112
	public String getTaskFullUrl() {
113
		return taskFullUrl;
114
	}
115
116
	public String getTaskId() {
117
		return taskId;
118
	}
119
120
}
(-)src/org/eclipse/mylar/internal/team/LinkedTaskInfoAdapterFactory.java (+333 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2004 - 2006 University Of British Columbia and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 *
8
 * Contributors:
9
 *     Eugene Kuleshov - initial API and implementation
10
 *******************************************************************************/
11
12
package org.eclipse.mylar.internal.team;
13
14
import org.eclipse.compare.structuremergeviewer.DiffNode;
15
import org.eclipse.compare.structuremergeviewer.IDiffElement;
16
import org.eclipse.core.resources.IProject;
17
import org.eclipse.core.resources.IResource;
18
import org.eclipse.core.resources.ResourcesPlugin;
19
import org.eclipse.core.runtime.IAdaptable;
20
import org.eclipse.core.runtime.IAdapterFactory;
21
import org.eclipse.core.runtime.IAdapterManager;
22
import org.eclipse.core.runtime.Platform;
23
import org.eclipse.mylar.internal.team.template.CommitTemplateManager;
24
import org.eclipse.mylar.tasks.core.TaskRepository;
25
import org.eclipse.mylar.tasks.ui.TasksUiPlugin;
26
import org.eclipse.mylar.team.MylarTeamPlugin;
27
import org.eclipse.team.core.TeamException;
28
import org.eclipse.team.core.history.IFileRevision;
29
import org.eclipse.team.core.variants.IResourceVariant;
30
import org.eclipse.team.internal.ccvs.core.CVSException;
31
import org.eclipse.team.internal.ccvs.core.ICVSResource;
32
import org.eclipse.team.internal.ccvs.core.resources.CVSWorkspaceRoot;
33
import org.eclipse.team.internal.ccvs.core.resources.RemoteResource;
34
import org.eclipse.team.internal.core.subscribers.ChangeSet;
35
import org.eclipse.team.internal.core.subscribers.DiffChangeSet;
36
import org.eclipse.team.internal.ui.synchronize.ChangeSetDiffNode;
37
import org.eclipse.team.internal.ui.synchronize.SyncInfoModelElement;
38
import org.eclipse.team.internal.ui.synchronize.SynchronizeModelElement;
39
import org.tigris.subversion.subclipse.core.ISVNRemoteResource;
40
import org.tigris.subversion.subclipse.core.sync.SVNStatusSyncInfo;
41
import org.tigris.subversion.subclipse.ui.settings.ProjectProperties;
42
import org.tigris.subversion.svnclientadapter.ISVNLogMessage;
43
import org.tigris.subversion.svnclientadapter.SVNRevision;
44
45
46
/**
47
 * Adapter factory used to create adapters for <code>LinkedTaskInfo</code> 
48
 * 
49
 * @author Eugene Kuleshov
50
 */
51
public class LinkedTaskInfoAdapterFactory implements IAdapterFactory {
52
53
	private static final Class[] ADAPTER_TYPES = new Class[] { ILinkedTaskInfo.class };
54
55
	private static IAdapterFactory FACTORY = new LinkedTaskInfoAdapterFactory();
56
57
	private static final String PREFIX_HTTP = "http://";
58
59
    private static final String PREFIX_HTTPS = "https://";
60
61
	
62
	public static void registerAdapters() {
63
		IAdapterManager adapterManager = Platform.getAdapterManager();
64
65
		// Mylar
66
		adapterManager.registerAdapters(FACTORY, ContextChangeSet.class);
67
68
		// Team public
69
		adapterManager.registerAdapters(FACTORY, IFileRevision.class);
70
		adapterManager.registerAdapters(FACTORY, DiffNode.class);
71
72
		// Team internal
73
		adapterManager.registerAdapters(FACTORY, DiffChangeSet.class); // CVSCheckedInChangeSet ???
74
		adapterManager.registerAdapters(FACTORY, ChangeSetDiffNode.class);
75
		adapterManager.registerAdapters(FACTORY, SynchronizeModelElement.class);
76
		
77
		// Team CVS internal; is it used? Maybe CVS History view in Eclipse 3.1?
78
		adapterManager.registerAdapters(FACTORY, org.eclipse.team.internal.ccvs.core.client.listeners.LogEntry.class);
79
		
80
		// Subclipse. need to do something when Subclibse is not installed		
81
		adapterManager.registerAdapters(FACTORY, org.tigris.subversion.subclipse.core.history.LogEntry.class);  
82
	}
83
	
84
	public static void unregisterAdapters() {
85
		Platform.getAdapterManager().unregisterAdapters(FACTORY); 
86
	}
87
    
88
	
89
	private LinkedTaskInfoAdapterFactory() {
90
	}
91
	
92
	public Object getAdapter(Object object, Class adapterType) {
93
		if(!ILinkedTaskInfo.class.equals(adapterType)) {
94
			return null;
95
		}
96
			
97
		if(object instanceof ChangeSetDiffNode) {
98
			return adaptChangeSetDiffNode(object);
99
		}
100
		
101
		if(object instanceof DiffNode) {
102
			return getAdapter(((DiffNode) object).getParent(), adapterType);
103
		}
104
		
105
		if(object instanceof org.tigris.subversion.subclipse.core.history.LogEntry) {
106
			return adaptSubclipseLogEntry(object);
107
		}
108
		
109
		// TODO add other adapted types
110
111
/*		
112
        if (object instanceof DiffChangeSet) {
113
            return ((CVSCheckedInChangeSet) object).getComment();
114
        } else if (object instanceof ChangeSetDiffNode) {
115
            return ((ChangeSetDiffNode) object).getName();
116
        } else if (object instanceof LogEntry) {
117
            return ((LogEntry) object).getComment();
118
        } else if (object instanceof IFileRevision) {
119
            return ((IFileRevision) object).getComment();
120
        }
121
*/		
122
		
123
		return adaptFromComment(object);
124
	}
125
126
	public Class[] getAdapterList() {
127
		return ADAPTER_TYPES;
128
	}
129
130
	private ILinkedTaskInfo adaptChangeSetDiffNode(Object object) {
131
        ChangeSetDiffNode diffNode = (ChangeSetDiffNode) object;
132
        ChangeSet set = diffNode.getSet();
133
        if (set instanceof ContextChangeSet) {
134
            return new LinkedTaskInfo(((ContextChangeSet) set).getTask());
135
        } else if(set.getClass().getName().startsWith("org.tigris")) {
136
            return adaptSubclipseChangeset(diffNode, set);
137
        }
138
139
        return adaptFromComment(object);
140
	}
141
142
	private ILinkedTaskInfo adaptSubclipseChangeset(ChangeSetDiffNode diff, ChangeSet set) {
143
        SynchronizeModelElement diffContainer = (SynchronizeModelElement) diff.getChildren()[0];
144
145
        IResource res = diffContainer.getResource();
146
147
        SyncInfoModelElement melement = (SyncInfoModelElement) diffContainer.getChildren()[0];
148
149
        // Specific to Subclipse
150
        SVNStatusSyncInfo info = (SVNStatusSyncInfo) melement.getSyncInfo();
151
152
        ISVNRemoteResource remoteResource = (ISVNRemoteResource) info.getRemote();
153
        SVNRevision rev = remoteResource.getLastChangedRevision();
154
155
		String comment;
156
		try {
157
			ISVNLogMessage[] messages = remoteResource.getLogMessages(rev, rev, SVNRevision.START, false, false, 1);
158
			comment = messages[0].getMessage();
159
		} catch (TeamException ex) {
160
			comment = diff.getSet().getComment();
161
		}
162
		return adaptFromComment(diff, res, comment);
163
	}
164
165
	private ILinkedTaskInfo adaptSubclipseLogEntry(Object object) {
166
		org.tigris.subversion.subclipse.core.history.LogEntry logEntry = 
167
			(org.tigris.subversion.subclipse.core.history.LogEntry) object;
168
169
		String comment = logEntry.getComment();
170
		IResource res = logEntry.getResource().getResource();
171
		
172
		return adaptFromComment(object, res, comment);
173
	}
174
175
	private ILinkedTaskInfo adaptFromComment(Object object, IResource res, String comment) {
176
		ProjectProperties props = null;
177
		try {
178
			props = ProjectProperties.getProjectProperties(res);
179
		} catch (TeamException ex) {
180
			// ignore?
181
		}
182
		String[] urls = null;
183
		if(props!=null) {
184
			urls = props.getLinkList(comment).getUrls();
185
		}
186
		if (urls == null || urls.length == 0) {
187
			urls = ProjectProperties.getUrls(comment).getUrls();
188
		}
189
		if (urls != null && urls.length > 0) {
190
			return new LinkedTaskInfo(urls[0]);
191
		}
192
		return adaptFromComment(object);
193
	}
194
195
	private ILinkedTaskInfo adaptFromComment(Object object) {
196
		String comment = getCommentFromElement(object);
197
		
198
		CommitTemplateManager commitTemplateManager = MylarTeamPlugin.getDefault().getCommitTemplateManager();
199
		String taskId = commitTemplateManager.getTaskIdFromCommentOrLabel(comment);
200
		if (taskId == null) {
201
			taskId = getTaskIdFromLegacy07Label(comment);
202
		}
203
204
		IProject project = findCorrespondingProject(object);
205
		if (project != null) {
206
			TaskRepository repository = TasksUiPlugin.getDefault().getRepositoryForResource(project, false);
207
			if (repository != null && taskId!=null) {
208
				return new LinkedTaskInfo(repository.getUrl(), taskId, null);
209
			}
210
		}
211
		
212
		String fullTaskUrl = getUrlFromComment(comment);
213
        if(fullTaskUrl!=null) {
214
        	return new LinkedTaskInfo(fullTaskUrl);
215
        }
216
        
217
        return null;
218
	}
219
	
220
    private String getCommentFromElement(Object element) {
221
        if (element instanceof DiffChangeSet) {
222
            return ((DiffChangeSet) element).getComment();
223
        } else if (element instanceof ChangeSetDiffNode) {
224
            return ((ChangeSetDiffNode) element).getName();
225
        } else if (element instanceof IFileRevision) {
226
        	return ((IFileRevision) element).getComment();
227
        } else if (element instanceof org.eclipse.team.internal.ccvs.core.client.listeners.LogEntry) {
228
            return ((org.eclipse.team.internal.ccvs.core.client.listeners.LogEntry) element).getComment();
229
        } else if (element instanceof org.tigris.subversion.subclipse.core.history.LogEntry) {
230
            return ((org.tigris.subversion.subclipse.core.history.LogEntry) element).getComment();
231
        }
232
        return null;
233
    }
234
	
235
	
236
	//
237
238
    public static String getUrlFromComment(String comment) {
239
        int httpIndex = comment.indexOf(PREFIX_HTTP);
240
        int httpsIndex = comment.indexOf(PREFIX_HTTPS);
241
        int idStart = -1;
242
        if (httpIndex != -1) {
243
            idStart = httpIndex;
244
        } else if (httpsIndex != -1) {
245
            idStart = httpsIndex;
246
        }
247
        if (idStart != -1) {
248
            int idEnd = comment.indexOf(' ', idStart);
249
            if (idEnd == -1) {
250
                return comment.substring(idStart);
251
            } else if (idEnd != -1 && idStart < idEnd) {
252
                return comment.substring(idStart, idEnd);
253
            }
254
        }
255
        return null;
256
    }
257
258
    public static String getTaskIdFromLegacy07Label(String comment) {
259
        String PREFIX_DELIM = ":";
260
        String PREFIX_START_1 = "Progress on:";
261
        String PREFIX_START_2 = "Completed:";
262
        String usedPrefix = PREFIX_START_1;
263
        int firstDelimIndex = comment.indexOf(PREFIX_START_1);
264
        if (firstDelimIndex == -1) {
265
            firstDelimIndex = comment.indexOf(PREFIX_START_2);
266
            usedPrefix = PREFIX_START_2;
267
        }
268
        if (firstDelimIndex != -1) {
269
            int idStart = firstDelimIndex + usedPrefix.length();
270
            int idEnd = comment.indexOf(PREFIX_DELIM, firstDelimIndex + usedPrefix.length());// comment.indexOf(PREFIX_DELIM);
271
            if (idEnd != -1 && idStart < idEnd) {
272
                String id = comment.substring(idStart, idEnd);
273
                if (id != null) {
274
                    return id.trim();
275
                }
276
            } else {
277
                return comment.substring(0, firstDelimIndex);
278
            }
279
        }
280
        return null;
281
    }
282
	
283
    private static IProject findCorrespondingProject(Object element) {
284
        if (element instanceof DiffChangeSet) {
285
            IResource[] resources = ((DiffChangeSet) element).getResources();
286
            if (resources.length > 0) {
287
                // TODO: only checks first resource
288
                return resources[0].getProject();
289
            }
290
        } else if (element instanceof SynchronizeModelElement) {
291
            SynchronizeModelElement modelElement = (SynchronizeModelElement)element;
292
            IResource resource = modelElement.getResource();
293
            if (resource != null) {
294
                return resource.getProject();
295
            } else {
296
                IDiffElement[] elements = modelElement.getChildren();
297
                if (elements.length > 0) {
298
                    // TODO: only checks first diff
299
                    if (elements[0] instanceof SynchronizeModelElement) {
300
                        return ((SynchronizeModelElement)elements[0]).getResource().getProject();
301
                    }
302
                }
303
            }
304
        } else if (element instanceof IAdaptable) {
305
        	IAdaptable adaptable = (IAdaptable) element;
306
			IResourceVariant resourceVariant = (IResourceVariant) adaptable.getAdapter(IResourceVariant.class);
307
            if (resourceVariant != null && resourceVariant instanceof RemoteResource) {
308
            	RemoteResource remoteResource = (RemoteResource) resourceVariant;
309
            	// TODO is there a better way then iterating trough all projects?
310
                String path = remoteResource.getRepositoryRelativePath();
311
                for (IProject project : ResourcesPlugin.getWorkspace().getRoot().getProjects()) {
312
                	if(project.isAccessible()) {
313
                		ICVSResource cvsResource = CVSWorkspaceRoot.getCVSFolderFor(project);
314
                		try {
315
							if(cvsResource!=null && path.startsWith(cvsResource.getRepositoryRelativePath())) {
316
								return project;
317
							}
318
						} catch (CVSException ex) {
319
							// ignore
320
						}
321
                	}
322
                }
323
                
324
                return null;
325
            }
326
        } else {
327
        	// TODO
328
        	
329
        }
330
        return null;
331
    }
332
    
333
}
(-)src/org/eclipse/mylar/internal/trac/core/TracRepositoryConnector.java (-2 / +16 lines)
Lines 81-90 Link Here
81
		if (url == null) {
81
		if (url == null) {
82
			return null;
82
			return null;
83
		}
83
		}
84
		int i = url.lastIndexOf(ITracClient.TICKET_URL);
84
		int index = url.lastIndexOf(ITracClient.TICKET_URL);
85
		return (i != -1) ? url.substring(0, i) : null;
85
		return index == -1 ? null : url.substring(0, index);
86
	}
86
	}
87
87
88
	public String getTaskIdFromTaskUrl(String url) {
89
		if (url == null) {
90
			return null;
91
		}
92
		int index = url.lastIndexOf(ITracClient.TICKET_URL);
93
		return index == -1 ? null : url.substring(index + ITracClient.TICKET_URL.length());
94
	}
95
96
	@Override
97
	public String getTaskWebUrl(String repositoryUrl, String taskId) {
98
		return repositoryUrl + ITracClient.TICKET_URL + taskId;
99
	}
100
101
	
88
	@Override
102
	@Override
89
	public List<String> getSupportedVersions() {
103
	public List<String> getSupportedVersions() {
90
		if (supportedVersions == null) {
104
		if (supportedVersions == null) {

Return to bug 165581