/******************************************************************************* * Copyright (c) 2004, 2015 Tasktop Technologies and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Tasktop Technologies - initial API and implementation *******************************************************************************/ package org.eclipse.mylyn.internal.tasks.ui; import java.io.File; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.util.ArrayList; import java.util.Arrays; 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 java.util.concurrent.atomic.AtomicInteger; 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.IPath; 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.Platform; import org.eclipse.core.runtime.SafeRunner; import org.eclipse.core.runtime.Status; import org.eclipse.core.runtime.jobs.Job; import org.eclipse.jface.action.Action; import org.eclipse.jface.action.MenuManager; import org.eclipse.jface.dialogs.Dialog; import org.eclipse.jface.operation.IRunnableWithProgress; import org.eclipse.jface.preference.IPreferenceStore; import org.eclipse.jface.resource.ImageDescriptor; import org.eclipse.jface.util.SafeRunnable; import org.eclipse.mylyn.commons.core.StatusHandler; import org.eclipse.mylyn.commons.identity.core.IIdentityService; import org.eclipse.mylyn.commons.net.WebUtil; import org.eclipse.mylyn.commons.notifications.core.NotificationEnvironment; import org.eclipse.mylyn.commons.notifications.feed.ServiceMessageManager; import org.eclipse.mylyn.commons.notifications.ui.AbstractUiNotification; import org.eclipse.mylyn.commons.ui.compatibility.CommonColors; import org.eclipse.mylyn.commons.ui.compatibility.CommonFonts; import org.eclipse.mylyn.commons.workbench.TaskBarManager; import org.eclipse.mylyn.internal.commons.notifications.feed.ServiceMessage; import org.eclipse.mylyn.internal.discovery.ui.DiscoveryUi; import org.eclipse.mylyn.internal.monitor.ui.MonitorUiPlugin; import org.eclipse.mylyn.internal.tasks.core.AbstractSearchHandler; import org.eclipse.mylyn.internal.tasks.core.AbstractTask; import org.eclipse.mylyn.internal.tasks.core.IRepositoryModelListener; 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.RepositoryModel; 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.TaskList; import org.eclipse.mylyn.internal.tasks.core.TaskRepositoryDelta; import org.eclipse.mylyn.internal.tasks.core.TaskRepositoryDelta.Type; import org.eclipse.mylyn.internal.tasks.core.TaskRepositoryManager; import org.eclipse.mylyn.internal.tasks.core.data.SynchronizationManger; 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.externalization.ExternalizationManager; import org.eclipse.mylyn.internal.tasks.core.externalization.IExternalizationParticipant; import org.eclipse.mylyn.internal.tasks.core.externalization.TaskActivationExternalizationParticipant; import org.eclipse.mylyn.internal.tasks.core.externalization.TaskListExternalizationParticipant; import org.eclipse.mylyn.internal.tasks.core.externalization.TaskListExternalizer; import org.eclipse.mylyn.internal.tasks.core.util.RepositoryConnectorLoader; import org.eclipse.mylyn.internal.tasks.core.util.TaskRepositoryKeyringMigrator; import org.eclipse.mylyn.internal.tasks.core.util.TaskRepositorySecureStoreMigrator; import org.eclipse.mylyn.internal.tasks.core.util.TasksCoreExtensionReader; import org.eclipse.mylyn.internal.tasks.ui.actions.ActivateTaskDialogAction; import org.eclipse.mylyn.internal.tasks.ui.actions.NewTaskAction; import org.eclipse.mylyn.internal.tasks.ui.notifications.TaskListNotificationReminder; import org.eclipse.mylyn.internal.tasks.ui.notifications.TaskListNotifier; import org.eclipse.mylyn.internal.tasks.ui.util.TasksUiExtensionReader; import org.eclipse.mylyn.internal.tasks.ui.views.TaskListView; 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.ITask.PriorityLevel; import org.eclipse.mylyn.tasks.core.ITaskContainer; import org.eclipse.mylyn.tasks.core.RepositoryTemplate; import org.eclipse.mylyn.tasks.core.TaskRepository; import org.eclipse.mylyn.tasks.core.activity.AbstractTaskActivityMonitor; import org.eclipse.mylyn.tasks.core.context.AbstractTaskContextStore; 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.TasksUiImages; import org.eclipse.mylyn.tasks.ui.editors.AbstractTaskEditorPageFactory; import org.eclipse.osgi.util.NLS; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.widgets.Display; import org.eclipse.ui.IStartup; import org.eclipse.ui.IWorkbenchWindow; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.forms.FormColors; 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; import org.osgi.util.tracker.ServiceTracker; /** * Main entry point for the Tasks UI. * * @author Mik Kersten * @since 3.0 */ public class TasksUiPlugin extends AbstractUIPlugin { private static final int DEFAULT_LINK_PROVIDER_TIMEOUT = 5 * 1000; public static final String ID_PLUGIN = "org.eclipse.mylyn.tasks.ui"; //$NON-NLS-1$ private static final String DIRECTORY_METADATA = ".metadata"; //$NON-NLS-1$ private static final String NAME_DATA_DIR = ".mylyn"; //$NON-NLS-1$ private static final char DEFAULT_PATH_SEPARATOR = '/'; private static final int NOTIFICATION_DELAY = 5000; private static final String PREF_MIGRATED_TASK_REPOSITORIES_FROM_SECURE_STORE = "migrated.task.repositories.secure.store"; //$NON-NLS-1$ private static final String PREF_MIGRATED_TASK_REPOSITORIES_FROM_KEYRING = "migrated.task.repositories.keyring"; //$NON-NLS-1$ private static final String PROP_FORCE_CREDENTIALS_MIGRATION = "org.eclipse.mylyn.tasks.force.credentials.migration"; //$NON-NLS-1$ private static final boolean DEBUG_HTTPCLIENT = "true" //$NON-NLS-1$ .equalsIgnoreCase(Platform.getDebugOption("org.eclipse.mylyn.tasks.ui/debug/httpclient")); //$NON-NLS-1$ private static TasksUiPlugin INSTANCE; private static ExternalizationManager externalizationManager; private static TaskActivityManager taskActivityManager; private static TaskRepositoryManager repositoryManager; private static TaskDataManager taskDataManager; private static Map<String, AbstractRepositoryConnectorUi> repositoryConnectorUiMap = new HashMap<String, AbstractRepositoryConnectorUi>(); private static AbstractTaskContextStore contextStore; private TaskListNotificationManager taskListNotificationManager; private TaskListBackupManager taskListBackupManager; private RepositoryTemplateManager repositoryTemplateManager; private ServiceMessageManager serviceMessageManager; private final Set<AbstractTaskEditorPageFactory> taskEditorPageFactories = new HashSet<AbstractTaskEditorPageFactory>(); private final TreeSet<AbstractTaskRepositoryLinkProvider> repositoryLinkProviders = new TreeSet<AbstractTaskRepositoryLinkProvider>( new OrderComparator()); private TaskListExternalizer taskListExternalizer; private final BrandManager brandManager = new BrandManager(); private final Set<AbstractDuplicateDetector> duplicateDetectors = new HashSet<AbstractDuplicateDetector>(); private ISaveParticipant saveParticipant; private TaskJobFactory taskJobFactory; // shared colors for all forms private FormColors formColors; private final List<AbstractSearchHandler> searchHandlers = new ArrayList<AbstractSearchHandler>(); // 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"; //$NON-NLS-1$ case THREE_HOURS: return "3 hours"; //$NON-NLS-1$ case DAY: return "1 day"; //$NON-NLS-1$ default: return "3 hours"; //$NON-NLS-1$ } } public static TaskListSaveMode fromString(String string) { if (string == null) { return null; } if (string.equals("1 hour")) { //$NON-NLS-1$ return ONE_HOUR; } if (string.equals("3 hours")) { //$NON-NLS-1$ return THREE_HOURS; } if (string.equals("1 day")) { //$NON-NLS-1$ 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 ITaskListNotificationProvider REMINDER_NOTIFICATION_PROVIDER = new ITaskListNotificationProvider() { public Set<AbstractUiNotification> getNotifications() { Collection<AbstractTask> allTasks = TasksUiPlugin.getTaskList().getAllTasks(); Set<AbstractUiNotification> reminders = new HashSet<AbstractUiNotification>(); for (AbstractTask task : allTasks) { if (TasksUiPlugin.getTaskActivityManager().isPastReminder(task) && !task.isReminded()) { reminders.add(new TaskListNotificationReminder(task)); task.setReminded(true); } } return reminders; } }; 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(ITasksUiPreferenceConstants.PLANNING_ENDHOUR) || event.getProperty().equals(ITasksUiPreferenceConstants.WEEK_START_DAY)) { updateTaskActivityManager(); } if (event.getProperty().equals(ITasksUiPreferenceConstants.SERVICE_MESSAGES_ENABLED)) { if (getPreferenceStore().getBoolean(ITasksUiPreferenceConstants.SERVICE_MESSAGES_ENABLED)) { serviceMessageManager.start(); } else { serviceMessageManager.stop(); } } if (synchronizationManager != null) { synchronizationManager.processPreferenceChange(event); } } }; private AbstractTaskActivityMonitor taskActivityMonitor; @SuppressWarnings("rawtypes") private ServiceReference proxyServiceReference; private IProxyChangeListener proxyChangeListener; private static TaskListExternalizationParticipant taskListExternalizationParticipant; private final Set<IRepositoryModelListener> listeners = new HashSet<IRepositoryModelListener>(); private File activationHistoryFile; private static TaskList taskList; private static RepositoryModel repositoryModel; private static TasksUiFactory uiFactory; @Deprecated public static String LABEL_VIEW_REPOSITORIES = Messages.TasksUiPlugin_Task_Repositories; private final AtomicInteger initializationCount = new AtomicInteger(); private SynchronizationManger synchronizationManger; private RepositoryConnectorLoader connectorLoader; private TaskListScheduledSynchronizationManager synchronizationManager; private class TasksUiInitializationJob extends UIJob { public TasksUiInitializationJob() { super(Messages.TasksUiPlugin_Initializing_Task_List); setSystem(true); } @SuppressWarnings("restriction") @Override public IStatus runInUIThread(IProgressMonitor monitor) { // NOTE: failure in one part of the initialization should // not prevent others monitor.beginTask("Initializing Task List", 5); //$NON-NLS-1$ try { // Needs to run after workbench is loaded because it // relies on images. TasksUiExtensionReader.initWorkbenchUiExtensions(connectorLoader.getBlackList()); if (externalizationManager.getLoadStatus() != null) { // XXX: recovery from task list load failure (Rendered in task list) } List<String> commandLineArgs = Arrays.asList(Platform.getCommandLineArgs()); boolean activateTask = !commandLineArgs.contains(ITasksCoreConstants.COMMAND_LINE_NO_ACTIVATE_TASK); if (activateTask) { try { Field field = org.eclipse.core.internal.resources.Workspace.class.getDeclaredField("crashed"); //$NON-NLS-1$ field.setAccessible(true); Object value = field.get(ResourcesPlugin.getWorkspace()); if (value instanceof Boolean) { activateTask = !(Boolean) value; } } catch (Throwable t) { t.printStackTrace(); // ignore } } // Needs to happen asynchronously to avoid bug 159706 for (AbstractTask task : taskList.getAllTasks()) { if (task.isActive()) { // the externalizer might set multiple tasks active task.setActive(false); if (activateTask) { // make sure only one task is activated taskActivityManager.activateTask(task); activateTask = false; } } } //taskActivityMonitor.reloadActivityTime(); } catch (Throwable t) { StatusHandler.log( new Status(IStatus.ERROR, TasksUiPlugin.ID_PLUGIN, "Could not initialize task activity", t)); //$NON-NLS-1$ } monitor.worked(1); initializeNotificationsAndSynchronization(); addSystemTaskBarActions(); 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(); } } catch (Throwable t) { StatusHandler.log(new Status(IStatus.ERROR, TasksUiPlugin.ID_PLUGIN, "Could not finish Tasks UI initialization", t)); //$NON-NLS-1$ } finally { monitor.done(); } hideNonMatchingSubtasks(); return new Status(IStatus.OK, TasksUiPlugin.ID_PLUGIN, IStatus.OK, "", null); //$NON-NLS-1$ } /** * hide non-matching subtasks, or display a message about it if this is not a fresh installation */ protected void hideNonMatchingSubtasks() { final String HIDE_SUBTASKS = "hide-subtasks"; //$NON-NLS-1$ if (!getPreferenceStore().getBoolean(ITasksUiPreferenceConstants.FILTER_NON_MATCHING) && !getPreferenceStore().getBoolean(ITasksUiPreferenceConstants.ENCOURAGED_FILTER_NON_MATCHING)) { if (taskList.getQueries().isEmpty()) { getPreferenceStore().setValue(ITasksUiPreferenceConstants.FILTER_NON_MATCHING, true); } else { TaskListView view = TaskListView.getFromActivePerspective(); if (view != null && view.getServiceMessageControl() != null) { ServiceMessage message = new ServiceMessage("") { //$NON-NLS-1$ @Override public boolean openLink(String link) { if (HIDE_SUBTASKS.equals(link)) { getPreferenceStore().setValue(ITasksUiPreferenceConstants.FILTER_NON_MATCHING, true); savePluginPreferences(); return true; } return false; } }; message.setImage(Dialog.DLG_IMG_MESSAGE_INFO); message.setTitle(Messages.TasksUiPlugin_Hide_Irrelevant_Subtasks); message.setDescription( NLS.bind(Messages.TasksUiPlugin_Hide_Irrelevant_Subtasks_Message, HIDE_SUBTASKS)); view.getServiceMessageControl().setMessage(message); } } // never do this again getPreferenceStore().setValue(ITasksUiPreferenceConstants.ENCOURAGED_FILTER_NON_MATCHING, true); savePluginPreferences(); } } } public TasksUiPlugin() { super(); INSTANCE = this; } private void addSystemTaskBarActions() { MenuManager taskBarMenuManager = TaskBarManager.getTaskBarMenuManager(); if (taskBarMenuManager != null) { NewTaskAction newTaskAction = new NewTaskAction(Messages.TasksUiPlugin_New_Task, true); taskBarMenuManager.add(newTaskAction); Action activateTaskAction = new Action() { @Override public void run() { ActivateTaskDialogAction activateTaskDialogAction = new ActivateTaskDialogAction(); IWorkbenchWindow window = getWorkbench().getActiveWorkbenchWindow(); if (window == null && getWorkbench().getWorkbenchWindows().length > 0) { window = getWorkbench().getWorkbenchWindows()[0]; } activateTaskDialogAction.init(window); activateTaskDialogAction.run(null); } }; activateTaskAction.setImageDescriptor(TasksUiImages.CONTEXT_ACTIVE_CENTERED); activateTaskAction.setText(Messages.TasksUiPlugin_Activate_Task); taskBarMenuManager.add(activateTaskAction); taskBarMenuManager.update(true); } } @SuppressWarnings("restriction") @Override public void start(BundleContext context) throws Exception { super.start(context); // NOTE: startup order is very sensitive try { // initialize framework and settings if (DEBUG_HTTPCLIENT) { // do this before anything else, once commons logging is initialized and an instance // of Log has been created it's too late initHttpLogging(); } WebUtil.init(); initializePreferences(getPreferenceStore()); // initialize CommonFonts from UI thread: bug 240076 if (CommonFonts.BOLD == null) { // ignore } 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(); repositoryModel = new RepositoryModel(taskList, repositoryManager); taskListExternalizer = new TaskListExternalizer(repositoryModel, repositoryManager); taskListExternalizationParticipant = new TaskListExternalizationParticipant(repositoryModel, taskList, taskListExternalizer, externalizationManager, repositoryManager); //externalizationManager.load(taskListSaveParticipant); externalizationManager.addParticipant(taskListExternalizationParticipant); taskList.addChangeListener(taskListExternalizationParticipant); taskActivityManager = new TaskActivityManager(repositoryManager, taskList); taskActivityManager.addActivationListener(taskListExternalizationParticipant); // initialize updateTaskActivityManager(); proxyServiceReference = context.getServiceReference(IProxyService.class.getName()); if (proxyServiceReference != null) { @SuppressWarnings("unchecked") IProxyService proxyService = (IProxyService) context.getService(proxyServiceReference); if (proxyService != null) { proxyChangeListener = new IProxyChangeListener() { public void proxyInfoChanged(IProxyChangeEvent event) { List<TaskRepository> repositories = repositoryManager.getAllRepositories(); for (TaskRepository repository : repositories) { if (repository.isDefaultProxyEnabled()) { repositoryManager.notifyRepositorySettingsChanged(repository, new TaskRepositoryDelta(Type.PROYX)); } } } }; proxyService.addProxyChangeListener(proxyChangeListener); } } repositoryTemplateManager = new RepositoryTemplateManager(); // NOTE: initializing extensions in start(..) has caused race // conditions previously connectorLoader = new RepositoryConnectorLoader(); connectorLoader.registerConnectors(repositoryManager, taskListExternalizer); connectorLoader.registerTemplates(repositoryManager, repositoryTemplateManager); TasksUiExtensionReader.initStartupExtensions(connectorLoader.getBlackList()); // instantiate taskDataManager TaskDataStore taskDataStore = new TaskDataStore(repositoryManager); synchronizationManger = new SynchronizationManger(repositoryModel); taskDataManager = new TaskDataManager(taskDataStore, repositoryManager, taskList, taskActivityManager, synchronizationManger); taskJobFactory = new TaskJobFactory(taskList, taskDataManager, repositoryManager, repositoryModel); taskActivityMonitor = TasksCoreExtensionReader.loadTaskActivityMonitor(); taskActivityMonitor.start(taskActivityManager); 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(); } } }; ResourcesPlugin.getWorkspace().addSaveParticipant(this, saveParticipant); // initialize externalization for task activation history IPath stateLocation = Platform.getStateLocation(getBundle()); activationHistoryFile = stateLocation.append("TaskActivationHistory.xml").toFile(); //$NON-NLS-1$ TaskActivationExternalizationParticipant taskActivationExternalizationParticipant = new TaskActivationExternalizationParticipant( externalizationManager, taskList, taskActivityManager.getTaskActivationHistory(), activationHistoryFile); taskActivityManager.addActivationListener(taskActivationExternalizationParticipant); externalizationManager.addParticipant(taskActivationExternalizationParticipant); // initialize managers initializeDataSources(); migrateCredentials(repositoryManager.getAllRepositories()); // make this available early for clients that are not initialized through tasks ui but need access taskListNotificationManager = new TaskListNotificationManager(); String lastMod = getPreferenceStore() .getString(ITasksUiPreferenceConstants.LAST_SERVICE_MESSAGE_LAST_MODIFIED); String etag = getPreferenceStore().getString(ITasksUiPreferenceConstants.LAST_SERVICE_MESSAGE_ETAG); String serviceMessageUrl = getPreferenceStore().getString(ITasksUiPreferenceConstants.SERVICE_MESSAGE_URL); Long checktime = getPreferenceStore().getLong(ITasksUiPreferenceConstants.LAST_SERVICE_MESSAGE_CHECKTIME); serviceMessageManager = new ServiceMessageManager(serviceMessageUrl, lastMod, etag, checktime, new NotificationEnvironment() { private Set<String> installedFeatures; @Override public Set<String> getInstalledFeatures(IProgressMonitor monitor) { if (installedFeatures == null) { installedFeatures = DiscoveryUi.createInstallJob().getInstalledFeatures(monitor); } return installedFeatures; } }); // Disabled for initial 3.4 release as per bug#263528 if (getPreferenceStore().getBoolean(ITasksUiPreferenceConstants.SERVICE_MESSAGES_ENABLED)) { serviceMessageManager.start(); } // trigger lazy initialization new TasksUiInitializationJob().schedule(); } catch (Exception e) { StatusHandler.log(new Status(IStatus.ERROR, TasksUiPlugin.ID_PLUGIN, "Task list initialization failed", e)); //$NON-NLS-1$ } } /** * Migrate credentials from the old secure store location, and from the deprecated keyring if the compatibility.auth * bundle is present. */ @SuppressWarnings("deprecation") private void migrateCredentials(final List<TaskRepository> repositories) { final boolean force = Boolean.parseBoolean(System.getProperty(PROP_FORCE_CREDENTIALS_MIGRATION)); final boolean migrateFromSecureStore = force || !getPluginPreferences().getBoolean(PREF_MIGRATED_TASK_REPOSITORIES_FROM_SECURE_STORE); final boolean migrateFromKeyring = (force || !getPluginPreferences().getBoolean(PREF_MIGRATED_TASK_REPOSITORIES_FROM_KEYRING)) && isKeyringInstalled(); if (!migrateFromSecureStore && !migrateFromKeyring) { return; } // Use a UI job to ensure the UI has loaded new UIJob("Credential Migration UI Job") { //$NON-NLS-1$ @Override public IStatus runInUIThread(IProgressMonitor monitor) { // use a Job to ensure we do not access the secure store on the UI thread new Job("Credential Migration") { //$NON-NLS-1$ @Override protected IStatus run(IProgressMonitor monitor) { if (force) { StatusHandler.log(new Status(IStatus.INFO, ITasksCoreConstants.ID_PLUGIN, NLS.bind( "Forcing task repository credential migration because system property {0} is set.", //$NON-NLS-1$ PROP_FORCE_CREDENTIALS_MIGRATION))); } if (migrateFromSecureStore) { new TaskRepositorySecureStoreMigrator().migrateCredentials(repositories); } if (migrateFromKeyring) { new TaskRepositoryKeyringMigrator("", "Basic").migrateCredentials(repositories); //$NON-NLS-1$ //$NON-NLS-2$ } return Status.OK_STATUS; } }.schedule(); return Status.OK_STATUS; } }.schedule(); } private boolean isKeyringInstalled() { return Platform.getBundle("org.eclipse.core.runtime.compatibility.auth") != null; //$NON-NLS-1$ } private void initHttpLogging() { System.setProperty("org.apache.commons.logging.Log", "org.apache.commons.logging.impl.SimpleLog"); //$NON-NLS-1$ //$NON-NLS-2$ System.setProperty("org.apache.commons.logging.simplelog.showdatetime", "true"); //$NON-NLS-1$ //$NON-NLS-2$ System.setProperty("org.apache.commons.logging.simplelog.log.httpclient.wire", "debug"); //$NON-NLS-1$ //$NON-NLS-2$ System.setProperty("org.apache.commons.logging.simplelog.log.httpclient.wire.header", "debug"); //$NON-NLS-1$ //$NON-NLS-2$ System.setProperty("org.apache.commons.logging.simplelog.log.org.apache.commons.httpclient", "debug"); //$NON-NLS-1$ //$NON-NLS-2$ System.setProperty("org.apache.commons.logging.simplelog.log.org.apache.commons.httpclient.HttpConnection", //$NON-NLS-1$ "trace"); //$NON-NLS-1$ System.setProperty("org.apache.commons.logging.simplelog.log.org.apache.axis.message", "debug"); //$NON-NLS-1$ //$NON-NLS-2$ } 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 local = getLocalTaskRepository(); repositoryManager.applyMigrators(local); // 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 { String repositoryUrl = TaskRepositoryManager.stripSlashes(template.repositoryUrl); TaskRepository taskRepository = repositoryManager.getRepository(connector.getConnectorKind(), repositoryUrl); if (taskRepository == null) { taskRepository = new TaskRepository(connector.getConnectorKind(), repositoryUrl); taskRepository.setVersion(template.version); taskRepository.setRepositoryLabel(template.label); taskRepository.setCharacterEncoding(template.characterEncoding); if (template.anonymous) { taskRepository.setProperty("org.eclipse.mylyn.tasklist.repositories.enabled", //$NON-NLS-1$ String.valueOf(false)); // bug 332747: avoid reseting password in shared keystore //taskRepository.setCredentials(AuthenticationType.REPOSITORY, null, true); } taskRepository.setCreatedFromTemplate(true); repositoryManager.addRepository(taskRepository); repositoryManager.applyMigrators(taskRepository); } } catch (Throwable t) { StatusHandler.log(new Status(IStatus.WARNING, TasksUiPlugin.ID_PLUGIN, NLS.bind( "Could not load repository template for repository {0}", template.repositoryUrl), t)); //$NON-NLS-1$ } } } } } /** * 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); repositoryManager.addRepository(localRepository); } return localRepository; } @Override public void stop(BundleContext context) throws Exception { try { Job.getJobManager().cancel(ITasksCoreConstants.JOB_FAMILY_SYNCHRONIZATION); if (formColors != null) { formColors.dispose(); formColors = null; } if (taskActivityMonitor != null) { taskActivityMonitor.stop(); } if (ResourcesPlugin.getWorkspace() != null) { ResourcesPlugin.getWorkspace().removeSaveParticipant(this); } if (proxyServiceReference != null) { @SuppressWarnings("unchecked") IProxyService proxyService = (IProxyService) context.getService(proxyServiceReference); if (proxyService != null) { proxyService.removeProxyChangeListener(proxyChangeListener); } context.ungetService(proxyServiceReference); } if (identityServiceTracker != null) { identityServiceTracker.close(); identityServiceTracker = null; } // wait until stop() to set these to reduce chance of crash after setting them but before creds are persisted getPluginPreferences().setValue(PREF_MIGRATED_TASK_REPOSITORIES_FROM_SECURE_STORE, Boolean.toString(true)); if (isKeyringInstalled()) { getPluginPreferences().setValue(PREF_MIGRATED_TASK_REPOSITORIES_FROM_KEYRING, Boolean.toString(true)); } if (PlatformUI.isWorkbenchRunning()) { if (taskListNotificationManager != null) { getPreferenceStore().removePropertyChangeListener(taskListNotificationManager); } if (taskListBackupManager != null) { getPreferenceStore().removePropertyChangeListener(taskListBackupManager); } getPreferenceStore().removePropertyChangeListener(PROPERTY_LISTENER); //taskListManager.getTaskList().removeChangeListener(taskListSaveManager); CommonColors.dispose(); // if (ContextCorePlugin.getDefault() != null) { // ContextCorePlugin.getDefault().getPluginPreferences().removePropertyChangeListener( // PREFERENCE_LISTENER); // } serviceMessageManager.stop(); INSTANCE = null; } } catch (Exception e) { StatusHandler .log(new Status(IStatus.ERROR, TasksUiPlugin.ID_PLUGIN, "Task list stop terminated abnormally", e)); //$NON-NLS-1$ } finally { super.stop(context); } } public String getDefaultDataDirectory() { return ResourcesPlugin.getWorkspace().getRoot().getLocation().toString() + '/' + DIRECTORY_METADATA + '/' + NAME_DATA_DIR; } public String getDataDirectory() { return getPreferenceStore().getString(ITasksUiPreferenceConstants.PREF_DATA_DIR); } /** * Persist <code>path</code> as data directory and loads data from <code>path</code>. This method may block if other * jobs are running that modify tasks data. This method will only execute after all conflicting jobs have been * completed. * * @throws CoreException * in case setting of the data directory did not complete normally * @throws OperationCanceledException * if the operation is cancelled by the user */ public void setDataDirectory(final String path) throws CoreException { Assert.isNotNull(path); IRunnableWithProgress runner = new IRunnableWithProgress() { public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException { try { monitor.beginTask(Messages.TasksUiPlugin_Load_Data_Directory, IProgressMonitor.UNKNOWN); if (monitor.isCanceled()) { throw new InterruptedException(); } TasksUi.getTaskActivityManager().deactivateActiveTask(); // set new preference in case of a change if (!path.equals(getDataDirectory())) { getPreferenceStore().setValue(ITasksUiPreferenceConstants.PREF_DATA_DIR, path); } // reload data from new directory initializeDataSources(); } finally { // FIXME roll back preferences change in case of an error? monitor.done(); } } }; IProgressService service = PlatformUI.getWorkbench().getProgressService(); try { service.runInUI(service, runner, ITasksCoreConstants.ROOT_SCHEDULING_RULE); } catch (InvocationTargetException e) { throw new CoreException(new Status(IStatus.ERROR, TasksUiPlugin.ID_PLUGIN, "Failed to set data directory", //$NON-NLS-1$ e.getCause())); } catch (InterruptedException e) { throw new OperationCanceledException(); } } public void reloadDataDirectory() throws CoreException { // no save just load what is there setDataDirectory(getDataDirectory()); } /** * Invoked on startup and when data is loaded from disk or when the data directory changes. * <p> * Public for testing. */ @SuppressWarnings("restriction") public void initializeDataSources() { // ensure that context directory exists File storeFile = new File(getDataDirectory(), ITasksCoreConstants.CONTEXTS_DIRECTORY); if (!storeFile.exists()) { storeFile.mkdirs(); } taskDataManager.setDataPath(getDataDirectory()); externalizationManager.setRootFolderPath(getDataDirectory()); getContextStore().setDirectory(new File(getDataDirectory(), "tasks")); //$NON-NLS-1$ externalizationManager.load(); // TODO: Move management of template repositories to TaskRepositoryManager loadTemplateRepositories(); taskActivityManager.clear(); taskActivityMonitor.loadActivityTime(); taskActivityManager.reloadPlanningData(); if (!activationHistoryFile.exists() && taskActivityManager.getTaskActivationHistory().getSize() == 0) { // fall back to activity history List<ITask> tasks = taskActivityMonitor.getActivationHistory(); for (ITask task : tasks) { taskActivityManager.getTaskActivationHistory().addTask((AbstractTask) task); } } if (!MonitorUiPlugin.getDefault() .getPreferenceStore() .getBoolean(MonitorUiPlugin.ACTIVITY_TRACKING_ENABLED + ".checked")) { //$NON-NLS-1$ if (!taskActivityMonitor.getActivationHistory().isEmpty()) { // tasks have been active before so fore preference enabled MonitorUiPlugin.getDefault().getPreferenceStore().setValue(MonitorUiPlugin.ACTIVITY_TRACKING_ENABLED, true); } MonitorUiPlugin.getDefault() .getPreferenceStore() .setValue(MonitorUiPlugin.ACTIVITY_TRACKING_ENABLED + ".checked", true); //$NON-NLS-1$ MonitorUiPlugin.getDefault().savePluginPreferences(); } // inform listeners that initialization is complete for (final IRepositoryModelListener listener : listeners) { SafeRunner.run(new ISafeRunnable() { public void handleException(Throwable exception) { StatusHandler.log(new Status(IStatus.WARNING, TasksUiPlugin.ID_PLUGIN, "Listener failed: " //$NON-NLS-1$ + listener.getClass(), exception)); } public void run() throws Exception { listener.loaded(); } }); } } @SuppressWarnings("deprecation") private void initializePreferences(IPreferenceStore store) { store.setDefault(ITasksUiPreferenceConstants.PREF_DATA_DIR, getDefaultDataDirectory()); store.setDefault(ITasksUiPreferenceConstants.GROUP_SUBTASKS, true); store.setDefault(ITasksUiPreferenceConstants.NOTIFICATIONS_ENABLED, true); store.setDefault(ITasksUiPreferenceConstants.SERVICE_MESSAGES_ENABLED, false); store.setDefault(ITasksUiPreferenceConstants.FILTER_PRIORITY, PriorityLevel.P5.toString()); store.setDefault(ITasksUiPreferenceConstants.EDITOR_TASKS_RICH, true); store.setDefault(ITasksUiPreferenceConstants.EDITOR_CURRENT_LINE_HIGHLIGHT, false); store.setDefault(ITasksUiPreferenceConstants.ACTIVATE_WHEN_OPENED, false); store.setDefault(ITasksUiPreferenceConstants.SHOW_TRIM, false); // remove preference store.setToDefault(ITasksUiPreferenceConstants.LOCAL_SUB_TASKS_ENABLED); store.setDefault(ITasksUiPreferenceConstants.USE_STRIKETHROUGH_FOR_COMPLETED, true); store.setDefault(ITasksUiPreferenceConstants.REPOSITORY_SYNCH_SCHEDULE_ENABLED, true); store.setDefault(ITasksUiPreferenceConstants.RELEVANT_SYNCH_SCHEDULE_ENABLED, true); store.setDefault(ITasksUiPreferenceConstants.REPOSITORY_SYNCH_SCHEDULE_MILISECONDS, "" + (20 * 60 * 1000)); //$NON-NLS-1$ store.setDefault(ITasksUiPreferenceConstants.RELEVANT_TASKS_SCHEDULE_MILISECONDS, "" + (5 * 60 * 1000)); //$NON-NLS-1$ store.setDefault(ITasksUiPreferenceConstants.BACKUP_MAXFILES, 20); store.setDefault(ITasksUiPreferenceConstants.BACKUP_LAST, 0f); store.setDefault(ITasksUiPreferenceConstants.FILTER_HIDDEN, true); 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(ITasksUiPreferenceConstants.SCHEDULE_NEW_TASKS_FOR, ITasksUiPreferenceConstants.SCHEDULE_NEW_TASKS_FOR_THIS_WEEK); store.setDefault(ITasksUiPreferenceConstants.PLANNING_ENDHOUR, 18); store.setDefault(ITasksUiPreferenceConstants.AUTO_EXPAND_TASK_LIST, true); store.setDefault(ITasksUiPreferenceConstants.TASK_LIST_TOOL_TIPS_ENABLED, true); store.setDefault(ITasksUiPreferenceConstants.SERVICE_MESSAGE_URL, "http://eclipse.org/mylyn/updates.xml"); //$NON-NLS-1$ } 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(ITaskContainer element) { boolean groupSubtasks = TasksUiPlugin.getDefault() .getPreferenceStore() .getBoolean(ITasksUiPreferenceConstants.GROUP_SUBTASKS); if (element instanceof ITask) { AbstractRepositoryConnectorUi connectorUi = TasksUiPlugin .getConnectorUi(((ITask) element).getConnectorKind()); if (connectorUi != null) { if (connectorUi.hasStrictSubtaskHierarchy()) { groupSubtasks = true; } } } if (element instanceof IRepositoryQuery) { AbstractRepositoryConnectorUi connectorUi = TasksUiPlugin .getConnectorUi(((IRepositoryQuery) element).getConnectorKind()); if (connectorUi != null) { if (connectorUi.hasStrictSubtaskHierarchy()) { groupSubtasks = true; } } } return groupSubtasks; } private final Map<String, List<IDynamicSubMenuContributor>> menuContributors = new HashMap<String, List<IDynamicSubMenuContributor>>(); @SuppressWarnings("rawtypes") private ServiceTracker identityServiceTracker; public Map<String, List<IDynamicSubMenuContributor>> getDynamicMenuMap() { return menuContributors; } 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; } /** * @since 3.0 */ public AbstractTaskEditorPageFactory[] getTaskEditorPageFactories() { return taskEditorPageFactories.toArray(new AbstractTaskEditorPageFactory[0]); } /** * @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; } /** * @deprecated Use {@link BrandManager#addDefaultBrandingIcon(String, Image)} instead * @see #getBrandManager() */ @Deprecated public void addBrandingIcon(String repositoryType, Image icon) { brandManager.addDefaultBrandingIcon(repositoryType, icon); } /** * @deprecated Use {@link BrandManager#getDefaultBrandingIcon(String)} instead * @see #getBrandManager() */ @Deprecated public Image getBrandingIcon(String repositoryType) { return brandManager.getDefaultBrandingIcon(repositoryType); } /** * @deprecated Use {@link BrandManager#addDefaultOverlayIcon(String, ImageDescriptor)} instead * @see #getBrandManager() */ @Deprecated public void addOverlayIcon(String repositoryType, ImageDescriptor icon) { brandManager.addDefaultOverlayIcon(repositoryType, icon); } /** * @deprecated Use {@link BrandManager#getDefaultOverlayIcon(String)} instead * @see #getBrandManager() */ @Deprecated public ImageDescriptor getOverlayIcon(String repositoryType) { return brandManager.getDefaultOverlayIcon(repositoryType); } public IBrandManager getBrandManager() { return brandManager; } public void addRepositoryLinkProvider(AbstractTaskRepositoryLinkProvider repositoryLinkProvider) { if (repositoryLinkProvider != null) { this.repositoryLinkProviders.add(repositoryLinkProvider); } } public static synchronized TaskListBackupManager getBackupManager() { if (INSTANCE.taskListBackupManager == null) { INSTANCE.taskListBackupManager = new TaskListBackupManager(INSTANCE.getBackupFolderPath()); INSTANCE.getPreferenceStore().addPropertyChangeListener(INSTANCE.taskListBackupManager); } return INSTANCE.taskListBackupManager; } 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); } /** * @since 3.0 */ public static TaskDataManager getTaskDataManager() { return taskDataManager; } /** * @since 3.0 */ public static TaskJobFactory getTaskJobFactory() { return INSTANCE.taskJobFactory; } 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 void addModelListener(IRepositoryModelListener listener) { listeners.add(listener); } public void removeModelListener(IRepositoryModelListener listener) { listeners.remove(listener); } public boolean canSetRepositoryForResource(final IResource resource) { if (resource == null) { return false; } // if a repository has already been linked only that provider should be queried to ensure that it is the same // provider that is used by getRepositoryForResource() final boolean result[] = new boolean[1]; final boolean found[] = new boolean[1]; for (final AbstractTaskRepositoryLinkProvider linkProvider : repositoryLinkProviders) { SafeRunner.run(new ISafeRunnable() { public void handleException(Throwable e) { StatusHandler.log(new Status(IStatus.ERROR, TasksUiPlugin.ID_PLUGIN, "Task repository link provider failed: \"" + linkProvider.getId() + "\"", e)); //$NON-NLS-1$ //$NON-NLS-2$ } public void run() throws Exception { if (linkProvider.getTaskRepository(resource, getRepositoryManager()) != null) { found[0] = true; result[0] = linkProvider.canSetTaskRepository(resource); } } }); if (found[0]) { return result[0]; } } // find a provider that can set new repository for (final AbstractTaskRepositoryLinkProvider linkProvider : repositoryLinkProviders) { SafeRunner.run(new ISafeRunnable() { public void handleException(Throwable e) { StatusHandler.log(new Status(IStatus.ERROR, TasksUiPlugin.ID_PLUGIN, "Task repository link provider failed: \"" + linkProvider.getId() + "\"", e)); //$NON-NLS-1$ //$NON-NLS-2$ } public void run() throws Exception { if (linkProvider.canSetTaskRepository(resource)) { result[0] = true; } } }); if (result[0]) { 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(final IResource resource, final TaskRepository repository) { Assert.isNotNull(resource); for (final AbstractTaskRepositoryLinkProvider linkProvider : repositoryLinkProviders) { SafeRunner.run(new ISafeRunnable() { public void handleException(Throwable e) { StatusHandler.log(new Status(IStatus.ERROR, TasksUiPlugin.ID_PLUGIN, "Task repository link provider failed: \"" + linkProvider.getId() + "\"", e)); //$NON-NLS-1$ //$NON-NLS-2$ } public void run() throws Exception { boolean canSetRepository = linkProvider.canSetTaskRepository(resource); if (canSetRepository) { linkProvider.setTaskRepository(resource, repository); } } }); } } /** * 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); long timeout; try { timeout = Long.parseLong(System.getProperty(ITasksCoreConstants.PROPERTY_LINK_PROVIDER_TIMEOUT, DEFAULT_LINK_PROVIDER_TIMEOUT + "")); //$NON-NLS-1$ } catch (NumberFormatException e) { timeout = DEFAULT_LINK_PROVIDER_TIMEOUT; } Set<AbstractTaskRepositoryLinkProvider> defectiveLinkProviders = new HashSet<AbstractTaskRepositoryLinkProvider>(); for (final AbstractTaskRepositoryLinkProvider linkProvider : repositoryLinkProviders) { long startTime = System.currentTimeMillis(); final TaskRepository[] repository = new TaskRepository[1]; SafeRunnable.run(new ISafeRunnable() { public void handleException(Throwable e) { StatusHandler.log(new Status(IStatus.ERROR, ID_PLUGIN, "Task repository link provider failed: \"" //$NON-NLS-1$ + linkProvider.getId() + "\"", e)); //$NON-NLS-1$ } public void run() throws Exception { repository[0] = linkProvider.getTaskRepository(resource, getRepositoryManager()); } }); long elapsed = System.currentTimeMillis() - startTime; if (timeout >= 0 && elapsed > timeout) { 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 " + timeout //$NON-NLS-1$ + " ms to execute and was timed out: \"" + defectiveLinkProviders + "\"")); //$NON-NLS-1$ //$NON-NLS-2$ } return null; } public static ExternalizationManager getExternalizationManager() { return externalizationManager; } public static AbstractTaskActivityMonitor getTaskActivityMonitor() { return INSTANCE.taskActivityMonitor; } public static TaskList getTaskList() { return taskList; } public static RepositoryModel getRepositoryModel() { return repositoryModel; } /** * Note: This is provisional API that is used by connectors. * <p> * DO NOT CHANGE. */ public void addSearchHandler(AbstractSearchHandler searchHandler) { searchHandlers.add(searchHandler); } /** * Note: This is provisional API that is used by connectors. * <p> * DO NOT CHANGE. */ 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; } public FormColors getFormColors(Display display) { if (formColors == null) { formColors = new FormColors(display); formColors.markShared(); } return formColors; } public void removeRepositoryLinkProvider(AbstractTaskRepositoryLinkProvider provider) { repositoryLinkProviders.remove(provider); } public TaskListExternalizer createTaskListExternalizer() { return new TaskListExternalizer(repositoryModel, repositoryManager); } public static TaskListExternalizationParticipant getTaskListExternalizationParticipant() { return taskListExternalizationParticipant; } public static TasksUiFactory getUiFactory() { if (uiFactory == null) { uiFactory = new TasksUiFactory(); } return uiFactory; } public void initializeNotificationsAndSynchronization() { // this method is invoked by the tasks ui initialization job and the task list view // only proceed if both calls have been made if (initializationCount.incrementAndGet() != 2) { return; } try { taskListNotificationManager.addNotificationProvider(REMINDER_NOTIFICATION_PROVIDER); // taskListNotificationManager.addNotificationProvider(INCOMING_NOTIFICATION_PROVIDER); TaskListNotifier taskListNotifier = new TaskListNotifier(getTaskDataManager(), getSynchronizationManger()); getTaskDataManager().addListener(taskListNotifier); taskListNotificationManager.addNotificationProvider(taskListNotifier); taskListNotificationManager.startNotification(NOTIFICATION_DELAY); getPreferenceStore().addPropertyChangeListener(taskListNotificationManager); } catch (Throwable t) { StatusHandler .log(new Status(IStatus.ERROR, TasksUiPlugin.ID_PLUGIN, "Could not initialize notifications", t)); //$NON-NLS-1$ } try { // trigger backup scheduler getBackupManager(); synchronizationManager = new TaskListScheduledSynchronizationManager(taskJobFactory, taskActivityManager, repositoryManager); } catch (Throwable t) { StatusHandler.log(new Status(IStatus.ERROR, TasksUiPlugin.ID_PLUGIN, "Could not initialize task list backup and synchronization", t)); //$NON-NLS-1$ } } @SuppressWarnings("restriction") public ServiceMessageManager getServiceMessageManager() { return serviceMessageManager; } public SynchronizationManger getSynchronizationManger() { return synchronizationManger; } @SuppressWarnings({ "rawtypes", "unchecked", "restriction" }) public IIdentityService getIdentityService() { if (identityServiceTracker == null) { identityServiceTracker = new ServiceTracker(getBundle().getBundleContext(), IIdentityService.class.getName(), null); identityServiceTracker.open(); } return (IIdentityService) identityServiceTracker.getService(); } public static synchronized AbstractTaskContextStore getContextStore() { if (contextStore == null) { contextStore = TasksCoreExtensionReader.loadTaskContextStore(); } return contextStore; } }