diff options
Diffstat (limited to 'org.eclipse.mylyn.tasks.core')
14 files changed, 394 insertions, 15 deletions
diff --git a/org.eclipse.mylyn.tasks.core/META-INF/MANIFEST.MF b/org.eclipse.mylyn.tasks.core/META-INF/MANIFEST.MF index cd04de767..d4956ab30 100644 --- a/org.eclipse.mylyn.tasks.core/META-INF/MANIFEST.MF +++ b/org.eclipse.mylyn.tasks.core/META-INF/MANIFEST.MF @@ -11,4 +11,5 @@ Require-Bundle: org.eclipse.core.runtime, org.eclipse.mylar.context.core, org.eclipse.update.core Export-Package: org.eclipse.mylar.internal.tasks.core, - org.eclipse.mylar.tasks.core + org.eclipse.mylar.tasks.core, + org.eclipse.mylar.tasks.core.web diff --git a/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/internal/tasks/core/OfflineDataStore.java b/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/internal/tasks/core/OfflineDataStore.java new file mode 100644 index 000000000..46d6cad3b --- /dev/null +++ b/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/internal/tasks/core/OfflineDataStore.java @@ -0,0 +1,59 @@ +/******************************************************************************* + * Copyright (c) 2004 - 2006 Mylar committers 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 + *******************************************************************************/ + +package org.eclipse.mylar.internal.tasks.core; + +import java.io.Serializable; +import java.util.HashMap; +import java.util.Map; + +import org.eclipse.mylar.tasks.core.RepositoryTaskData; + +/** + * This object holds RepositoryTaskData and is serialized to disk for offline + * storage. + * + * @author Rob Elves + */ +class OfflineDataStore implements Serializable { + + private static final long serialVersionUID = -3909672088254980426L; + + /** Last new repository task id */ + private int lastNewRepositoryTaskId = 0; + + /** Older version of Task Data */ + private Map<String, RepositoryTaskData> oldTaskDataMap = new HashMap<String, RepositoryTaskData>(); + + /** Newest version of the task data */ + private Map<String, RepositoryTaskData> newTaskDataMap = new HashMap<String, RepositoryTaskData>(); + + /** New unsubmitted repository task data */ + private Map<String, RepositoryTaskData> unsubmittedTaskData = new HashMap<String, RepositoryTaskData>(); + + public void setLastNewTaskId(int lastNumber) { + lastNewRepositoryTaskId = new Integer(lastNumber); + } + + public int getNextTaskId() { + lastNewRepositoryTaskId++; + return lastNewRepositoryTaskId; + } + + public Map<String, RepositoryTaskData> getOldDataMap() { + return oldTaskDataMap; + } + + public Map<String, RepositoryTaskData> getNewDataMap() { + return newTaskDataMap; + } + + public Map<String, RepositoryTaskData> getUnsubmittedTaskData() { + return unsubmittedTaskData; + } +}
\ No newline at end of file diff --git a/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/internal/tasks/core/SslProtocolSocketFactory.java b/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/internal/tasks/core/SslProtocolSocketFactory.java index b9bfb8536..6abc88ed5 100644 --- a/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/internal/tasks/core/SslProtocolSocketFactory.java +++ b/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/internal/tasks/core/SslProtocolSocketFactory.java @@ -29,6 +29,7 @@ import org.apache.commons.httpclient.auth.AuthScope; import org.apache.commons.httpclient.params.HttpConnectionParams; import org.apache.commons.httpclient.protocol.ProtocolSocketFactory; import org.eclipse.mylar.context.core.MylarStatusHandler; +import org.eclipse.mylar.tasks.core.web.WebClientUtil; /** * @author Nathan Hapke diff --git a/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/internal/tasks/core/TaskDataManager.java b/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/internal/tasks/core/TaskDataManager.java new file mode 100644 index 000000000..b90e5b541 --- /dev/null +++ b/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/internal/tasks/core/TaskDataManager.java @@ -0,0 +1,301 @@ +/******************************************************************************* + * Copyright (c) 2003 - 2006 University Of British Columbia 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: + * University Of British Columbia - initial API and implementation + *******************************************************************************/ +package org.eclipse.mylar.internal.tasks.core; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.OptionalDataException; +import java.util.Collections; +import java.util.List; +import java.util.Map; + +import org.eclipse.mylar.context.core.MylarStatusHandler; +import org.eclipse.mylar.tasks.core.AbstractAttributeFactory; +import org.eclipse.mylar.tasks.core.AbstractRepositoryConnector; +import org.eclipse.mylar.tasks.core.AbstractRepositoryTask; +import org.eclipse.mylar.tasks.core.RepositoryTaskData; +import org.eclipse.mylar.tasks.core.TaskRepositoryManager; + +/** + * Manager for persisting RepositoryTaskData offline + * + * @author Rob Elves + */ +public class TaskDataManager { + + private File file; + + private OfflineDataStore dataStore; + + /** Older version of Task Data */ + private Map<String, RepositoryTaskData> oldTaskDataMap; + + /** Newest version of the task data */ + private Map<String, RepositoryTaskData> newTaskDataMap; + + /** Unsubmitted tasks data */ + private Map<String, RepositoryTaskData> unsubmittedTaskData; + + private TaskRepositoryManager taskRepositoryManager; + + public TaskDataManager(TaskRepositoryManager taskRepositoryManager, File file, boolean read) throws IOException, ClassNotFoundException { + this.taskRepositoryManager = taskRepositoryManager; + this.file = file; + if (file.exists() && read) { + readOfflineData(); + } else { + dataStore = new OfflineDataStore(); + } + } + + private Map<String, RepositoryTaskData> getOldDataMap() { + if (oldTaskDataMap == null) { + oldTaskDataMap = Collections.synchronizedMap(dataStore.getOldDataMap()); + } + return oldTaskDataMap; + } + + private synchronized Map<String, RepositoryTaskData> getNewDataMap() { + if (newTaskDataMap == null) { + newTaskDataMap = Collections.synchronizedMap(dataStore.getNewDataMap()); + } + return newTaskDataMap; + } + + private synchronized Map<String, RepositoryTaskData> getUnsubmittedTaskData() { + if (unsubmittedTaskData == null) { + unsubmittedTaskData = Collections.synchronizedMap(dataStore.getUnsubmittedTaskData()); + } + return unsubmittedTaskData; + } + + /** + * Add a RepositoryTaskData to the offline reports file. Previously stored + * taskData is held and can be retrieved via getOldTaskData() + */ + public void put(RepositoryTaskData newEntry) { + synchronized (file) { + String handle = AbstractRepositoryTask.getHandle(newEntry.getRepositoryUrl(), newEntry.getId()); + RepositoryTaskData moveToOld = getNewDataMap().get(handle); + if (moveToOld != null) { + getOldDataMap().put(handle, moveToOld); + } + getNewDataMap().put(handle, newEntry); + } + } + + /** + * Add an unsubmitted RepositoryTaskData to the offline reports file. + */ + public void putUnsubmitted(RepositoryTaskData newEntry) { + String handle = AbstractRepositoryTask.getHandle(newEntry.getRepositoryUrl(), newEntry.getId()); + synchronized (file) { + getUnsubmittedTaskData().put(handle, newEntry); + } + } + + public Map<String, RepositoryTaskData> getUnsubmitted() { + return Collections.unmodifiableMap(getUnsubmittedTaskData()); + } + + public void removeUnsubmitted(String handle) { + synchronized (file) { + getUnsubmittedTaskData().remove(handle); + } + } + + public void clearUnsubmitted() { + synchronized (file) { + getUnsubmittedTaskData().clear(); + } + } + + /** + * @return Get the next available temporary id. This id is given to new + * unsubmitted repository tasks. Incremented each time this method + * is called. + */ + public String getNewRepositoryTaskId() { + return "" + dataStore.getNextTaskId(); + } + + /** + * Returns the most recent copy of the task data. + */ + public RepositoryTaskData getTaskData(String handle) { + RepositoryTaskData data = getNewDataMap().get(handle); + if (data == null) { + data = getOldTaskData(handle); + if (data != null) { + getNewDataMap().put(handle, data); + } + } + return data; + } + + /** + * Returns the most recent copy of the task data. + */ + public RepositoryTaskData getTaskData(String repositoryUrl, String taskId) { + String handle = AbstractRepositoryTask.getHandle(repositoryUrl, taskId); + return getTaskData(handle); + } + + /** + * Returns the old copy if exists, null otherwise. + */ + public RepositoryTaskData getOldTaskData(String handle) { + return getOldDataMap().get(handle); + } + + /** + * Returns the old copy if exists, null otherwise. + */ + public RepositoryTaskData getOldTaskData(String repositoryUrl, String taskId) { + String handle = AbstractRepositoryTask.getHandle(repositoryUrl, taskId); + return getOldTaskData(handle); + } + + /** + * Remove some bugs from the offline reports list + * + * @param indicesToRemove + * An array of the indicies of the bugs to be removed + */ + public void remove(List<RepositoryTaskData> dataToRemove) { + synchronized (file) { + for (RepositoryTaskData repositoryTaskData : dataToRemove) { + remove(repositoryTaskData); + } + } + } + + public void remove(RepositoryTaskData taskData) { + synchronized (file) { + String handle = AbstractRepositoryTask.getHandle(taskData.getRepositoryUrl(), taskData.getId()); + getNewDataMap().remove(handle); + getOldDataMap().remove(handle); + } + } + + /** + * Public for testing + */ + public void clear() { + synchronized (file) { + dataStore = new OfflineDataStore(); + oldTaskDataMap = null; + newTaskDataMap = null; + unsubmittedTaskData = null; + } + } + + /** + * Public for testing + */ + public void readOfflineData() throws IOException, ClassNotFoundException { + clear(); + synchronized (file) { + ObjectInputStream in = null; + try { + in = new ObjectInputStream(new FileInputStream(file)); + dataStore = (OfflineDataStore) in.readObject(); + for (RepositoryTaskData taskData : getNewDataMap().values()) { + updateAttributeFactory(taskData); + } + for (RepositoryTaskData taskData : getOldDataMap().values()) { + updateAttributeFactory(taskData); + } + } catch (OptionalDataException e) { + in.close(); + readOldOfflineFile(); + } catch (ClassCastException e) { + in.close(); + readOldOfflineFile(); + } finally { + in.close(); + } + } + } + + /** + * Migrate from old offline task data format (pre 1.0) + */ + private void readOldOfflineFile() throws IOException { + ObjectInputStream in = null; + try { + in = new ObjectInputStream(new FileInputStream(file)); + // read in each of the offline reports in the file + + dataStore = new OfflineDataStore(); + + // get the number of offline reports in the file + int size = in.readInt(); + dataStore.setLastNewTaskId(in.readInt()); + for (int nX = 0; nX < size; nX++) { + RepositoryTaskData taskData = null; + + taskData = (RepositoryTaskData) in.readObject(); + + if (taskData != null) { + updateAttributeFactory(taskData); + put(taskData); + } + } + } catch (Exception ex) { + dataStore = new OfflineDataStore(); + MylarStatusHandler.log(ex, "Could not migrate old offline data file, created new."); + } finally { + in.close(); + } + } + + /** save task data to offline file */ + public void save() { + synchronized (file) { + + ObjectOutputStream out = null; + try { + out = new ObjectOutputStream(new FileOutputStream(file)); + out.writeObject(dataStore); + out.close(); + } catch (IOException e) { + MylarStatusHandler.fail(e, "Could not write to offline reports file.", false); + } finally { + if (out != null) { + try { + out.close(); + } catch (IOException e) { + // ignore + } + } + } + } + } + + private void updateAttributeFactory(RepositoryTaskData taskData) { + AbstractRepositoryConnector connector = taskRepositoryManager.getRepositoryConnector( + taskData.getRepositoryKind()); +// AbstractRepositoryConnector connector = TasksUiPlugin.getRepositoryManager().getRepositoryConnector( +// taskData.getRepositoryKind()); + if (connector != null && connector.getTaskDataHandler() != null) { + AbstractAttributeFactory factory = connector.getTaskDataHandler().getAttributeFactory(); + if (factory != null) { + taskData.setAttributeFactory(factory); + } + } + } + +} diff --git a/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/tasks/core/.AbstractRepositoryTask.java b/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/tasks/core/.AbstractRepositoryTask.java index 4f5683f37..75e9a8ad8 100644 --- a/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/tasks/core/.AbstractRepositoryTask.java +++ b/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/tasks/core/.AbstractRepositoryTask.java @@ -14,7 +14,7 @@ package org.eclipse.mylar.tasks.core; import java.util.Date; import org.eclipse.core.runtime.IStatus; -import org.eclipse.mylar.internal.tasks.core.HtmlStreamTokenizer; +import org.eclipse.mylar.tasks.core.web.HtmlStreamTokenizer; /** * Virtual proxy for a repository task. diff --git a/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/tasks/core/AbstractRepositoryTask.java b/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/tasks/core/AbstractRepositoryTask.java index 4f5683f37..75e9a8ad8 100644 --- a/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/tasks/core/AbstractRepositoryTask.java +++ b/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/tasks/core/AbstractRepositoryTask.java @@ -14,7 +14,7 @@ package org.eclipse.mylar.tasks.core; import java.util.Date; import org.eclipse.core.runtime.IStatus; -import org.eclipse.mylar.internal.tasks.core.HtmlStreamTokenizer; +import org.eclipse.mylar.tasks.core.web.HtmlStreamTokenizer; /** * Virtual proxy for a repository task. diff --git a/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/tasks/core/DelegatingTaskExternalizer.java b/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/tasks/core/DelegatingTaskExternalizer.java index 7ac081339..dce16de75 100644 --- a/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/tasks/core/DelegatingTaskExternalizer.java +++ b/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/tasks/core/DelegatingTaskExternalizer.java @@ -20,6 +20,7 @@ import java.util.List; import java.util.Locale; import org.eclipse.mylar.context.core.MylarStatusHandler; +import org.eclipse.mylar.internal.tasks.core.TaskDataManager; import org.eclipse.mylar.tasks.core.AbstractRepositoryTask.RepositoryTaskSyncState; import org.w3c.dom.Document; import org.w3c.dom.Element; @@ -110,7 +111,16 @@ public class DelegatingTaskExternalizer implements ITaskListExternalizer { public static final String KEY_SYNC_STATE = "offlineSyncState"; private List<ITaskListExternalizer> delegateExternalizers = new ArrayList<ITaskListExternalizer>(); - + + /** + * Only needed by delegating externalizer, not subtypes + */ + private TaskDataManager taskDataManager; + + public void init(TaskDataManager taskDataManager) { + this.taskDataManager = taskDataManager; + } + /** * Set these on the TaskListWriter instead */ @@ -428,10 +438,15 @@ public class DelegatingTaskExternalizer implements ITaskListExternalizer { } } - // TODO pull up implementation from BugzillaTaskExternalizer and TracTaskExternalizer protected void readTaskData(AbstractRepositoryTask task) { + RepositoryTaskData data = taskDataManager.getTaskData(task.getHandleIdentifier()); +// RepositoryTaskData data = TasksUiPlugin.getDefault().getTaskDataManager().getTaskData(task.getHandleIdentifier()); + task.setTaskData(data); + if (data != null && data.hasLocalChanges()) { + task.setSyncState(RepositoryTaskSyncState.OUTGOING); + } } - + protected Date getDateFromString(String dateString) { Date date = null; if ("".equals(dateString)) diff --git a/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/tasks/core/ITaskListExternalizer.java b/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/tasks/core/ITaskListExternalizer.java index 815b15e95..180711760 100644 --- a/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/tasks/core/ITaskListExternalizer.java +++ b/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/tasks/core/ITaskListExternalizer.java @@ -48,7 +48,7 @@ public interface ITaskListExternalizer { public abstract boolean canReadCategory(Node node); - public abstract void readCategory(Node node, TaskList tlist) throws TaskExternalizationException; + public abstract void readCategory(Node node, TaskList taskList) throws TaskExternalizationException; public abstract boolean canReadTask(Node node); diff --git a/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/tasks/core/TaskList.java b/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/tasks/core/TaskList.java index bc07a0a1b..74baa3493 100644 --- a/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/tasks/core/TaskList.java +++ b/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/tasks/core/TaskList.java @@ -299,11 +299,11 @@ public class TaskList { } public Set<ITask> getRootTasks() { - return rootCategory.getChildren(); + return Collections.unmodifiableSet(rootCategory.getChildren()); } public Set<AbstractTaskContainer> getCategories() { - return categories; + return Collections.unmodifiableSet(categories); } public List<AbstractTaskContainer> getUserCategories() { @@ -317,7 +317,7 @@ public class TaskList { } public Set<AbstractRepositoryQuery> getQueries() { - return queries; + return Collections.unmodifiableSet(queries); } public Set<ITaskListElement> getRootElements() { diff --git a/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/tasks/core/TaskRepository.java b/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/tasks/core/TaskRepository.java index 82c2c5291..b1973f4c3 100644 --- a/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/tasks/core/TaskRepository.java +++ b/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/tasks/core/TaskRepository.java @@ -22,7 +22,7 @@ import java.util.TimeZone; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.Platform; import org.eclipse.mylar.context.core.MylarStatusHandler; -import org.eclipse.mylar.internal.tasks.core.WebClientUtil; +import org.eclipse.mylar.tasks.core.web.WebClientUtil; /** * Note that task repositories use Strings for storing time stamps because using diff --git a/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/internal/tasks/core/UnrecognizedReponseException.java b/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/tasks/core/UnrecognizedReponseException.java index 4c60efcc9..54c445755 100644 --- a/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/internal/tasks/core/UnrecognizedReponseException.java +++ b/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/tasks/core/UnrecognizedReponseException.java @@ -9,7 +9,7 @@ * University Of British Columbia - initial API and implementation *******************************************************************************/ -package org.eclipse.mylar.internal.tasks.core; +package org.eclipse.mylar.tasks.core; import java.io.IOException; diff --git a/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/internal/tasks/core/HtmlStreamTokenizer.java b/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/tasks/core/web/HtmlStreamTokenizer.java index 8583a1a1d..9edf98a2e 100644 --- a/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/internal/tasks/core/HtmlStreamTokenizer.java +++ b/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/tasks/core/web/HtmlStreamTokenizer.java @@ -9,7 +9,7 @@ * University Of British Columbia - initial API and implementation *******************************************************************************/ -package org.eclipse.mylar.internal.tasks.core; +package org.eclipse.mylar.tasks.core.web; import java.io.BufferedReader; import java.io.IOException; diff --git a/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/internal/tasks/core/HtmlTag.java b/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/tasks/core/web/HtmlTag.java index b81e95b2c..e997defd3 100644 --- a/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/internal/tasks/core/HtmlTag.java +++ b/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/tasks/core/web/HtmlTag.java @@ -9,7 +9,7 @@ * University Of British Columbia - initial API and implementation *******************************************************************************/ -package org.eclipse.mylar.internal.tasks.core; +package org.eclipse.mylar.tasks.core.web; import java.net.URL; import java.text.ParseException; diff --git a/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/internal/tasks/core/WebClientUtil.java b/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/tasks/core/web/WebClientUtil.java index f3522af7e..be9f6d30e 100644 --- a/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/internal/tasks/core/WebClientUtil.java +++ b/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/tasks/core/web/WebClientUtil.java @@ -9,7 +9,7 @@ * University Of British Columbia - initial API and implementation *******************************************************************************/ -package org.eclipse.mylar.internal.tasks.core; +package org.eclipse.mylar.tasks.core.web; import java.net.InetSocketAddress; import java.net.Proxy; @@ -20,6 +20,8 @@ import org.apache.commons.httpclient.HttpClient; import org.apache.commons.httpclient.UsernamePasswordCredentials; import org.apache.commons.httpclient.auth.AuthScope; import org.apache.commons.httpclient.protocol.Protocol; +import org.eclipse.mylar.internal.tasks.core.AuthenticatedProxy; +import org.eclipse.mylar.internal.tasks.core.SslProtocolSocketFactory; import org.eclipse.update.internal.core.UpdateCore; /** |