| /******************************************************************************* |
| * Copyright (c) 2004, 2007 Mylyn project 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.mylyn.internal.tasks.ui; |
| |
| import java.io.File; |
| import java.lang.reflect.InvocationTargetException; |
| import java.util.ArrayList; |
| import java.util.Calendar; |
| import java.util.Collection; |
| import java.util.Comparator; |
| import java.util.HashMap; |
| import java.util.HashSet; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.Set; |
| import java.util.TreeSet; |
| |
| import org.eclipse.core.net.proxy.IProxyChangeEvent; |
| import org.eclipse.core.net.proxy.IProxyChangeListener; |
| import org.eclipse.core.net.proxy.IProxyService; |
| import org.eclipse.core.resources.IResource; |
| import org.eclipse.core.resources.ISaveContext; |
| import org.eclipse.core.resources.ISaveParticipant; |
| import org.eclipse.core.resources.ResourcesPlugin; |
| import org.eclipse.core.runtime.Assert; |
| 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.NullProgressMonitor; |
| import org.eclipse.core.runtime.OperationCanceledException; |
| import org.eclipse.core.runtime.Platform; |
| import org.eclipse.core.runtime.Status; |
| import org.eclipse.core.runtime.SubProgressMonitor; |
| import org.eclipse.core.runtime.jobs.Job; |
| import org.eclipse.jface.dialogs.MessageDialog; |
| import org.eclipse.jface.operation.IRunnableWithProgress; |
| import org.eclipse.jface.preference.IPreferenceStore; |
| import org.eclipse.jface.resource.ImageDescriptor; |
| import org.eclipse.jface.text.hyperlink.IHyperlinkDetector; |
| import org.eclipse.jface.util.SafeRunnable; |
| import org.eclipse.mylyn.commons.core.CoreUtil; |
| import org.eclipse.mylyn.commons.core.StatusHandler; |
| import org.eclipse.mylyn.commons.net.WebClientLog; |
| import org.eclipse.mylyn.commons.net.WebUtil; |
| import org.eclipse.mylyn.context.core.ContextCore; |
| import org.eclipse.mylyn.internal.context.core.ContextPreferenceContstants; |
| import org.eclipse.mylyn.internal.provisional.commons.ui.AbstractNotification; |
| import org.eclipse.mylyn.internal.provisional.commons.ui.CommonColors; |
| import org.eclipse.mylyn.internal.tasks.core.AbstractSearchHandler; |
| import org.eclipse.mylyn.internal.tasks.core.AbstractTask; |
| import org.eclipse.mylyn.internal.tasks.core.ITasksCoreConstants; |
| import org.eclipse.mylyn.internal.tasks.core.LocalRepositoryConnector; |
| import org.eclipse.mylyn.internal.tasks.core.RepositoryExternalizationParticipant; |
| import org.eclipse.mylyn.internal.tasks.core.RepositoryQuery; |
| import org.eclipse.mylyn.internal.tasks.core.RepositoryTemplateManager; |
| import org.eclipse.mylyn.internal.tasks.core.TaskActivityManager; |
| import org.eclipse.mylyn.internal.tasks.core.TaskActivityUtil; |
| import org.eclipse.mylyn.internal.tasks.core.TaskDataStorageManager; |
| import org.eclipse.mylyn.internal.tasks.core.TaskList; |
| import org.eclipse.mylyn.internal.tasks.core.TaskRepositoryManager; |
| import org.eclipse.mylyn.internal.tasks.core.TasksModel; |
| import org.eclipse.mylyn.internal.tasks.core.data.TaskDataManager; |
| import org.eclipse.mylyn.internal.tasks.core.data.TaskDataStore; |
| import org.eclipse.mylyn.internal.tasks.core.deprecated.AbstractLegacyRepositoryConnector; |
| import org.eclipse.mylyn.internal.tasks.core.externalization.ExternalizationManager; |
| import org.eclipse.mylyn.internal.tasks.core.externalization.IExternalizationParticipant; |
| import org.eclipse.mylyn.internal.tasks.core.externalization.TaskListExternalizationParticipant; |
| import org.eclipse.mylyn.internal.tasks.core.externalization.TaskListExternalizer; |
| import org.eclipse.mylyn.internal.tasks.ui.notifications.TaskListNotification; |
| import org.eclipse.mylyn.internal.tasks.ui.notifications.TaskListNotificationQueryIncoming; |
| import org.eclipse.mylyn.internal.tasks.ui.notifications.TaskListNotificationReminder; |
| import org.eclipse.mylyn.internal.tasks.ui.util.TaskListElementImporter; |
| import org.eclipse.mylyn.internal.tasks.ui.util.TasksUiExtensionReader; |
| import org.eclipse.mylyn.internal.tasks.ui.views.TaskRepositoriesView; |
| import org.eclipse.mylyn.tasks.core.AbstractDuplicateDetector; |
| import org.eclipse.mylyn.tasks.core.AbstractRepositoryConnector; |
| import org.eclipse.mylyn.tasks.core.IRepositoryQuery; |
| import org.eclipse.mylyn.tasks.core.ITask; |
| import org.eclipse.mylyn.tasks.core.ITaskActivityListener; |
| import org.eclipse.mylyn.tasks.core.ITaskElement; |
| import org.eclipse.mylyn.tasks.core.RepositoryTemplate; |
| import org.eclipse.mylyn.tasks.core.TaskActivityAdapter; |
| import org.eclipse.mylyn.tasks.core.TaskRepository; |
| import org.eclipse.mylyn.tasks.core.ITask.PriorityLevel; |
| import org.eclipse.mylyn.tasks.core.ITask.SynchronizationState; |
| import org.eclipse.mylyn.tasks.ui.AbstractRepositoryConnectorUi; |
| import org.eclipse.mylyn.tasks.ui.AbstractTaskRepositoryLinkProvider; |
| import org.eclipse.mylyn.tasks.ui.TasksUi; |
| import org.eclipse.mylyn.tasks.ui.editors.AbstractTaskEditorFactory; |
| import org.eclipse.mylyn.tasks.ui.editors.AbstractTaskEditorPageFactory; |
| import org.eclipse.swt.graphics.Image; |
| import org.eclipse.ui.IStartup; |
| import org.eclipse.ui.PlatformUI; |
| import org.eclipse.ui.plugin.AbstractUIPlugin; |
| import org.eclipse.ui.progress.IProgressService; |
| import org.eclipse.ui.progress.UIJob; |
| import org.osgi.framework.BundleContext; |
| import org.osgi.framework.ServiceReference; |
| |
| /** |
| * Main entry point for the Tasks UI. |
| * |
| * @author Mik Kersten |
| * @since 3.0 |
| */ |
| public class TasksUiPlugin extends AbstractUIPlugin { |
| |
| private static final int DELAY_QUERY_REFRESH_ON_STARTUP = 20 * 1000; |
| |
| private static final int LINK_PROVIDER_TIMEOUT_SECONDS = 5; |
| |
| public static final String LABEL_VIEW_REPOSITORIES = "Task Repositories"; |
| |
| public static final String ID_PLUGIN = "org.eclipse.mylyn.tasks.ui"; |
| |
| private static final String FOLDER_OFFLINE = "offline"; |
| |
| private static final String DIRECTORY_METADATA = ".metadata"; |
| |
| private static final String NAME_DATA_DIR = ".mylyn"; |
| |
| private static final char DEFAULT_PATH_SEPARATOR = '/'; |
| |
| private static final int NOTIFICATION_DELAY = 5000; |
| |
| private static TasksUiPlugin INSTANCE; |
| |
| private static ExternalizationManager externalizationManager; |
| |
| private static TaskListManager taskListManager; |
| |
| private static TaskActivityManager taskActivityManager; |
| |
| private static TaskRepositoryManager repositoryManager; |
| |
| private static TaskListSynchronizationScheduler synchronizationScheduler; |
| |
| private static TaskDataManager taskDataManager; |
| |
| private static Map<String, AbstractRepositoryConnectorUi> repositoryConnectorUiMap = new HashMap<String, AbstractRepositoryConnectorUi>(); |
| |
| //private TaskListSaveManager taskListSaveManager; |
| |
| private TaskListNotificationManager taskListNotificationManager; |
| |
| private TaskListBackupManager taskListBackupManager; |
| |
| private TaskDataStorageManager taskDataStorageManager; |
| |
| private RepositoryTemplateManager repositoryTemplateManager; |
| |
| private final Set<AbstractTaskEditorFactory> taskEditorFactories = new HashSet<AbstractTaskEditorFactory>(); |
| |
| private final Set<AbstractTaskEditorPageFactory> taskEditorPageFactories = new HashSet<AbstractTaskEditorPageFactory>(); |
| |
| private final Set<IHyperlinkDetector> hyperlinkDetectors = new HashSet<IHyperlinkDetector>(); |
| |
| private final TreeSet<AbstractTaskRepositoryLinkProvider> repositoryLinkProviders = new TreeSet<AbstractTaskRepositoryLinkProvider>( |
| new OrderComparator()); |
| |
| private TaskListExternalizer taskListExternalizer; |
| |
| private ITaskHighlighter highlighter; |
| |
| private final Map<String, Image> brandingIcons = new HashMap<String, Image>(); |
| |
| private final Map<String, ImageDescriptor> overlayIcons = new HashMap<String, ImageDescriptor>(); |
| |
| private final Set<AbstractDuplicateDetector> duplicateDetectors = new HashSet<AbstractDuplicateDetector>(); |
| |
| private ISaveParticipant saveParticipant; |
| |
| private TaskEditorBloatMonitor taskEditorBloatManager; |
| |
| private TaskJobFactory tasksJobFactory; |
| |
| private final List<AbstractSearchHandler> searchHandlers = new ArrayList<AbstractSearchHandler>(); |
| |
| private static final boolean DEBUG_HTTPCLIENT = "true".equalsIgnoreCase(Platform.getDebugOption("org.eclipse.mylyn.tasks.ui/debug/httpclient")); |
| |
| // XXX reconsider if this is necessary |
| public static class TasksUiStartup implements IStartup { |
| |
| public void earlyStartup() { |
| // ignore |
| } |
| } |
| |
| private static final class OrderComparator implements Comparator<AbstractTaskRepositoryLinkProvider> { |
| public int compare(AbstractTaskRepositoryLinkProvider p1, AbstractTaskRepositoryLinkProvider p2) { |
| return p1.getOrder() - p2.getOrder(); |
| } |
| } |
| |
| public enum TaskListSaveMode { |
| ONE_HOUR, THREE_HOURS, DAY; |
| @Override |
| public String toString() { |
| switch (this) { |
| case ONE_HOUR: |
| return "1 hour"; |
| case THREE_HOURS: |
| return "3 hours"; |
| case DAY: |
| return "1 day"; |
| default: |
| return "3 hours"; |
| } |
| } |
| |
| public static TaskListSaveMode fromString(String string) { |
| if (string == null) { |
| return null; |
| } |
| if (string.equals("1 hour")) { |
| return ONE_HOUR; |
| } |
| if (string.equals("3 hours")) { |
| return THREE_HOURS; |
| } |
| if (string.equals("1 day")) { |
| return DAY; |
| } |
| return null; |
| } |
| |
| public static long fromStringToLong(String string) { |
| long hour = 3600 * 1000; |
| switch (fromString(string)) { |
| case ONE_HOUR: |
| return hour; |
| case THREE_HOURS: |
| return hour * 3; |
| case DAY: |
| return hour * 24; |
| default: |
| return hour * 3; |
| } |
| } |
| } |
| |
| public enum ReportOpenMode { |
| EDITOR, INTERNAL_BROWSER, EXTERNAL_BROWSER; |
| } |
| |
| private static ITaskActivityListener CONTEXT_TASK_ACTIVITY_LISTENER = new TaskActivityAdapter() { |
| |
| @Override |
| public void taskActivated(final ITask task) { |
| ContextCore.getContextManager().activateContext(task.getHandleIdentifier()); |
| } |
| |
| @Override |
| public void taskDeactivated(final ITask task) { |
| ContextCore.getContextManager().deactivateContext(task.getHandleIdentifier()); |
| } |
| |
| }; |
| |
| private static ITaskListNotificationProvider REMINDER_NOTIFICATION_PROVIDER = new ITaskListNotificationProvider() { |
| |
| public Set<AbstractNotification> getNotifications() { |
| Collection<AbstractTask> allTasks = TasksUiPlugin.getTaskList().getAllTasks(); |
| Set<AbstractNotification> reminders = new HashSet<AbstractNotification>(); |
| for (AbstractTask task : allTasks) { |
| if (task.isPastReminder() && !task.isReminded()) { |
| reminders.add(new TaskListNotificationReminder(task)); |
| task.setReminded(true); |
| } |
| } |
| return reminders; |
| } |
| }; |
| |
| private static ITaskListNotificationProvider INCOMING_NOTIFICATION_PROVIDER = new ITaskListNotificationProvider() { |
| |
| @SuppressWarnings( { "deprecation", "restriction" }) |
| public Set<AbstractNotification> getNotifications() { |
| Set<AbstractNotification> notifications = new HashSet<AbstractNotification>(); |
| // Incoming Changes |
| for (TaskRepository repository : getRepositoryManager().getAllRepositories()) { |
| AbstractRepositoryConnector connector = getRepositoryManager().getRepositoryConnector( |
| repository.getConnectorKind()); |
| if (connector instanceof AbstractLegacyRepositoryConnector) { |
| AbstractRepositoryConnectorUi connectorUi = getConnectorUi(repository.getConnectorKind()); |
| if (connectorUi != null && !connectorUi.isCustomNotificationHandling()) { |
| for (ITask itask : TasksUiPlugin.getTaskList().getTasks(repository.getRepositoryUrl())) { |
| if (itask instanceof AbstractTask) { |
| AbstractTask task = (AbstractTask) itask; |
| if ((task.getLastReadTimeStamp() == null || task.getSynchronizationState() == SynchronizationState.INCOMING) |
| && task.isNotified() == false) { |
| TaskListNotification notification = LegacyChangeManager.getIncommingNotification( |
| connector, task); |
| notifications.add(notification); |
| task.setNotified(true); |
| } |
| } |
| } |
| } |
| } |
| } |
| // New query hits |
| for (RepositoryQuery query : TasksUiPlugin.getTaskList().getQueries()) { |
| TaskRepository repository = getRepositoryManager().getRepository(query.getRepositoryUrl()); |
| if (repository != null) { |
| AbstractRepositoryConnector connector = getRepositoryManager().getRepositoryConnector( |
| repository.getConnectorKind()); |
| if (connector instanceof AbstractLegacyRepositoryConnector) { |
| AbstractRepositoryConnectorUi connectorUi = getConnectorUi(query.getConnectorKind()); |
| if (!connectorUi.isCustomNotificationHandling()) { |
| for (ITask hit : query.getChildren()) { |
| if (((AbstractTask) hit).isNotified() == false) { |
| notifications.add(new TaskListNotificationQueryIncoming(hit)); |
| ((AbstractTask) hit).setNotified(true); |
| } |
| } |
| } |
| } |
| } |
| } |
| return notifications; |
| } |
| }; |
| |
| // private final IPropertyChangeListener PREFERENCE_LISTENER = new IPropertyChangeListener() { |
| // |
| // public void propertyChange(PropertyChangeEvent event) { |
| // // TODO: do we ever get here? |
| //// if (event.getProperty().equals(ContextPreferenceContstants.PREF_DATA_DIR)) { |
| //// if (event.getOldValue() instanceof String) { |
| //// reloadDataDirectory(); |
| //// } |
| //// } |
| // } |
| // }; |
| |
| private final org.eclipse.jface.util.IPropertyChangeListener PROPERTY_LISTENER = new org.eclipse.jface.util.IPropertyChangeListener() { |
| |
| public void propertyChange(org.eclipse.jface.util.PropertyChangeEvent event) { |
| // if (event.getProperty().equals(ContextPreferenceContstants.PREF_DATA_DIR)) { |
| // if (event.getOldValue() instanceof String) { |
| // reloadDataDirectory(); |
| // } |
| // } |
| |
| if (event.getProperty().equals(ITasksUiPreferenceConstants.PLANNING_ENDHOUR) |
| || event.getProperty().equals(ITasksUiPreferenceConstants.WEEK_START_DAY)) { |
| updateTaskActivityManager(); |
| } |
| |
| if (event.getProperty().equals(ITasksUiPreferenceConstants.REPOSITORY_SYNCH_SCHEDULE_ENABLED) |
| || event.getProperty().equals(ITasksUiPreferenceConstants.REPOSITORY_SYNCH_SCHEDULE_MILISECONDS)) { |
| updateSynchronizationScheduler(false); |
| } |
| } |
| }; |
| |
| private TaskActivityMonitor taskActivityMonitor; |
| |
| private ServiceReference proxyServiceReference; |
| |
| private IProxyChangeListener proxyChangeListener; |
| |
| private TaskListExternalizationParticipant taskListSaveParticipant; |
| |
| private static TaskList taskList; |
| |
| private static TasksModel tasksModel; |
| |
| private class TasksUiInitializationJob extends UIJob { |
| |
| public TasksUiInitializationJob() { |
| super("Initializing Task List"); |
| setSystem(true); |
| } |
| |
| @Override |
| public IStatus runInUIThread(IProgressMonitor monitor) { |
| // NOTE: failure in one part of the initialization should |
| // not prevent others |
| monitor.beginTask("Initializing Task List", 5); |
| try { |
| // Needs to run after workbench is loaded because it |
| // relies on images. |
| TasksUiExtensionReader.initWorkbenchUiExtensions(); |
| |
| if (externalizationManager.getLoadStatus() != null) { |
| // XXX: recovery from task list load failure (Rendered in task list) |
| } |
| |
| // Needs to happen asynchronously to avoid bug 159706 |
| for (AbstractTask task : taskListManager.getTaskList().getAllTasks()) { |
| if (task.isActive()) { |
| taskListManager.activateTask(task); |
| break; |
| } |
| } |
| //taskActivityMonitor.reloadActivityTime(); |
| } catch (Throwable t) { |
| StatusHandler.log(new Status(IStatus.ERROR, TasksUiPlugin.ID_PLUGIN, |
| "Could not initialize task activity", t)); |
| } |
| monitor.worked(1); |
| |
| try { |
| taskListNotificationManager = new TaskListNotificationManager(); |
| taskListNotificationManager.addNotificationProvider(REMINDER_NOTIFICATION_PROVIDER); |
| taskListNotificationManager.addNotificationProvider(INCOMING_NOTIFICATION_PROVIDER); |
| taskListNotificationManager.startNotification(NOTIFICATION_DELAY); |
| getPreferenceStore().addPropertyChangeListener(taskListNotificationManager); |
| } catch (Throwable t) { |
| StatusHandler.log(new Status(IStatus.ERROR, TasksUiPlugin.ID_PLUGIN, |
| "Could not initialize notifications", t)); |
| } |
| monitor.worked(1); |
| |
| try { |
| taskListBackupManager = new TaskListBackupManager(getBackupFolderPath()); |
| getPreferenceStore().addPropertyChangeListener(taskListBackupManager); |
| |
| synchronizationScheduler = new TaskListSynchronizationScheduler(tasksJobFactory); |
| updateSynchronizationScheduler(true); |
| } catch (Throwable t) { |
| StatusHandler.log(new Status(IStatus.ERROR, TasksUiPlugin.ID_PLUGIN, |
| "Could not initialize task list backup and synchronization", t)); |
| } |
| monitor.worked(1); |
| |
| try { |
| |
| getPreferenceStore().addPropertyChangeListener(PROPERTY_LISTENER); |
| |
| // TODO: get rid of this, hack to make decorators show |
| // up on startup |
| TaskRepositoriesView repositoriesView = TaskRepositoriesView.getFromActivePerspective(); |
| if (repositoriesView != null) { |
| repositoriesView.getViewer().refresh(); |
| } |
| |
| taskEditorBloatManager = new TaskEditorBloatMonitor(); |
| taskEditorBloatManager.install(PlatformUI.getWorkbench()); |
| } catch (Throwable t) { |
| StatusHandler.log(new Status(IStatus.ERROR, TasksUiPlugin.ID_PLUGIN, |
| "Could not finish Tasks UI initialization", t)); |
| } finally { |
| monitor.done(); |
| } |
| return new Status(IStatus.OK, TasksUiPlugin.ID_PLUGIN, IStatus.OK, "", null); |
| } |
| } |
| |
| public TasksUiPlugin() { |
| super(); |
| INSTANCE = this; |
| } |
| |
| private void updateSynchronizationScheduler(boolean initial) { |
| boolean enabled = TasksUiPlugin.getDefault().getPreferenceStore().getBoolean( |
| ITasksUiPreferenceConstants.REPOSITORY_SYNCH_SCHEDULE_ENABLED); |
| if (enabled) { |
| long interval = TasksUiPlugin.getDefault().getPreferenceStore().getLong( |
| ITasksUiPreferenceConstants.REPOSITORY_SYNCH_SCHEDULE_MILISECONDS); |
| if (initial) { |
| synchronizationScheduler.setInterval(DELAY_QUERY_REFRESH_ON_STARTUP, interval); |
| } else { |
| synchronizationScheduler.setInterval(interval); |
| } |
| } else { |
| synchronizationScheduler.setInterval(0); |
| } |
| } |
| |
| @SuppressWarnings("deprecation") |
| @Override |
| public void start(BundleContext context) throws Exception { |
| super.start(context); |
| // NOTE: startup order is very sensitive |
| try { |
| // initialize framwork and settings |
| StatusHandler.setDefaultStatusHandler(new RepositoryAwareStatusHandler()); |
| WebUtil.init(); |
| WebClientLog.setLoggingEnabled(DEBUG_HTTPCLIENT); |
| initializeDefaultPreferences(getPreferenceStore()); |
| |
| File dataDir = new File(getDataDirectory()); |
| dataDir.mkdirs(); |
| |
| // create data model |
| externalizationManager = new ExternalizationManager(getDataDirectory()); |
| |
| repositoryManager = new TaskRepositoryManager(); |
| IExternalizationParticipant repositoryParticipant = new RepositoryExternalizationParticipant( |
| externalizationManager, repositoryManager); |
| externalizationManager.addParticipant(repositoryParticipant); |
| |
| taskList = new TaskList(); |
| tasksModel = new TasksModel(taskList, repositoryManager); |
| taskListExternalizer = new TaskListExternalizer(tasksModel); |
| TaskListElementImporter taskListImporter = new TaskListElementImporter(repositoryManager, tasksModel); |
| |
| taskListSaveParticipant = new TaskListExternalizationParticipant(taskList, taskListExternalizer, |
| externalizationManager, repositoryManager); |
| //externalizationManager.load(taskListSaveParticipant); |
| externalizationManager.addParticipant(taskListSaveParticipant); |
| taskList.addChangeListener(taskListSaveParticipant); |
| |
| taskActivityManager = new TaskActivityManager(repositoryManager, taskList); |
| |
| taskListManager = new TaskListManager(taskList, taskListSaveParticipant, taskListImporter); |
| |
| // initialize |
| updateTaskActivityManager(); |
| |
| proxyServiceReference = context.getServiceReference(IProxyService.class.getName()); |
| if (proxyServiceReference != null) { |
| IProxyService proxyService = (IProxyService) context.getService(proxyServiceReference); |
| if (proxyService != null) { |
| proxyChangeListener = new IProxyChangeListener() { |
| public void proxyInfoChanged(IProxyChangeEvent event) { |
| List<TaskRepository> repos = repositoryManager.getAllRepositories(); |
| for (TaskRepository repo : repos) { |
| if (repo.isDefaultProxyEnabled()) { |
| repositoryManager.notifyRepositorySettingsChanged(repo); |
| } |
| } |
| } |
| }; |
| proxyService.addProxyChangeListener(proxyChangeListener); |
| } |
| } |
| |
| repositoryTemplateManager = new RepositoryTemplateManager(); |
| |
| // NOTE: initializing extensions in start(..) has caused race |
| // conditions previously |
| TasksUiExtensionReader.initStartupExtensions(taskListExternalizer, taskListImporter); |
| |
| // instantiates taskDataManager |
| File root = new File(this.getDataDirectory() + '/' + FOLDER_OFFLINE); |
| OfflineFileStorage storage = new OfflineFileStorage(root); |
| OfflineCachingStorage cachedStorage = new OfflineCachingStorage(storage); |
| taskDataStorageManager = new TaskDataStorageManager(repositoryManager, cachedStorage); |
| taskDataStorageManager.start(); |
| |
| TaskDataStore taskDataStore = new TaskDataStore(repositoryManager); |
| |
| taskDataManager = new TaskDataManager(taskDataStorageManager, taskDataStore, repositoryManager, |
| taskListManager.getTaskList()); |
| taskDataManager.setDataPath(getDataDirectory()); |
| |
| for (AbstractRepositoryConnector connector : repositoryManager.getRepositoryConnectors()) { |
| if (connector instanceof AbstractLegacyRepositoryConnector) { |
| ((AbstractLegacyRepositoryConnector) connector).init(taskDataManager); |
| } |
| } |
| |
| tasksJobFactory = new TaskJobFactory(taskListManager.getTaskList(), taskDataManager, repositoryManager, |
| tasksModel); |
| |
| taskActivityManager.addActivityListener(CONTEXT_TASK_ACTIVITY_LISTENER); |
| |
| taskActivityMonitor = new TaskActivityMonitor(taskActivityManager, ContextCore.getContextManager()); |
| taskActivityMonitor.start(); |
| |
| saveParticipant = new ISaveParticipant() { |
| |
| public void doneSaving(ISaveContext context) { |
| } |
| |
| public void prepareToSave(ISaveContext context) throws CoreException { |
| } |
| |
| public void rollback(ISaveContext context) { |
| } |
| |
| public void saving(ISaveContext context) throws CoreException { |
| if (context.getKind() == ISaveContext.FULL_SAVE) { |
| externalizationManager.stop(); |
| taskDataStorageManager.stop(); |
| } |
| } |
| }; |
| ResourcesPlugin.getWorkspace().addSaveParticipant(this, saveParticipant); |
| |
| ActivityExternalizationParticipant ACTIVITY_EXTERNALIZTAION_PARTICIPANT = new ActivityExternalizationParticipant(); |
| externalizationManager.addParticipant(ACTIVITY_EXTERNALIZTAION_PARTICIPANT); |
| taskActivityManager.addActivityListener(ACTIVITY_EXTERNALIZTAION_PARTICIPANT); |
| loadDataSources(); |
| new TasksUiInitializationJob().schedule(); |
| } catch (Exception e) { |
| StatusHandler.log(new Status(IStatus.ERROR, TasksUiPlugin.ID_PLUGIN, "Task list initialization failed", e)); |
| } |
| } |
| |
| private void updateTaskActivityManager() { |
| int endHour = getPreferenceStore().getInt(ITasksUiPreferenceConstants.PLANNING_ENDHOUR); |
| // if (taskActivityManager.getEndHour() != endHour) { |
| // taskActivityManager.setEndHour(endHour); |
| TaskActivityUtil.setEndHour(endHour); |
| // } |
| |
| int newWeekStartDay = getPreferenceStore().getInt(ITasksUiPreferenceConstants.WEEK_START_DAY); |
| int oldWeekStartDay = taskActivityManager.getWeekStartDay(); |
| if (oldWeekStartDay != newWeekStartDay) { |
| taskActivityManager.setWeekStartDay(newWeekStartDay); |
| // taskActivityManager.setStartTime(new Date()); |
| } |
| |
| // event.getProperty().equals(TaskListPreferenceConstants.PLANNING_STARTDAY) |
| // scheduledStartHour = |
| // TasksUiPlugin.getDefault().getPreferenceStore().getInt( |
| // TaskListPreferenceConstants.PLANNING_STARTHOUR); |
| } |
| |
| private void loadTemplateRepositories() { |
| // Add standard local task repository |
| TaskRepository localRepository = getLocalTaskRepository(); |
| localRepository.setRepositoryLabel(LocalRepositoryConnector.REPOSITORY_LABEL); |
| |
| // Add the automatically created templates |
| for (AbstractRepositoryConnector connector : repositoryManager.getRepositoryConnectors()) { |
| for (RepositoryTemplate template : repositoryTemplateManager.getTemplates(connector.getConnectorKind())) { |
| |
| if (template.addAutomatically && !TaskRepositoryUtil.isAddAutomaticallyDisabled(template.repositoryUrl)) { |
| try { |
| TaskRepository taskRepository = repositoryManager.getRepository(connector.getConnectorKind(), |
| template.repositoryUrl); |
| if (taskRepository == null) { |
| taskRepository = new TaskRepository(connector.getConnectorKind(), template.repositoryUrl); |
| taskRepository.setVersion(template.version); |
| taskRepository.setRepositoryLabel(template.label); |
| taskRepository.setCharacterEncoding(template.characterEncoding); |
| taskRepository.setAnonymous(template.anonymous); |
| repositoryManager.addRepository(taskRepository); |
| } |
| } catch (Throwable t) { |
| StatusHandler.log(new Status(IStatus.ERROR, TasksUiPlugin.ID_PLUGIN, |
| "Could not load repository template", t)); |
| } |
| } |
| } |
| } |
| } |
| |
| /** |
| * Returns the local task repository. If the repository does not exist it is created and added to the task |
| * repository manager. |
| * |
| * @return the local task repository; never <code>null</code> |
| * @since 3.0 |
| */ |
| public TaskRepository getLocalTaskRepository() { |
| TaskRepository localRepository = repositoryManager.getRepository(LocalRepositoryConnector.CONNECTOR_KIND, |
| LocalRepositoryConnector.REPOSITORY_URL); |
| if (localRepository == null) { |
| localRepository = new TaskRepository(LocalRepositoryConnector.CONNECTOR_KIND, |
| LocalRepositoryConnector.REPOSITORY_URL); |
| localRepository.setVersion(LocalRepositoryConnector.REPOSITORY_VERSION); |
| localRepository.setRepositoryLabel(LocalRepositoryConnector.REPOSITORY_LABEL); |
| localRepository.setAnonymous(true); |
| repositoryManager.addRepository(localRepository); |
| } |
| return localRepository; |
| } |
| |
| @Override |
| public void stop(BundleContext context) throws Exception { |
| try { |
| if (taskActivityMonitor != null) { |
| taskActivityMonitor.stop(); |
| } |
| |
| if (ResourcesPlugin.getWorkspace() != null) { |
| ResourcesPlugin.getWorkspace().removeSaveParticipant(this); |
| } |
| |
| if (proxyServiceReference != null) { |
| IProxyService proxyService = (IProxyService) context.getService(proxyServiceReference); |
| if (proxyService != null) { |
| proxyService.removeProxyChangeListener(proxyChangeListener); |
| } |
| context.ungetService(proxyServiceReference); |
| } |
| |
| if (PlatformUI.isWorkbenchRunning()) { |
| getPreferenceStore().removePropertyChangeListener(taskListNotificationManager); |
| getPreferenceStore().removePropertyChangeListener(taskListBackupManager); |
| getPreferenceStore().removePropertyChangeListener(PROPERTY_LISTENER); |
| //taskListManager.getTaskList().removeChangeListener(taskListSaveManager); |
| CommonColors.dispose(); |
| // if (ContextCorePlugin.getDefault() != null) { |
| // ContextCorePlugin.getDefault().getPluginPreferences().removePropertyChangeListener( |
| // PREFERENCE_LISTENER); |
| // } |
| taskEditorBloatManager.dispose(PlatformUI.getWorkbench()); |
| INSTANCE = null; |
| } |
| } catch (Exception e) { |
| StatusHandler.log(new Status(IStatus.ERROR, TasksUiPlugin.ID_PLUGIN, |
| "Task list stop terminated abnormally", e)); |
| } finally { |
| super.stop(context); |
| } |
| } |
| |
| public String getDefaultDataDirectory() { |
| return ResourcesPlugin.getWorkspace().getRoot().getLocation().toString() + '/' + DIRECTORY_METADATA + '/' |
| + NAME_DATA_DIR; |
| } |
| |
| public String getDataDirectory() { |
| return getPreferenceStore().getString(ContextPreferenceContstants.PREF_DATA_DIR); |
| } |
| |
| /** |
| * Save first, then load from <code>newPath</code>. Sets the new data directory, which upon setting results in |
| * reload of task list information from the <code>newPath</code> supplied. |
| * |
| * @throws CoreException |
| */ |
| public void setDataDirectory(final String newPath, IProgressMonitor monitor) throws CoreException { |
| |
| externalizationManager.saveNow(monitor); |
| // TODO: backup now? |
| //TasksUiPlugin.getBackupManager().backupNow(true); |
| loadDataDirectory(newPath); |
| getPreferenceStore().setValue(ContextPreferenceContstants.PREF_DATA_DIR, newPath); |
| ContextCore.getContextStore().contextStoreMoved(); |
| |
| } |
| |
| public void reloadDataDirectory() throws CoreException { |
| // no save just load what is there |
| loadDataDirectory(getDataDirectory()); |
| } |
| |
| /** |
| * Load's data sources from <code>newPath</code> and executes with progress |
| */ |
| private synchronized void loadDataDirectory(final String newPath) throws CoreException { |
| |
| IRunnableWithProgress setDirectoryRunnable = new IRunnableWithProgress() { |
| |
| public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException { |
| |
| try { |
| monitor.beginTask("Load Data Directory", IProgressMonitor.UNKNOWN); |
| Job.getJobManager().beginRule(ITasksCoreConstants.ROOT_SCHEDULING_RULE, |
| new SubProgressMonitor(monitor, 1)); |
| if (monitor.isCanceled()) { |
| throw new InterruptedException(); |
| } |
| TasksUi.getTaskActivityManager().deactivateActiveTask(); |
| externalizationManager.setRootFolderPath(newPath); |
| |
| loadDataSources(); |
| } finally { |
| Job.getJobManager().endRule(ITasksCoreConstants.ROOT_SCHEDULING_RULE); |
| monitor.done(); |
| } |
| } |
| |
| }; |
| |
| IProgressService service = PlatformUI.getWorkbench().getProgressService(); |
| try { |
| if (!CoreUtil.TEST_MODE) { |
| service.run(false, false, setDirectoryRunnable); |
| } else { |
| setDirectoryRunnable.run(new NullProgressMonitor()); |
| } |
| } catch (InvocationTargetException e) { |
| throw new CoreException(new Status(IStatus.ERROR, TasksUiPlugin.ID_PLUGIN, "Failed to set data directory", |
| e.getCause())); |
| } catch (InterruptedException e) { |
| throw new OperationCanceledException(); |
| } |
| |
| } |
| |
| /** |
| * called on startup and when the mylyn data structures are reloaded from disk |
| */ |
| private void loadDataSources() { |
| externalizationManager.reLoad(); |
| // TODO: Move management of template repositories to TaskRepositoryManager |
| loadTemplateRepositories(); |
| |
| taskActivityManager.clear(); |
| ContextCore.getContextManager().loadActivityMetaContext(); |
| taskActivityMonitor.reloadActivityTime(); |
| taskActivityManager.reloadPlanningData(); |
| } |
| |
| @Override |
| protected void initializeDefaultPreferences(IPreferenceStore store) { |
| store.setDefault(ContextPreferenceContstants.PREF_DATA_DIR, getDefaultDataDirectory()); |
| store.setDefault(ITasksUiPreferenceConstants.GROUP_SUBTASKS, true); |
| store.setDefault(ITasksUiPreferenceConstants.NOTIFICATIONS_ENABLED, true); |
| store.setDefault(ITasksUiPreferenceConstants.FILTER_PRIORITY, PriorityLevel.P5.toString()); |
| store.setDefault(ITasksUiPreferenceConstants.EDITOR_TASKS_RICH, true); |
| store.setDefault(ITasksUiPreferenceConstants.ACTIVATE_WHEN_OPENED, false); |
| store.setDefault(ITasksUiPreferenceConstants.SHOW_TRIM, false); |
| store.setDefault(ITasksUiPreferenceConstants.LOCAL_SUB_TASKS_ENABLED, false); |
| |
| store.setDefault(ITasksUiPreferenceConstants.REPOSITORY_SYNCH_SCHEDULE_ENABLED, true); |
| store.setDefault(ITasksUiPreferenceConstants.REPOSITORY_SYNCH_SCHEDULE_MILISECONDS, "" + (20 * 60 * 1000)); |
| |
| //store.setDefault(TasksUiPreferenceConstants.BACKUP_SCHEDULE, 1); |
| store.setDefault(ITasksUiPreferenceConstants.BACKUP_MAXFILES, 20); |
| store.setDefault(ITasksUiPreferenceConstants.BACKUP_LAST, 0f); |
| |
| store.setDefault(ITasksUiPreferenceConstants.FILTER_ARCHIVE_MODE, true); |
| store.setDefault(ITasksUiPreferenceConstants.ACTIVATE_MULTIPLE, false); |
| store.setValue(ITasksUiPreferenceConstants.ACTIVATE_MULTIPLE, false); |
| |
| store.setDefault(ITasksUiPreferenceConstants.WEEK_START_DAY, Calendar.getInstance().getFirstDayOfWeek()); |
| //store.setDefault(TasksUiPreferenceConstants.PLANNING_STARTHOUR, 9); |
| store.setDefault(ITasksUiPreferenceConstants.PLANNING_ENDHOUR, 18); |
| } |
| |
| public static TaskListManager getTaskListManager() { |
| return taskListManager; |
| } |
| |
| public static TaskActivityManager getTaskActivityManager() { |
| return taskActivityManager; |
| } |
| |
| public static TaskListNotificationManager getTaskListNotificationManager() { |
| return INSTANCE.taskListNotificationManager; |
| } |
| |
| /** |
| * Returns the shared instance. |
| */ |
| public static TasksUiPlugin getDefault() { |
| return INSTANCE; |
| } |
| |
| public boolean groupSubtasks(ITaskElement container) { |
| boolean groupSubtasks = TasksUiPlugin.getDefault().getPreferenceStore().getBoolean( |
| ITasksUiPreferenceConstants.GROUP_SUBTASKS); |
| |
| if (container instanceof ITask) { |
| AbstractRepositoryConnectorUi connectorUi = TasksUiPlugin.getConnectorUi(((ITask) container).getConnectorKind()); |
| if (connectorUi != null) { |
| if (connectorUi.forceSubtaskHierarchy()) { |
| groupSubtasks = true; |
| } |
| } |
| } |
| |
| if (container instanceof IRepositoryQuery) { |
| AbstractRepositoryConnectorUi connectorUi = TasksUiPlugin.getConnectorUi(((IRepositoryQuery) container).getConnectorKind()); |
| if (connectorUi != null) { |
| if (connectorUi.forceSubtaskHierarchy()) { |
| groupSubtasks = true; |
| } |
| } |
| } |
| |
| return groupSubtasks; |
| } |
| |
| private final Map<String, List<IDynamicSubMenuContributor>> menuContributors = new HashMap<String, List<IDynamicSubMenuContributor>>(); |
| |
| public Map<String, List<IDynamicSubMenuContributor>> getDynamicMenuMap() { |
| return menuContributors; |
| } |
| |
| // API-3.0: move to a standard dynamic menu mechanism? |
| public void addDynamicPopupContributor(String menuPath, IDynamicSubMenuContributor contributor) { |
| List<IDynamicSubMenuContributor> contributors = menuContributors.get(menuPath); |
| if (contributors == null) { |
| contributors = new ArrayList<IDynamicSubMenuContributor>(); |
| menuContributors.put(menuPath, contributors); |
| } |
| contributors.add(contributor); |
| } |
| |
| public String[] getSaveOptions() { |
| String[] options = { TaskListSaveMode.ONE_HOUR.toString(), TaskListSaveMode.THREE_HOURS.toString(), |
| TaskListSaveMode.DAY.toString() }; |
| return options; |
| } |
| |
| public String getBackupFolderPath() { |
| return getDataDirectory() + DEFAULT_PATH_SEPARATOR + ITasksCoreConstants.DEFAULT_BACKUP_FOLDER_NAME; |
| } |
| |
| public ITaskHighlighter getHighlighter() { |
| return highlighter; |
| } |
| |
| public void setHighlighter(ITaskHighlighter highlighter) { |
| this.highlighter = highlighter; |
| } |
| |
| /** |
| * @since 3.0 |
| */ |
| public AbstractTaskEditorPageFactory[] getTaskEditorPageFactories() { |
| return taskEditorPageFactories.toArray(new AbstractTaskEditorPageFactory[0]); |
| } |
| |
| public Set<AbstractTaskEditorFactory> getTaskEditorFactories() { |
| return taskEditorFactories; |
| } |
| |
| public void addContextEditor(AbstractTaskEditorFactory contextEditor) { |
| if (contextEditor != null) { |
| this.taskEditorFactories.add(contextEditor); |
| } |
| } |
| |
| /** |
| * @since 3.0 |
| */ |
| public void addTaskEditorPageFactory(AbstractTaskEditorPageFactory factory) { |
| Assert.isNotNull(factory); |
| taskEditorPageFactories.add(factory); |
| } |
| |
| /** |
| * @since 3.0 |
| */ |
| public void removeTaskEditorPageFactory(AbstractTaskEditorPageFactory factory) { |
| Assert.isNotNull(factory); |
| taskEditorPageFactories.remove(factory); |
| } |
| |
| public static TaskRepositoryManager getRepositoryManager() { |
| return repositoryManager; |
| } |
| |
| /** |
| * @since 3.0 |
| */ |
| public static RepositoryTemplateManager getRepositoryTemplateManager() { |
| return INSTANCE.repositoryTemplateManager; |
| } |
| |
| public void addBrandingIcon(String repositoryType, Image icon) { |
| brandingIcons.put(repositoryType, icon); |
| } |
| |
| public Image getBrandingIcon(String repositoryType) { |
| return brandingIcons.get(repositoryType); |
| } |
| |
| public void addOverlayIcon(String repositoryType, ImageDescriptor icon) { |
| overlayIcons.put(repositoryType, icon); |
| } |
| |
| public ImageDescriptor getOverlayIcon(String repositoryType) { |
| return overlayIcons.get(repositoryType); |
| } |
| |
| // public boolean isInitialized() { |
| // return initialized; |
| // } |
| |
| public IHyperlinkDetector[] getTaskHyperlinkDetectors() { |
| return hyperlinkDetectors.toArray(new IHyperlinkDetector[1]); |
| } |
| |
| public void addTaskHyperlinkDetector(IHyperlinkDetector listener) { |
| if (listener != null) { |
| this.hyperlinkDetectors.add(listener); |
| } |
| } |
| |
| public void addRepositoryLinkProvider(AbstractTaskRepositoryLinkProvider repositoryLinkProvider) { |
| if (repositoryLinkProvider != null) { |
| this.repositoryLinkProviders.add(repositoryLinkProvider); |
| } |
| } |
| |
| public static TaskListBackupManager getBackupManager() { |
| return INSTANCE.taskListBackupManager; |
| } |
| |
| public static TaskDataStorageManager getTaskDataStorageManager() { |
| return INSTANCE.taskDataStorageManager; |
| } |
| |
| public void addRepositoryConnectorUi(AbstractRepositoryConnectorUi repositoryConnectorUi) { |
| if (!repositoryConnectorUiMap.values().contains(repositoryConnectorUi)) { |
| repositoryConnectorUiMap.put(repositoryConnectorUi.getConnectorKind(), repositoryConnectorUi); |
| } |
| } |
| |
| /** |
| * @since 3.0 |
| */ |
| public static AbstractRepositoryConnector getConnector(String kind) { |
| return getRepositoryManager().getRepositoryConnector(kind); |
| } |
| |
| public static AbstractRepositoryConnectorUi getConnectorUi(String kind) { |
| return repositoryConnectorUiMap.get(kind); |
| } |
| |
| public static TaskListSynchronizationScheduler getSynchronizationScheduler() { |
| return synchronizationScheduler; |
| } |
| |
| /** |
| * @since 3.0 |
| */ |
| public static TaskDataManager getTaskDataManager() { |
| return taskDataManager; |
| } |
| |
| /** |
| * @since 3.0 |
| */ |
| public static TaskJobFactory getTasksJobFactory() { |
| return INSTANCE.tasksJobFactory; |
| } |
| |
| public void addDuplicateDetector(AbstractDuplicateDetector duplicateDetector) { |
| Assert.isNotNull(duplicateDetector); |
| duplicateDetectors.add(duplicateDetector); |
| } |
| |
| public Set<AbstractDuplicateDetector> getDuplicateSearchCollectorsList() { |
| return duplicateDetectors; |
| } |
| |
| public String getRepositoriesFilePath() { |
| return getDataDirectory() + File.separator + TaskRepositoryManager.DEFAULT_REPOSITORIES_FILE; |
| } |
| |
| public boolean canSetRepositoryForResource(IResource resource) { |
| if (resource == null) { |
| return false; |
| } |
| |
| // find first provider that can link repository |
| for (AbstractTaskRepositoryLinkProvider linkProvider : repositoryLinkProviders) { |
| TaskRepository repository = linkProvider.getTaskRepository(resource, getRepositoryManager()); |
| if (repository != null) { |
| return linkProvider.canSetTaskRepository(resource); |
| } |
| } |
| // find first provider that can set new repository |
| for (AbstractTaskRepositoryLinkProvider linkProvider : repositoryLinkProviders) { |
| if (linkProvider.canSetTaskRepository(resource)) { |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| /** |
| * Associate a Task Repository with a workbench project |
| * |
| * @param resource |
| * project or resource belonging to a project |
| * @param repository |
| * task repository to associate with given project |
| * @throws CoreException |
| */ |
| public void setRepositoryForResource(IResource resource, TaskRepository repository) throws CoreException { |
| if (resource == null || repository == null) { |
| return; |
| } |
| |
| for (AbstractTaskRepositoryLinkProvider linkProvider : repositoryLinkProviders) { |
| TaskRepository r = linkProvider.getTaskRepository(resource, getRepositoryManager()); |
| boolean canSetRepository = linkProvider.canSetTaskRepository(resource); |
| if (r != null && !canSetRepository) { |
| return; |
| } |
| if (canSetRepository) { |
| linkProvider.setTaskRepository(resource, repository); |
| return; |
| } |
| } |
| } |
| |
| /** |
| * Retrieve the task repository that has been associated with the given project (or resource belonging to a project) |
| * |
| * NOTE: if call does not return in LINK_PROVIDER_TIMEOUT_SECONDS, the provide will be disabled until the next time |
| * that the Workbench starts. |
| */ |
| public TaskRepository getRepositoryForResource(final IResource resource) { |
| Assert.isNotNull(resource); |
| Set<AbstractTaskRepositoryLinkProvider> defectiveLinkProviders = new HashSet<AbstractTaskRepositoryLinkProvider>(); |
| for (final AbstractTaskRepositoryLinkProvider linkProvider : repositoryLinkProviders) { |
| long startTime = System.nanoTime(); |
| final TaskRepository[] repository = new TaskRepository[1]; |
| SafeRunnable.run(new ISafeRunnable() { |
| public void handleException(Throwable e) { |
| StatusHandler.log(new Status(IStatus.ERROR, ID_PLUGIN, "Repository link provider failed: \"" |
| + linkProvider.getId() + "\"", e)); |
| } |
| |
| public void run() throws Exception { |
| repository[0] = linkProvider.getTaskRepository(resource, getRepositoryManager()); |
| } |
| }); |
| long elapsed = System.nanoTime() - startTime; |
| if (elapsed > LINK_PROVIDER_TIMEOUT_SECONDS * 1000 * 1000 * 1000) { |
| defectiveLinkProviders.add(linkProvider); |
| } |
| if (repository[0] != null) { |
| return repository[0]; |
| } |
| } |
| if (!defectiveLinkProviders.isEmpty()) { |
| repositoryLinkProviders.removeAll(defectiveLinkProviders); |
| StatusHandler.log(new Status(IStatus.WARNING, ID_PLUGIN, |
| "Repository link provider took over 5s to execute and was timed out: \"" + defectiveLinkProviders |
| + "\"")); |
| } |
| return null; |
| } |
| |
| @Deprecated |
| public TaskRepository getRepositoryForResource(final IResource resource, boolean silent) { |
| TaskRepository repository = getRepositoryForResource(resource); |
| if (repository == null && !silent) { |
| MessageDialog.openInformation(null, "No Repository Found", |
| "No repository was found. Associate a Task Repository with this project via the project's property page."); |
| } |
| return repository; |
| } |
| |
| public String getNextNewRepositoryTaskId() { |
| return getTaskDataStorageManager().getNewRepositoryTaskId(); |
| } |
| |
| public static ExternalizationManager getExternalizationManager() { |
| return externalizationManager; |
| } |
| |
| public static TaskActivityMonitor getTaskActivityMonitor() { |
| return INSTANCE.taskActivityMonitor; |
| } |
| |
| public static TaskList getTaskList() { |
| return taskList; |
| } |
| |
| public static TasksModel getTasksModel() { |
| return tasksModel; |
| } |
| |
| public void addSearchHandler(AbstractSearchHandler searchHandler) { |
| searchHandlers.add(searchHandler); |
| } |
| |
| public void removeSearchHandler(AbstractSearchHandler searchHandler) { |
| searchHandlers.remove(searchHandler); |
| } |
| |
| public AbstractSearchHandler getSearchHandler(String connectorKind) { |
| Assert.isNotNull(connectorKind); |
| for (AbstractSearchHandler searchHandler : searchHandlers) { |
| if (searchHandler.getConnectorKind().equals(connectorKind)) { |
| return searchHandler; |
| } |
| } |
| return null; |
| } |
| |
| } |