diff options
6 files changed, 279 insertions, 2 deletions
diff --git a/org.eclipse.mylyn.tasks.core/plugin.xml b/org.eclipse.mylyn.tasks.core/plugin.xml index c0d4cff78..219b5e723 100644 --- a/org.eclipse.mylyn.tasks.core/plugin.xml +++ b/org.eclipse.mylyn.tasks.core/plugin.xml @@ -13,6 +13,7 @@ <plugin> <extension-point id="templates" name="templates" schema="schema/templates.exsd"/> <extension-point id="synchronizationParticipants" name="Synchronization Participants" schema="schema/synchronizationParticipants.exsd"/> + <extension-point id="taskJobListeners" name="Task Job Listeners" schema="schema/taskJobListeners.exsd"/> <extension-point id="taskActivationListeners" name="Task Activation Listeners" schema="schema/taskActivationListeners.exsd"/> <extension-point id="activityMonitor" name="Task Activity Monitor" schema="schema/activityMonitor.exsd"/> <extension-point id="contextStore" name="Task Context Store" schema="schema/contextStore.exsd"/> diff --git a/org.eclipse.mylyn.tasks.core/schema/taskJobListeners.exsd b/org.eclipse.mylyn.tasks.core/schema/taskJobListeners.exsd new file mode 100644 index 000000000..6cb0cae06 --- /dev/null +++ b/org.eclipse.mylyn.tasks.core/schema/taskJobListeners.exsd @@ -0,0 +1,104 @@ +<?xml version='1.0' encoding='UTF-8'?> +<!-- Schema file written by PDE --> +<schema targetNamespace="org.eclipse.mylyn.tasks.core" xmlns="http://www.w3.org/2001/XMLSchema"> +<annotation> + <appInfo> + <meta.schema plugin="org.eclipse.mylyn.tasks.core" id="taskJobListeners" name="Task Job Listeners"/> + </appInfo> + <documentation> + Provides notification of task submission. + </documentation> + </annotation> + + <element name="extension"> + <annotation> + <appInfo> + <meta.element /> + </appInfo> + </annotation> + <complexType> + <sequence minOccurs="1" maxOccurs="unbounded"> + <element ref="listener"/> + </sequence> + <attribute name="point" type="string" use="required"> + <annotation> + <documentation> + + </documentation> + </annotation> + </attribute> + <attribute name="id" type="string"> + <annotation> + <documentation> + + </documentation> + </annotation> + </attribute> + <attribute name="name" type="string"> + <annotation> + <documentation> + + </documentation> + <appInfo> + <meta.attribute translatable="true"/> + </appInfo> + </annotation> + </attribute> + </complexType> + </element> + + <element name="listener"> + <complexType> + <attribute name="name" type="string"> + <annotation> + <documentation> + + </documentation> + </annotation> + </attribute> + <attribute name="connectorKind" type="string"> + <annotation> + <documentation> + If specified, the listener is only notified about submits for the specified connector. Otherwise, it is notified about all submits. + </documentation> + </annotation> + </attribute> + <attribute name="class" type="string"> + <annotation> + <documentation> + + </documentation> + <appInfo> + <meta.attribute kind="java" basedOn="org.eclipse.mylyn.tasks.core.TaskJobListener:"/> + </appInfo> + </annotation> + </attribute> + </complexType> + </element> + + <annotation> + <appInfo> + <meta.section type="since"/> + </appInfo> + <documentation> + 3.7 + </documentation> + </annotation> + + + + + <annotation> + <appInfo> + <meta.section type="copyright"/> + </appInfo> + <documentation> + Copyright (c) 2012 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 + </documentation> + </annotation> + +</schema> diff --git a/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/internal/tasks/core/TaskJobFactory.java b/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/internal/tasks/core/TaskJobFactory.java index 38b5ab0ea..d87d52b2a 100644 --- a/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/internal/tasks/core/TaskJobFactory.java +++ b/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/internal/tasks/core/TaskJobFactory.java @@ -11,6 +11,10 @@ package org.eclipse.mylyn.internal.tasks.core; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; import java.util.Set; import org.eclipse.core.runtime.CoreException; @@ -21,6 +25,7 @@ import org.eclipse.core.runtime.SubMonitor; import org.eclipse.core.runtime.jobs.IJobChangeEvent; import org.eclipse.core.runtime.jobs.Job; import org.eclipse.core.runtime.jobs.JobChangeAdapter; +import org.eclipse.mylyn.commons.core.ExtensionPointReader; import org.eclipse.mylyn.commons.core.StatusHandler; import org.eclipse.mylyn.internal.tasks.core.data.TaskDataManager; import org.eclipse.mylyn.internal.tasks.core.sync.SubmitTaskAttachmentJob; @@ -32,6 +37,7 @@ import org.eclipse.mylyn.tasks.core.AbstractRepositoryConnector; import org.eclipse.mylyn.tasks.core.IRepositoryManager; import org.eclipse.mylyn.tasks.core.IRepositoryModel; import org.eclipse.mylyn.tasks.core.ITask; +import org.eclipse.mylyn.tasks.core.TaskJobListener; import org.eclipse.mylyn.tasks.core.TaskRepository; import org.eclipse.mylyn.tasks.core.data.AbstractTaskAttachmentSource; import org.eclipse.mylyn.tasks.core.data.TaskAttribute; @@ -44,6 +50,12 @@ import org.eclipse.mylyn.tasks.core.sync.TaskJob; * @author Steffen Pingel */ public class TaskJobFactory implements ITaskJobFactory { + private static final String ALL_CONNECTORS = "org.eclipse.mylyn.tasks.core.all.connectors"; //$NON-NLS-1$ + + /** + * listeners provided by extension point + */ + private static Map<String, List<TaskJobListener>> taskJobListeners; private final TaskList taskList; @@ -53,6 +65,33 @@ public class TaskJobFactory implements ITaskJobFactory { private final IRepositoryModel tasksModel; + protected static synchronized List<TaskJobListener> getTaskJobListeners(AbstractRepositoryConnector connector) { + if (taskJobListeners == null) { + taskJobListeners = new HashMap<String, List<TaskJobListener>>(); + List<TaskJobListener> listeners = loadTaskJobListeners(""); //$NON-NLS-1$ + taskJobListeners.put(ALL_CONNECTORS, listeners); + } + if (taskJobListeners.get(connector.getConnectorKind()) == null) { + List<TaskJobListener> listeners = loadTaskJobListeners(connector.getConnectorKind()); + taskJobListeners.put(connector.getConnectorKind(), listeners); + } + List<TaskJobListener> listeners = new ArrayList<TaskJobListener>(); + listeners.addAll(taskJobListeners.get(ALL_CONNECTORS)); + listeners.addAll(taskJobListeners.get(connector.getConnectorKind())); + return listeners; + } + + protected static List<TaskJobListener> loadTaskJobListeners(String connectorKind) { + ExtensionPointReader<TaskJobListener> reader = new ExtensionPointReader<TaskJobListener>( + ITasksCoreConstants.ID_PLUGIN, + "taskJobListeners", "listener", TaskJobListener.class, "connectorKind", connectorKind); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + IStatus status = reader.read(); + if (!status.isOK()) { + StatusHandler.log(status); + } + return reader.getItems(); + } + public TaskJobFactory(TaskList taskList, TaskDataManager taskDataManager, IRepositoryManager repositoryManager, IRepositoryModel tasksModel) { this.taskList = taskList; @@ -102,7 +141,8 @@ public class TaskJobFactory implements ITaskJobFactory { public SubmitJob createSubmitTaskJob(AbstractRepositoryConnector connector, TaskRepository taskRepository, final ITask task, TaskData taskData, Set<TaskAttribute> oldAttributes) { - SubmitJob job = new SubmitTaskJob(taskDataManager, connector, taskRepository, task, taskData, oldAttributes); + SubmitJob job = new SubmitTaskJob(taskDataManager, connector, taskRepository, task, taskData, oldAttributes, + getTaskJobListeners(connector)); job.setPriority(Job.INTERACTIVE); try { taskList.run(new ITaskListRunnable() { diff --git a/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/internal/tasks/core/sync/SubmitTaskJob.java b/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/internal/tasks/core/sync/SubmitTaskJob.java index 54d708838..102fca9a1 100644 --- a/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/internal/tasks/core/sync/SubmitTaskJob.java +++ b/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/internal/tasks/core/sync/SubmitTaskJob.java @@ -11,12 +11,16 @@ package org.eclipse.mylyn.internal.tasks.core.sync; +import java.util.Collections; +import java.util.List; import java.util.Set; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.ISafeRunnable; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.OperationCanceledException; +import org.eclipse.core.runtime.SafeRunner; import org.eclipse.core.runtime.Status; import org.eclipse.mylyn.commons.core.StatusHandler; import org.eclipse.mylyn.commons.net.Policy; @@ -28,6 +32,8 @@ import org.eclipse.mylyn.tasks.core.AbstractRepositoryConnector; import org.eclipse.mylyn.tasks.core.ITask; import org.eclipse.mylyn.tasks.core.RepositoryResponse; import org.eclipse.mylyn.tasks.core.RepositoryStatus; +import org.eclipse.mylyn.tasks.core.TaskJobEvent; +import org.eclipse.mylyn.tasks.core.TaskJobListener; import org.eclipse.mylyn.tasks.core.TaskRepository; import org.eclipse.mylyn.tasks.core.data.AbstractTaskDataHandler; import org.eclipse.mylyn.tasks.core.data.TaskAttribute; @@ -49,21 +55,34 @@ public class SubmitTaskJob extends SubmitJob { private ITask task; + private final ITask originalTask; + private final Set<TaskAttribute> oldAttributes; private final TaskDataManager taskDataManager; private RepositoryResponse response; + private final List<TaskJobListener> taskJobListeners; + public SubmitTaskJob(TaskDataManager taskDataManager, AbstractRepositoryConnector connector, TaskRepository taskRepository, ITask task, TaskData taskData, Set<TaskAttribute> oldAttributes) { + this(taskDataManager, connector, taskRepository, task, taskData, oldAttributes, + Collections.<TaskJobListener> emptyList()); + } + + public SubmitTaskJob(TaskDataManager taskDataManager, AbstractRepositoryConnector connector, + TaskRepository taskRepository, ITask task, TaskData taskData, Set<TaskAttribute> oldAttributes, + List<TaskJobListener> taskJobListeners) { super("Submitting Task"); //$NON-NLS-1$ this.taskDataManager = taskDataManager; this.connector = connector; this.taskRepository = taskRepository; this.task = task; + this.originalTask = task; this.taskData = taskData; this.oldAttributes = oldAttributes; + this.taskJobListeners = taskJobListeners; setRule(new MutexSchedulingRule()); } @@ -75,7 +94,7 @@ public class SubmitTaskJob extends SubmitJob { try { monitor.beginTask(Messages.SubmitTaskJob_Submitting_task, 2 * (1 + getSubmitJobListeners().length) * 100); - + fireTaskAboutToSubmit(); // post task data AbstractTaskDataHandler taskDataHandler = connector.getTaskDataHandler(); monitor.subTask(Messages.SubmitTaskJob_Sending_data); @@ -96,6 +115,7 @@ public class SubmitTaskJob extends SubmitJob { task = createTask(monitor, updatedTaskData); taskDataManager.putSubmittedTaskData(task, updatedTaskData, monitor); fireTaskSynchronized(monitor); + fireTaskSubmissionComplete(); } catch (CoreException e) { errorStatus = e.getStatus(); } catch (OperationCanceledException e) { @@ -115,6 +135,36 @@ public class SubmitTaskJob extends SubmitJob { } } + protected void fireTaskAboutToSubmit() { + for (final TaskJobListener listener : taskJobListeners) { + SafeRunner.run(new ISafeRunnable() { + public void run() throws Exception { + listener.aboutToSubmit(new TaskJobEvent(originalTask, task)); + } + + public void handleException(Throwable e) { + StatusHandler.log(new Status(IStatus.ERROR, ITasksCoreConstants.ID_PLUGIN, + "Error thrown by TaskJobListener", e)); //$NON-NLS-1$ + } + }); + } + } + + protected void fireTaskSubmissionComplete() { + for (final TaskJobListener listener : taskJobListeners) { + SafeRunner.run(new ISafeRunnable() { + public void run() throws Exception { + listener.taskSubmitted(new TaskJobEvent(originalTask, task)); + } + + public void handleException(Throwable e) { + StatusHandler.log(new Status(IStatus.ERROR, ITasksCoreConstants.ID_PLUGIN, + "Error thrown by TaskJobListener", e)); //$NON-NLS-1$ + } + }); + } + } + private ITask createTask(IProgressMonitor monitor, TaskData updatedTaskData) throws CoreException { if (taskData.isNew()) { task = new TaskTask(connector.getConnectorKind(), taskRepository.getRepositoryUrl(), diff --git a/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/tasks/core/TaskJobEvent.java b/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/tasks/core/TaskJobEvent.java new file mode 100644 index 000000000..27c1b147d --- /dev/null +++ b/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/tasks/core/TaskJobEvent.java @@ -0,0 +1,44 @@ +/******************************************************************************* + * Copyright (c) 2012 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.tasks.core; + +/** + * @author Sam Davis + * @since 3.7 + */ +public class TaskJobEvent { + + private final ITask task; + + private final ITask originalTask; + + public TaskJobEvent(ITask originalTask, ITask task) { + this.originalTask = originalTask; + this.task = task; + } + + /** + * @return the original task that was submitted + */ + public ITask getOriginalTask() { + return originalTask; + } + + /** + * @return the task that exists after submission has completed; will be the same as originalTask unless originalTask + * was a new (previously unsubmitted) task and this is a submission complete event + */ + public ITask getTask() { + return task; + } + +} diff --git a/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/tasks/core/TaskJobListener.java b/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/tasks/core/TaskJobListener.java new file mode 100644 index 000000000..2edcaac35 --- /dev/null +++ b/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/tasks/core/TaskJobListener.java @@ -0,0 +1,38 @@ +/******************************************************************************* + * Copyright (c) 2012 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.tasks.core; + +import org.eclipse.mylyn.tasks.core.sync.SubmitJob; +import org.eclipse.mylyn.tasks.core.sync.SubmitJobListener; + +/** + * Clients can contribute an implementation of this class to be notified of all task submissions for a particular + * connector, or all connectors. Implementations can be contributed using the taskJobListeners extension point. See also + * {@link SubmitJobListener} if you only need to be notified about specific {@link SubmitJob}s. + * + * @author Sam Davis + * @since 3.7 + */ +public abstract class TaskJobListener { + + /** + * Called when a task is about to be submitted. Note that the submission may fail after this call due to network + * error, invalid credentials, etc. + */ + public abstract void aboutToSubmit(TaskJobEvent event); + + /** + * Called after a submission has completed successfully. + */ + public abstract void taskSubmitted(TaskJobEvent event); + +}
\ No newline at end of file |