diff options
author | spingel | 2011-05-29 14:46:11 +0000 |
---|---|---|
committer | spingel | 2011-05-29 14:46:11 +0000 |
commit | 3845075581138bb690843b570f0723ef240f18a3 (patch) | |
tree | d808823a40f2833468081c30e6c0050b5a3878e9 | |
parent | 293e1f6cf4284f2c5465175460e765826637d1c8 (diff) | |
download | org.eclipse.mylyn.tasks-3845075581138bb690843b570f0723ef240f18a3.tar.gz org.eclipse.mylyn.tasks-3845075581138bb690843b570f0723ef240f18a3.tar.xz org.eclipse.mylyn.tasks-3845075581138bb690843b570f0723ef240f18a3.zip |
NEW - bug 339467: [discovery] inform users when new versions or connectors are available
https://bugs.eclipse.org/bugs/show_bug.cgi?id=339467
19 files changed, 909 insertions, 116 deletions
diff --git a/org.eclipse.mylyn.tasks.core/META-INF/MANIFEST.MF b/org.eclipse.mylyn.tasks.core/META-INF/MANIFEST.MF index 604613462..335a58a51 100644 --- a/org.eclipse.mylyn.tasks.core/META-INF/MANIFEST.MF +++ b/org.eclipse.mylyn.tasks.core/META-INF/MANIFEST.MF @@ -19,4 +19,9 @@ Export-Package: org.eclipse.mylyn.internal.provisional.tasks.core;x-internal:=tr org.eclipse.mylyn.tasks.core, org.eclipse.mylyn.tasks.core.data, org.eclipse.mylyn.tasks.core.sync +Import-Package: com.sun.syndication.feed;version="0.9.0";resolution:=optional, + com.sun.syndication.feed.module;version="0.9.0";resolution:=optional, + com.sun.syndication.feed.synd;version="0.9.0";resolution:=optional, + com.sun.syndication.io;version="0.9.0";resolution:=optional, + org.jdom;version="1.0.0";resolution:=optional Bundle-Localization: plugin diff --git a/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/internal/tasks/core/notifications/Environment.java b/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/internal/tasks/core/notifications/Environment.java new file mode 100644 index 000000000..aced0f558 --- /dev/null +++ b/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/internal/tasks/core/notifications/Environment.java @@ -0,0 +1,171 @@ +/******************************************************************************* + * Copyright (c) 2011 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.core.notifications; + +import java.util.Collections; +import java.util.Dictionary; +import java.util.Hashtable; +import java.util.List; +import java.util.Set; + +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.Platform; +import org.eclipse.osgi.service.resolver.VersionRange; +import org.osgi.framework.Bundle; +import org.osgi.framework.Filter; +import org.osgi.framework.FrameworkUtil; +import org.osgi.framework.InvalidSyntaxException; +import org.osgi.framework.Version; + +/** + * @author Steffen Pingel + */ +public class Environment { + + private final Dictionary<Object, Object> environment; + + public Environment() { + environment = new Hashtable<Object, Object>(System.getProperties()); + } + + public Version getFrameworkVersion() { + Bundle bundle = Platform.getBundle("org.eclipse.mylyn"); //$NON-NLS-1$ + if (bundle != null) { + return bundle.getVersion(); + } else { + return Version.emptyVersion; + } + } + + public Version getPlatformVersion() { + Bundle bundle = Platform.getBundle("org.eclipse.platform"); //$NON-NLS-1$ + if (bundle == null) { + bundle = Platform.getBundle(Platform.PI_RUNTIME); + } + if (bundle != null) { + String versionString = bundle.getHeaders().get(org.osgi.framework.Constants.BUNDLE_VERSION); + try { + return new Version(versionString); + } catch (IllegalArgumentException e) { + // should never happen + } + } + return Version.emptyVersion; + } + + public Version getRuntimeVersion() { + Version result = parseRuntimeVersion(System.getProperty("java.runtime.version")); //$NON-NLS-1$ + if (result == Version.emptyVersion) { + result = parseRuntimeVersion(System.getProperty("java.version")); //$NON-NLS-1$ + } + return result; + } + + @SuppressWarnings({ "unchecked", "rawtypes" }) + public boolean matches(FeedEntry entry, IProgressMonitor monitor) { + if (!matchesVersion(entry.getFilter("frameworkVersion"), getFrameworkVersion())) { //$NON-NLS-1$ + return false; + } + if (!matchesVersion(entry.getFilter("platformVersion"), getPlatformVersion())) { //$NON-NLS-1$ + return false; + } + if (!matchesVersion(entry.getFilter("runtimeVersion"), getRuntimeVersion())) { //$NON-NLS-1$ + return false; + } + List<String> filterExpressions = entry.getFilters("filter"); //$NON-NLS-1$ + for (String filterExpression : filterExpressions) { + try { + Filter filter = FrameworkUtil.createFilter(filterExpression); + if (!filter.match((Dictionary) environment)) { + return false; + } + } catch (InvalidSyntaxException e) { + // ignore that filter + } + } + List<String> requiredFeatures = entry.getFilters("requires"); //$NON-NLS-1$ + for (String requiredFeature : requiredFeatures) { + if (!getInstalledFeatures(monitor).contains(parseFeature(requiredFeature))) { + return false; + } + } + List<String> conflictedFeatures = entry.getFilters("conflicts"); //$NON-NLS-1$ + for (String conflictedFeature : conflictedFeatures) { + if (getInstalledFeatures(monitor).contains(parseFeature(conflictedFeature))) { + return false; + } + } + return true; + } + + private int findLastNumberIndex(String versionString, int secondSeparator) { + int lastDigit = secondSeparator; + for (int i = secondSeparator + 1; i < versionString.length(); i++) { + if (Character.isDigit(versionString.charAt(i))) { + lastDigit++; + } else { + break; + } + } + if (lastDigit == secondSeparator) { + return secondSeparator - 1; + } + return lastDigit; + } + + public Set<String> getInstalledFeatures(IProgressMonitor monitor) { + return Collections.emptySet(); + } + + private boolean matchesVersion(String expectedVersionRangeExpression, Version actualVersion) { + if (expectedVersionRangeExpression != null) { + try { + VersionRange versionRange = new VersionRange(expectedVersionRangeExpression); + if (!versionRange.isIncluded(actualVersion)) { + return false; + } + } catch (IllegalArgumentException e) { + // ignore + } + } + return true; + } + + private String parseFeature(String requiredFeature) { + int i = requiredFeature.indexOf(";"); //$NON-NLS-1$ + if (i != -1) { + return requiredFeature.substring(0, i); + } + return requiredFeature; + } + + private Version parseRuntimeVersion(String versionString) { + if (versionString != null) { + int firstSeparator = versionString.indexOf('.'); + if (firstSeparator != -1) { + try { + int secondSeparator = versionString.indexOf('.', firstSeparator + 1); + if (secondSeparator != -1) { + return new Version(versionString.substring(0, + findLastNumberIndex(versionString, secondSeparator) + 1)); + } + return new Version(versionString.substring(0, + findLastNumberIndex(versionString, firstSeparator) + 1)); + } catch (IllegalArgumentException e) { + // ignore + } + } + } + return Version.emptyVersion; + } + +} diff --git a/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/internal/tasks/core/notifications/FeedEntry.java b/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/internal/tasks/core/notifications/FeedEntry.java new file mode 100644 index 000000000..4098c4c88 --- /dev/null +++ b/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/internal/tasks/core/notifications/FeedEntry.java @@ -0,0 +1,107 @@ +/******************************************************************************* + * Copyright (c) 2011 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.core.notifications; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import org.eclipse.core.runtime.Assert; + +import com.sun.syndication.feed.module.DCModule; +import com.sun.syndication.feed.module.DCSubject; +import com.sun.syndication.feed.synd.SyndEntry; + +/** + * @author Steffen Pingel + */ +public class FeedEntry extends ServiceMessage { + + private final SyndEntry source; + + public FeedEntry(SyndEntry source) { + this.source = source; + setId(source.getUri()); + setTitle(source.getTitle()); + if (source.getDescription() != null) { + setDescription(source.getDescription().getValue()); + } + setUrl(source.getLink()); + setImage("dialog_messasge_info_image"); //$NON-NLS-1$ + } + + public FeedEntry() { + this.source = null; + } + + public SyndEntry getSource() { + return source; + } + + public List<String> getFilters(String key) { + Assert.isNotNull(key); + List<String> result = new ArrayList<String>(); + DCModule module = (DCModule) source.getModule(DCModule.URI); + if (module != null && module.getSubjects() != null) { + for (Iterator<?> it = module.getSubjects().iterator(); it.hasNext();) { + DCSubject category = (DCSubject) it.next(); + String value = parseFilter(key, category.getValue()); + if (value != null) { + result.add(value); + } + } + } +// for (Iterator<?> it = source.getCategories().iterator(); it.hasNext();) { +// SyndCategory category = (SyndCategory) it.next(); +// String value = parseFilter(key, category.getName()); +// if (value != null) { +// result.add(value); +// } +// } + return result; + } + + public String getFilter(String key) { + Assert.isNotNull(key); + DCModule module = (DCModule) source.getModule(DCModule.URI); + if (module != null && module.getSubjects() != null) { + for (Iterator<?> it = module.getSubjects().iterator(); it.hasNext();) { + DCSubject category = (DCSubject) it.next(); + String value = parseFilter(key, category.getValue()); + if (value != null) { + return value; + } + } + } +// for (Iterator<?> it = source.getCategories().iterator(); it.hasNext();) { +// SyndCategory category = (SyndCategory) it.next(); +// String value = parseCategory(key, category.getName()); +// if (value != null) { +// return value; +// } +// } + return null; + } + + private String parseFilter(String key, String category) { + if (category != null) { + int i = category.indexOf("="); //$NON-NLS-1$ + if (i != -1) { + if (category.substring(0, i).trim().equals(key)) { + return category.substring(i + 1).trim(); + } + } + } + return null; + } + +} diff --git a/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/internal/tasks/core/notifications/FeedReader.java b/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/internal/tasks/core/notifications/FeedReader.java new file mode 100644 index 000000000..bba4dfc1e --- /dev/null +++ b/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/internal/tasks/core/notifications/FeedReader.java @@ -0,0 +1,65 @@ +/******************************************************************************* + * Copyright (c) 2011 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.core.notifications; + +import java.io.InputStream; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.mylyn.internal.tasks.core.ITasksCoreConstants; + +import com.sun.syndication.feed.synd.SyndEntry; +import com.sun.syndication.feed.synd.SyndFeed; +import com.sun.syndication.io.SyndFeedInput; +import com.sun.syndication.io.XmlReader; + +/** + * @author Steffen Pingel + */ +public class FeedReader { + + private final Environment environment; + + private final List<FeedEntry> entries; + + public FeedReader(Environment environment) { + this.environment = environment; + this.entries = new ArrayList<FeedEntry>(); + } + + public IStatus parse(InputStream in, IProgressMonitor monitor) { + SyndFeedInput input = new SyndFeedInput(); + try { + SyndFeed feed = input.build(new XmlReader(in)); + for (Iterator<?> it = feed.getEntries().iterator(); it.hasNext();) { + SyndEntry syndEntry = (SyndEntry) it.next(); + FeedEntry entry = new FeedEntry(syndEntry); + if (environment.matches(entry, monitor)) { + entries.add(entry); + } + } + return Status.OK_STATUS; + } catch (Exception e) { + return new Status(IStatus.ERROR, ITasksCoreConstants.ID_PLUGIN, IStatus.ERROR, + "Failed to parse RSS feed", e); //$NON-NLS-1$ + } + } + + public List<FeedEntry> getEntries() { + return entries; + } + +} diff --git a/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/internal/tasks/core/notifications/ServiceMessage.java b/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/internal/tasks/core/notifications/ServiceMessage.java index 4b96603bd..144e82d7a 100644 --- a/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/internal/tasks/core/notifications/ServiceMessage.java +++ b/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/internal/tasks/core/notifications/ServiceMessage.java @@ -14,10 +14,10 @@ package org.eclipse.mylyn.internal.tasks.core.notifications; /** * @author Robert Elves */ -public class ServiceMessage { +public class ServiceMessage implements Comparable<ServiceMessage> { public enum Element { - ID, TITLE, DESCRIPTION, URL, IMAGE, VERSION + ID, TITLE, DESCRIPTION, URL, IMAGE }; private String id; @@ -30,8 +30,6 @@ public class ServiceMessage { private String image; - private String version; - private String eTag; private String lastModified; @@ -72,10 +70,6 @@ public class ServiceMessage { return lastModified; } - public String getVersion() { - return version; - } - public void setId(String id) { this.id = id; } @@ -96,12 +90,33 @@ public class ServiceMessage { this.image = image; } - public void setVersion(String version) { - this.version = version; - } - public boolean isValid() { return id != null && title != null && description != null && image != null; } + public int compareTo(ServiceMessage o) { + return -getId().compareTo(o.getId()); + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("ServiceMessage [id="); //$NON-NLS-1$ + builder.append(id); + builder.append(", title="); //$NON-NLS-1$ + builder.append(title); + builder.append(", description="); //$NON-NLS-1$ + builder.append(description); + builder.append(", url="); //$NON-NLS-1$ + builder.append(url); + builder.append(", image="); //$NON-NLS-1$ + builder.append(image); + builder.append(", eTag="); //$NON-NLS-1$ + builder.append(eTag); + builder.append(", lastModified="); //$NON-NLS-1$ + builder.append(lastModified); + builder.append("]"); //$NON-NLS-1$ + return builder.toString(); + } + } diff --git a/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/internal/tasks/core/notifications/ServiceMessageManager.java b/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/internal/tasks/core/notifications/ServiceMessageManager.java index adc0a381d..8c19a2ef5 100644 --- a/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/internal/tasks/core/notifications/ServiceMessageManager.java +++ b/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/internal/tasks/core/notifications/ServiceMessageManager.java @@ -8,16 +8,13 @@ package org.eclipse.mylyn.internal.tasks.core.notifications; +import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; import java.util.Collections; -import java.util.Date; import java.util.List; import java.util.concurrent.CopyOnWriteArrayList; -import javax.xml.parsers.SAXParser; -import javax.xml.parsers.SAXParserFactory; - import org.apache.commons.httpclient.Header; import org.apache.commons.httpclient.HostConfiguration; import org.apache.commons.httpclient.HttpClient; @@ -45,11 +42,11 @@ public class ServiceMessageManager { protected static final long START_DELAY = 30 * 1000; - protected static final long RECHECK_DELAY = 24 * 60 * 60 * 1000; + protected static final long RECHECK_DELAY = 14 * 24 * 60 * 60 * 1000; private String serviceMessageUrl; - private volatile List<ServiceMessage> messages = Collections.emptyList(); + private volatile List<? extends ServiceMessage> messages = Collections.emptyList(); private Job messageCheckJob; @@ -63,11 +60,19 @@ public class ServiceMessageManager { private final long checktime; - public ServiceMessageManager(String serviceMessageUrl, String lastModified, String eTag, long checktime) { + private final Environment environment; + + public ServiceMessageManager(String serviceMessageUrl, String lastModified, String eTag, long checktime, + Environment environment) { this.serviceMessageUrl = serviceMessageUrl; this.lastModified = lastModified; this.checktime = checktime; this.eTag = eTag; + this.environment = environment; + } + + public ServiceMessageManager(String serviceMessageUrl, String lastModified, String eTag, long checktime) { + this(serviceMessageUrl, lastModified, eTag, checktime, new Environment()); } public void start() { @@ -75,8 +80,13 @@ public class ServiceMessageManager { messageCheckJob = new Job("Checking for new service message") { //$NON-NLS-1$ @Override protected IStatus run(IProgressMonitor monitor) { - updateServiceMessage(monitor); - return Status.OK_STATUS; + try { + updateServiceMessage(monitor); + return Status.OK_STATUS; + } catch (Throwable t) { + // fail silently + return Status.CANCEL_STATUS; + } } }; @@ -95,18 +105,17 @@ public class ServiceMessageManager { messageCheckJob.schedule(START_DELAY); } else { long nextCheckTime = checktime + RECHECK_DELAY; - long now = new Date().getTime(); + long now = System.currentTimeMillis(); if (nextCheckTime < now) { messageCheckJob.schedule(START_DELAY); } else if (nextCheckTime > now) { - if ((nextCheckTime - now) < START_DELAY) { + if (nextCheckTime - now < START_DELAY) { messageCheckJob.schedule(START_DELAY); } else { messageCheckJob.schedule(nextCheckTime - now); } } } - } public void stop() { @@ -143,16 +152,17 @@ public class ServiceMessageManager { listeners.remove(listener); } - private void notifyListeners(List<ServiceMessage> messages) { + private void notifyListeners(List<? extends ServiceMessage> messages) { this.messages = messages; for (final ServiceMessage message : messages) { message.setETag(eTag); message.setLastModified(lastModified); } + ArrayList<ServiceMessage> sortedMessages = new ArrayList<ServiceMessage>(messages); + Collections.sort(messages); final ServiceMessageEvent event = new ServiceMessageEvent(this, ServiceMessageEvent.EVENT_KIND.MESSAGE_UPDATE, - messages); - + sortedMessages); for (final IServiceMessageListener listener : listeners) { SafeRunner.run(new ISafeRunnable() { public void run() throws Exception { @@ -176,7 +186,7 @@ public class ServiceMessageManager { */ public int updateServiceMessage(IProgressMonitor monitor) { int status = -1; - List<ServiceMessage> messages = null; + List<? extends ServiceMessage> messages = null; try { HttpClient httpClient = new HttpClient(WebUtil.getConnectionManager()); WebUtil.configureHttpClient(httpClient, null); @@ -203,13 +213,7 @@ public class ServiceMessageManager { InputStream in = WebUtil.getResponseBodyAsStream(method, monitor); try { - SAXParserFactory factory = SAXParserFactory.newInstance(); - factory.setValidating(false); - SAXParser parser = factory.newSAXParser(); - - ServiceMessageXmlHandler handler = new ServiceMessageXmlHandler(); - parser.parse(in, handler); - messages = handler.getMessages(); + messages = readMessages(in, monitor); } finally { in.close(); } @@ -218,21 +222,15 @@ public class ServiceMessageManager { } else if (status == HttpStatus.SC_NOT_MODIFIED) { // no new messages } else { - if (!statusLogged) { - statusLogged = true; - StatusHandler.log(new Status(IStatus.WARNING, ITasksCoreConstants.ID_PLUGIN, - "Http error retrieving service message: " + HttpStatus.getStatusText(status))); //$NON-NLS-1$ - } + logStatus(new Status(IStatus.WARNING, ITasksCoreConstants.ID_PLUGIN, + "Http error retrieving service message: " + HttpStatus.getStatusText(status))); //$NON-NLS-1$ } } finally { WebUtil.releaseConnection(method, monitor); } } catch (Exception e) { - if (!statusLogged) { - statusLogged = true; - StatusHandler.log(new Status(IStatus.WARNING, ITasksCoreConstants.ID_PLUGIN, - "Http error retrieving service message.", e)); //$NON-NLS-1$ - } + logStatus(new Status(IStatus.WARNING, ITasksCoreConstants.ID_PLUGIN, + "Http error retrieving service message.", e)); //$NON-NLS-1$ } if (messages != null && messages.size() > 0) { @@ -241,4 +239,28 @@ public class ServiceMessageManager { return status; } + private void logStatus(IStatus status) { + if (!statusLogged) { + statusLogged = true; + //StatusHandler.log(status); + } + } + +// private List<ServiceMessage> readMessages(InputStream in) throws ParserConfigurationException, SAXException, +// IOException { +// SAXParserFactory factory = SAXParserFactory.newInstance(); +// factory.setValidating(false); +// SAXParser parser = factory.newSAXParser(); +// +// ServiceMessageXmlHandler handler = new ServiceMessageXmlHandler(); +// parser.parse(in, handler); +// return handler.getMessages(); +// } + + private List<? extends ServiceMessage> readMessages(InputStream in, IProgressMonitor monitor) throws IOException { + FeedReader reader = new FeedReader(environment); + reader.parse(in, monitor); + return reader.getEntries(); + } + } diff --git a/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/internal/tasks/core/notifications/ServiceMessageXmlHandler.java b/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/internal/tasks/core/notifications/ServiceMessageXmlHandler.java index 3ba14985c..27b5fa6fe 100644 --- a/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/internal/tasks/core/notifications/ServiceMessageXmlHandler.java +++ b/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/internal/tasks/core/notifications/ServiceMessageXmlHandler.java @@ -75,9 +75,6 @@ public class ServiceMessageXmlHandler extends DefaultHandler { case IMAGE: message.setImage(parsedText); break; - case VERSION: - message.setVersion(parsedText); - break; } } catch (IllegalArgumentException e) { // ignore unrecognized elements diff --git a/org.eclipse.mylyn.tasks.tests/META-INF/MANIFEST.MF b/org.eclipse.mylyn.tasks.tests/META-INF/MANIFEST.MF index bc0ef9598..7cea214a0 100644 --- a/org.eclipse.mylyn.tasks.tests/META-INF/MANIFEST.MF +++ b/org.eclipse.mylyn.tasks.tests/META-INF/MANIFEST.MF @@ -33,10 +33,12 @@ Require-Bundle: org.eclipse.core.runtime, org.eclipse.equinox.security, org.eclipse.mylyn.tests.util, org.eclipse.mylyn.tasks.search +Import-Package: com.sun.syndication.feed.synd;version="0.9.0";resolution:=optional Export-Package: org.eclipse.mylyn.tasks.tests;x-internal:=true, org.eclipse.mylyn.tasks.tests.connector;x-internal:=true, org.eclipse.mylyn.tasks.tests.core;x-internal:=true, org.eclipse.mylyn.tasks.tests.data;x-internal:=true, + org.eclipse.mylyn.tasks.tests.support;x-internal:=true, org.eclipse.mylyn.tasks.tests.ui;x-internal:=true, org.eclipse.mylyn.tasks.tests.ui.editor;x-internal:=true, org.eclipse.mylyn.tasks.tests.util;x-internal:=true diff --git a/org.eclipse.mylyn.tasks.tests/src/org/eclipse/mylyn/tasks/tests/core/EnvironmentTest.java b/org.eclipse.mylyn.tasks.tests/src/org/eclipse/mylyn/tasks/tests/core/EnvironmentTest.java new file mode 100644 index 000000000..bc90e9034 --- /dev/null +++ b/org.eclipse.mylyn.tasks.tests/src/org/eclipse/mylyn/tasks/tests/core/EnvironmentTest.java @@ -0,0 +1,142 @@ +/******************************************************************************* + * Copyright (c) 2011 Tasktop Technologies. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Tasktop Technologies - initial API and implementation + *******************************************************************************/ + +package org.eclipse.mylyn.tasks.tests.core; + +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import junit.framework.TestCase; + +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.Platform; +import org.eclipse.mylyn.internal.tasks.core.notifications.Environment; +import org.eclipse.mylyn.internal.tasks.core.notifications.FeedEntry; +import org.eclipse.osgi.service.resolver.VersionRange; +import org.osgi.framework.Version; + +/** + * @author Steffen Pingel + */ +public class EnvironmentTest extends TestCase { + + private class StubEntry extends FeedEntry { + + private final Map<String, String> map; + + public StubEntry(Map<String, String> map) { + this.map = map; + } + + @Override + public List<String> getFilters(String key) { + String value = getFilter(key); + if (value != null) { + return Collections.singletonList(value); + } + return Collections.emptyList(); + } + + @Override + public String getFilter(String key) { + return map.get(key); + } + + } + + private Environment environment; + + Set<String> installedFeatures; + + @Override + protected void setUp() throws Exception { + installedFeatures = new HashSet<String>(); + environment = new Environment() { + @Override + public Set<String> getInstalledFeatures(IProgressMonitor monitor) { + return installedFeatures; + } + }; + } + + public void testGetRuntimeVersion() { + Version runtimeVersion = environment.getRuntimeVersion(); + assertTrue("Expected value between 1.5-1.8, got " + runtimeVersion, + new VersionRange("[1.5.0,1.8.0)").isIncluded(runtimeVersion)); + } + + public void testGetPlatformVersion() { + Version platformVersion = environment.getPlatformVersion(); + if (Platform.isRunning()) { + assertTrue("Expected value between 3.4-5.0, got " + platformVersion, + new VersionRange("[3.4.0,5.0.0)").isIncluded(platformVersion)); + } else { + assertEquals(Version.emptyVersion, platformVersion); + } + } + + public void testGetFrameworkVersion() { + Version frameworkVersion = environment.getFrameworkVersion(); + if (Platform.isRunning()) { + assertTrue("Expected value > 3.6, got " + frameworkVersion, + new VersionRange("3.6.0").isIncluded(frameworkVersion)); + } else { + assertEquals(Version.emptyVersion, frameworkVersion); + } + } + + public void testMatchesFrameworkVersion() { + Map<String, String> values = new HashMap<String, String>(); + assertTrue(environment.matches(new StubEntry(values), null)); + + values.put("frameworkVersion", "[1.0.0,2.0.0)"); + assertFalse(environment.matches(new StubEntry(values), null)); + + values.put("frameworkVersion", "[0.0.0,10.0.0)"); + assertTrue(environment.matches(new StubEntry(values), null)); + } + + public void testMatchesRequires() { + Map<String, String> values = new HashMap<String, String>(); + values.put("requires", "org.eclipse.mylyn"); + assertFalse(environment.matches(new StubEntry(values), null)); + + installedFeatures.add("org.eclipse.mylyn"); + assertTrue(environment.matches(new StubEntry(values), null)); + } + + public void testMatchesConflicts() { + Map<String, String> values = new HashMap<String, String>(); + values.put("conflicts", "org.eclipse.mylyn"); + assertTrue(environment.matches(new StubEntry(values), null)); + + installedFeatures.add("org.eclipse.mylyn"); + assertFalse(environment.matches(new StubEntry(values), null)); + } + + public void testMatchesRequiresConflicts() { + Map<String, String> values = new HashMap<String, String>(); + values.put("requires", "org.eclipse.mylyn"); + values.put("conflicts", "org.eclipse.cdt"); + assertFalse(environment.matches(new StubEntry(values), null)); + + installedFeatures.add("org.eclipse.mylyn"); + assertTrue(environment.matches(new StubEntry(values), null)); + + installedFeatures.add("org.eclipse.cdt"); + assertFalse(environment.matches(new StubEntry(values), null)); + } + +} diff --git a/org.eclipse.mylyn.tasks.tests/src/org/eclipse/mylyn/tasks/tests/core/FeedReaderTest.java b/org.eclipse.mylyn.tasks.tests/src/org/eclipse/mylyn/tasks/tests/core/FeedReaderTest.java new file mode 100644 index 000000000..a42345a89 --- /dev/null +++ b/org.eclipse.mylyn.tasks.tests/src/org/eclipse/mylyn/tasks/tests/core/FeedReaderTest.java @@ -0,0 +1,66 @@ +/******************************************************************************* + * Copyright (c) 2011 Tasktop Technologies. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Tasktop Technologies - initial API and implementation + *******************************************************************************/ + +package org.eclipse.mylyn.tasks.tests.core; + +import java.util.Collections; +import java.util.Set; + +import junit.framework.TestCase; + +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.Status; +import org.eclipse.mylyn.commons.tests.support.CommonTestUtil; +import org.eclipse.mylyn.internal.tasks.core.notifications.Environment; +import org.eclipse.mylyn.internal.tasks.core.notifications.FeedEntry; +import org.eclipse.mylyn.internal.tasks.core.notifications.FeedReader; + +/** + * @author Steffen Pingel + */ +public class FeedReaderTest extends TestCase { + + private FeedReader reader; + + private Environment environment; + + @Override + protected void setUp() throws Exception { + environment = new Environment() { + @Override + public Set<String> getInstalledFeatures(IProgressMonitor monitor) { + return Collections.singleton("org.eclipse.mylyn"); + } + }; + reader = new FeedReader(environment); + } + + public void testParse() throws Exception { + assertEquals(Status.OK_STATUS, reader.parse( + CommonTestUtil.getResource(FeedReaderTest.class, "testdata/FeedReaderTest/update1.xml"), null)); + assertEquals(2, reader.getEntries().size()); + Collections.sort(reader.getEntries()); + + FeedEntry entry = reader.getEntries().get(0); + assertEquals("New Connectors", entry.getTitle()); + assertEquals("[0.0.0,3.7.0)", entry.getFilter("frameworkVersion")); + assertEquals("New connectors are now available. <a href=\"#discovery\">Show connectors</a>.", + entry.getDescription()); + + entry = reader.getEntries().get(1); + assertEquals("Mylyn 3.6 is now available", entry.getTitle()); + assertEquals("1.5.0", entry.getFilter("runtimeVersion")); + assertEquals( + "Mylyn 3.7 is now available. <a href=\"http://eclipse.org/mylyn/new/\">See New and Noteworthy</a> for details.", + entry.getDescription()); + } + +} diff --git a/org.eclipse.mylyn.tasks.tests/src/org/eclipse/mylyn/tasks/tests/ui/TaskListServiceMessageControlTest.java b/org.eclipse.mylyn.tasks.tests/src/org/eclipse/mylyn/tasks/tests/ui/TaskListServiceMessageControlTest.java new file mode 100644 index 000000000..b8edda030 --- /dev/null +++ b/org.eclipse.mylyn.tasks.tests/src/org/eclipse/mylyn/tasks/tests/ui/TaskListServiceMessageControlTest.java @@ -0,0 +1,31 @@ +/******************************************************************************* + * Copyright (c) 2011 Tasktop Technologies. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Tasktop Technologies - initial API and implementation + *******************************************************************************/ + +package org.eclipse.mylyn.tasks.tests.ui; + +import junit.framework.TestCase; + +import org.eclipse.mylyn.internal.tasks.ui.notifications.TaskListServiceMessageControl; + +/** + * @author Steffen Pingel + */ +public class TaskListServiceMessageControlTest extends TestCase { + + public void testGetAction() { + assertEquals("abc", TaskListServiceMessageControl.getAction("ABC")); + assertEquals("abc", TaskListServiceMessageControl.getAction("abc")); + assertEquals("def", TaskListServiceMessageControl.getAction("http://eclipse.org?action=DEF")); + assertEquals("defg", TaskListServiceMessageControl.getAction("http://eclipse.org?action=defg&foo=bar")); + assertEquals(null, TaskListServiceMessageControl.getAction("http://eclipse.org?foo=bar&action=defg")); + } + +} diff --git a/org.eclipse.mylyn.tasks.tests/testdata/FeedReaderTest/update1.xml b/org.eclipse.mylyn.tasks.tests/testdata/FeedReaderTest/update1.xml new file mode 100644 index 000000000..47fbb4af3 --- /dev/null +++ b/org.eclipse.mylyn.tasks.tests/testdata/FeedReaderTest/update1.xml @@ -0,0 +1,41 @@ +<?xml version="1.0" encoding="UTF-8"?> +<rss version="2.0" + xmlns:dc="http://purl.org/dc/elements/1.1/" + > +<channel> +<title>Mylyn Updates</title> +<link>http://eclipse.org/mylyn</link> +<description>Mylyn Updates</description> +<lastBuildDate>Fri, 27 May 2011 17:33:37 +0000</lastBuildDate> +<language>en</language> +<item> +<title>Mylyn 3.6 is now available</title> +<link>http://eclipse.org/mylyn/new/</link> +<pubDate>Thu, 24 Mar 2011 14:00:07 +0000</pubDate> +<dc:creator>Steffen Pingel</dc:creator> +<dc:subject>runtimeVersion=1.5.0</dc:subject> +<dc:subject>requires=org.eclipse.mylyn</dc:subject> +<category>Mylyn</category> +<guid isPermaLink="false">20110527-0000</guid> +<description>Mylyn 3.7 is now available. <a href="http://eclipse.org/mylyn/new/">See New and Noteworthy</a> for details.</description> +</item> +<item> +<title>New Connectors</title> +<link>http://eclipse.org/mylyn/new/</link> +<pubDate>Fri, 27 May 2011 12:00:00 +0000</pubDate> +<dc:creator>Steffen Pingel</dc:creator> +<dc:subject>frameworkVersion=[0.0.0,3.7.0)</dc:subject> +<guid isPermaLink="false">20110527-0001</guid> +<description>New connectors are now available. <a href="#discovery">Show connectors</a>.</description> +</item> +<item> +<title>Filtered Item</title> +<link>http://eclipse.org/mylyn/new/</link> +<pubDate>Fri, 27 May 2011 12:00:00 +0000</pubDate> +<dc:creator>Steffen Pingel</dc:creator> +<dc:subject>frameworkVersion=[1.0.0,2.0.0)</dc:subject> +<guid isPermaLink="false">20110527-0002</guid> +<description>Specifies an unsatisfiable framework version.</description> +</item> +</channel> +</rss> diff --git a/org.eclipse.mylyn.tasks.ui/META-INF/MANIFEST.MF b/org.eclipse.mylyn.tasks.ui/META-INF/MANIFEST.MF index e032f10f7..6a1ef30b2 100644 --- a/org.eclipse.mylyn.tasks.ui/META-INF/MANIFEST.MF +++ b/org.eclipse.mylyn.tasks.ui/META-INF/MANIFEST.MF @@ -26,7 +26,8 @@ Require-Bundle: org.eclipse.ui, org.eclipse.mylyn.commons.net;bundle-version="[3.0.0,4.0.0)", org.eclipse.mylyn.commons.ui;bundle-version="[3.0.0,4.0.0)", org.eclipse.mylyn.monitor.core;bundle-version="[3.0.0,4.0.0)", - org.eclipse.mylyn.commons.repositories;bundle-version="0.1.0" + org.eclipse.mylyn.commons.repositories;bundle-version="0.1.0", + org.eclipse.mylyn.discovery.ui;bundle-version="3.6.0";resolution:=optional Bundle-ActivationPolicy: lazy Bundle-Vendor: %Bundle-Vendor Export-Package: org.eclipse.mylyn.internal.provisional.tasks.ui.wizards;x-internal:=true, diff --git a/org.eclipse.mylyn.tasks.ui/plugin.xml b/org.eclipse.mylyn.tasks.ui/plugin.xml index b683f884e..c9316d897 100644 --- a/org.eclipse.mylyn.tasks.ui/plugin.xml +++ b/org.eclipse.mylyn.tasks.ui/plugin.xml @@ -2105,5 +2105,27 @@ </toolbar> </menuContribution> </extension> - + <extension + point="org.eclipse.ui.commands"> + <command + description="%command.description" + id="org.eclipse.mylyn.tasks.ui.discoveryWizardCommand" + name="%command.name"> + </command> + </extension> + <extension + point="org.eclipse.ui.handlers"> + <handler + class="org.eclipse.mylyn.internal.tasks.ui.commands.ShowTasksConnectorDiscoveryWizardCommandHandler" + commandId="org.eclipse.mylyn.tasks.ui.discoveryWizardCommand"> + <enabledWhen> + <and> + <test + property="org.eclipse.core.runtime.isBundleInstalled" args="org.eclipse.mylyn.discovery.ui"/> + <test + property="org.eclipse.core.runtime.isBundleInstalled" args="org.eclipse.equinox.p2.repository"/> + </and> + </enabledWhen> + </handler> + </extension> </plugin> diff --git a/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/TasksUiPlugin.java b/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/TasksUiPlugin.java index 71ae0d530..fc0893f22 100644 --- a/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/TasksUiPlugin.java +++ b/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/TasksUiPlugin.java @@ -58,6 +58,7 @@ import org.eclipse.mylyn.internal.commons.identity.IdentityModel; import org.eclipse.mylyn.internal.commons.identity.gravatar.GravatarConnector; import org.eclipse.mylyn.internal.commons.ui.TaskBarManager; import org.eclipse.mylyn.internal.context.core.ContextCorePlugin; +import org.eclipse.mylyn.internal.discovery.ui.DiscoveryUi; import org.eclipse.mylyn.internal.monitor.ui.MonitorUiPlugin; import org.eclipse.mylyn.internal.provisional.commons.ui.AbstractNotification; import org.eclipse.mylyn.internal.provisional.commons.ui.CommonColors; @@ -83,6 +84,7 @@ import org.eclipse.mylyn.internal.tasks.core.externalization.ExternalizationMana 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.core.notifications.Environment; import org.eclipse.mylyn.internal.tasks.core.notifications.ServiceMessageManager; import org.eclipse.mylyn.internal.tasks.ui.actions.ActivateTaskDialogAction; import org.eclipse.mylyn.internal.tasks.ui.actions.NewTaskAction; @@ -666,12 +668,23 @@ public class TasksUiPlugin extends AbstractUIPlugin { Long checktime = getPreferenceStore().getLong(ITasksUiPreferenceConstants.LAST_SERVICE_MESSAGE_CHECKTIME); - serviceMessageManager = new ServiceMessageManager(serviceMessageUrl, lastMod, etag, checktime); + serviceMessageManager = new ServiceMessageManager(serviceMessageUrl, lastMod, etag, checktime, + new Environment() { + 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(); -// } + if (getPreferenceStore().getBoolean(ITasksUiPreferenceConstants.SERVICE_MESSAGES_ENABLED)) { + serviceMessageManager.start(); + } // trigger lazy initialization new TasksUiInitializationJob().schedule(); @@ -943,7 +956,7 @@ public class TasksUiPlugin extends AbstractUIPlugin { 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, 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); @@ -972,7 +985,7 @@ public class TasksUiPlugin extends AbstractUIPlugin { 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/message.xml"); //$NON-NLS-1$ + store.setDefault(ITasksUiPreferenceConstants.SERVICE_MESSAGE_URL, "http://eclipse.org/mylyn/updates.xml"); //$NON-NLS-1$ } public static TaskActivityManager getTaskActivityManager() { diff --git a/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/commands/ShowTasksConnectorDiscoveryWizardCommandHandler.java b/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/commands/ShowTasksConnectorDiscoveryWizardCommandHandler.java new file mode 100644 index 000000000..970b0b553 --- /dev/null +++ b/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/commands/ShowTasksConnectorDiscoveryWizardCommandHandler.java @@ -0,0 +1,76 @@ +/******************************************************************************* + * Copyright (c) 2009 Tasktop Technologies. + * 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.commands; + +import org.eclipse.core.commands.AbstractHandler; +import org.eclipse.core.commands.ExecutionEvent; +import org.eclipse.core.commands.ExecutionException; +import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.jface.resource.JFaceResources; +import org.eclipse.jface.wizard.WizardDialog; +import org.eclipse.mylyn.internal.discovery.ui.wizards.ConnectorDiscoveryWizard; +import org.eclipse.mylyn.internal.provisional.commons.ui.WorkbenchUtil; +import org.eclipse.mylyn.internal.tasks.ui.ITasksUiPreferenceConstants; +import org.eclipse.mylyn.internal.tasks.ui.TasksUiPlugin; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.SelectionAdapter; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; + +/** + * A command that causes the {@link ConnectorDiscoveryWizard} to appear in a dialog. + * + * @author David Green + * @author Steffen Pingel + */ +public class ShowTasksConnectorDiscoveryWizardCommandHandler extends AbstractHandler { + + private static final String ID_P2_INSTALL_UI = "org.eclipse.equinox.p2.ui.sdk/org.eclipse.equinox.p2.ui.sdk.install"; //$NON-NLS-1$ + + public Object execute(ExecutionEvent event) throws ExecutionException { + + // check to make sure that the p2 install ui is enabled + if (WorkbenchUtil.allowUseOf(ID_P2_INSTALL_UI)) { + ConnectorDiscoveryWizard wizard = new ConnectorDiscoveryWizard(); + WizardDialog dialog = new WizardDialog(WorkbenchUtil.getShell(), wizard) { + @Override + protected void createButtonsForButtonBar(Composite parent) { + super.createButtonsForButtonBar(parent); + ((GridLayout) parent.getLayout()).numColumns++; + final Button button = new Button(parent, SWT.CHECK); + button.setSelection(TasksUiPlugin.getDefault() + .getPreferenceStore() + .getBoolean(ITasksUiPreferenceConstants.SERVICE_MESSAGES_ENABLED)); + button.setText("Notify when new connectors are available"); + button.setFont(JFaceResources.getDialogFont()); + button.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent event) { + TasksUiPlugin.getDefault() + .getPreferenceStore() + .setValue(ITasksUiPreferenceConstants.SERVICE_MESSAGES_ENABLED, + button.getSelection()); + } + }); + button.moveAbove(null); + } + }; + dialog.open(); + } else { + MessageDialog.openWarning(WorkbenchUtil.getShell(), "Install Connectors", + "Unable to launch connector install since the required platform support is not available."); + } + + return null; + } +} diff --git a/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/notifications/TaskListServiceMessageControl.java b/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/notifications/TaskListServiceMessageControl.java index 6c6ce2a0d..d4c3f996a 100644 --- a/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/notifications/TaskListServiceMessageControl.java +++ b/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/notifications/TaskListServiceMessageControl.java @@ -12,6 +12,8 @@ package org.eclipse.mylyn.internal.tasks.ui.notifications; +import java.net.MalformedURLException; +import java.net.URL; import java.util.Collections; import java.util.Date; @@ -29,10 +31,10 @@ import org.eclipse.mylyn.internal.tasks.core.notifications.ServiceMessageEvent; import org.eclipse.mylyn.internal.tasks.ui.ITasksUiPreferenceConstants; import org.eclipse.mylyn.internal.tasks.ui.TasksUiPlugin; import org.eclipse.mylyn.internal.tasks.ui.actions.AddRepositoryAction; +import org.eclipse.mylyn.internal.tasks.ui.preferences.TasksUiPreferencePage; import org.eclipse.mylyn.internal.tasks.ui.util.TasksUiInternal; import org.eclipse.mylyn.internal.tasks.ui.wizards.Messages; import org.eclipse.mylyn.tasks.ui.TasksUiUtil; -import org.eclipse.osgi.service.resolver.VersionRange; import org.eclipse.osgi.util.NLS; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; @@ -41,7 +43,6 @@ import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Display; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.handlers.IHandlerService; -import org.osgi.framework.Version; /** * @author Robert Elves @@ -54,6 +55,7 @@ public class TaskListServiceMessageControl extends ServiceMessageControl impleme public TaskListServiceMessageControl(Composite parent) { super(parent); + setPreferencesPageId(TasksUiPreferencePage.ID); } static ExecutionEvent createExecutionEvent(Command command, IHandlerService handlerService) { @@ -83,12 +85,15 @@ public class TaskListServiceMessageControl extends ServiceMessageControl impleme continue; } - if (!lastMessageId.equals(message.getId()) && isForCurrentVersion(message)) { + if (message.getId().compareTo(lastMessageId) > 0) { Display.getDefault().asyncExec(new Runnable() { public void run() { setMessage(message); + // event id is not used but must be set to make configure link visible + setEventId(""); //$NON-NLS-1$ } }); + break; } } break; @@ -98,21 +103,6 @@ public class TaskListServiceMessageControl extends ServiceMessageControl impleme } } - private boolean isForCurrentVersion(ServiceMessage message) { - if (message.getVersion() == null) { - return true; - } - - try { - VersionRange version = new VersionRange(message.getVersion()); - String versionString = (String) TasksUiPlugin.getDefault().getBundle().getHeaders().get("Bundle-Version"); //$NON-NLS-1$ - return version.isIncluded(new Version(versionString)); - } catch (IllegalArgumentException e) { - // invalid version range - return false; - } - } - public void setMessage(ServiceMessage message) { if (message != null) { ensureControl(); @@ -126,8 +116,8 @@ public class TaskListServiceMessageControl extends ServiceMessageControl impleme this.currentMessage = message; setTitle(message.getTitle()); - setDescription(message.getDescription()); setTitleImage(Dialog.getImage(message.getImage())); + setDescription(message.getDescription()); } } @@ -136,35 +126,67 @@ public class TaskListServiceMessageControl extends ServiceMessageControl impleme return new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { - if (e.text != null) { - String action = e.text.toLowerCase(); - if ("create-local-task".equals(action)) { //$NON-NLS-1$ - closeMessage(); - LocalTask task = TasksUiInternal.createNewLocalTask(null); - TasksUiUtil.openTask(task); - } else if ("connect".equals(action)) { //$NON-NLS-1$ - closeMessage(); - new AddRepositoryAction().run(); - } else if ("discovery".equals(action)) { //$NON-NLS-1$ - closeMessage(); - final Command discoveryWizardCommand = TasksUiInternal.getConfiguredDiscoveryWizardCommand(); - if (discoveryWizardCommand != null && discoveryWizardCommand.isEnabled()) { - IHandlerService handlerService = (IHandlerService) PlatformUI.getWorkbench().getService( - IHandlerService.class); - try { - handlerService.executeCommand(discoveryWizardCommand.getId(), null); - } catch (Exception e1) { - IStatus status = new Status(IStatus.ERROR, TasksUiPlugin.ID_PLUGIN, NLS.bind( - Messages.SelectRepositoryConnectorPage_discoveryProblemMessage, - new Object[] { e1.getMessage() }), e1); - TasksUiInternal.logAndDisplayStatus( - Messages.SelectRepositoryConnectorPage_discoveryProblemTitle, status); - } + if (e.text == null) { + return; + } + + String action = getAction(e.text); + if ("create-local-task".equals(action)) { //$NON-NLS-1$ + closeMessage(); + LocalTask task = TasksUiInternal.createNewLocalTask(null); + TasksUiUtil.openTask(task); + } else if ("connect".equals(action)) { //$NON-NLS-1$ + closeMessage(); + new AddRepositoryAction().run(); + } else if ("discovery".equals(action)) { //$NON-NLS-1$ + closeMessage(); + final Command discoveryWizardCommand = TasksUiInternal.getConfiguredDiscoveryWizardCommand(); + if (discoveryWizardCommand != null && discoveryWizardCommand.isEnabled()) { + IHandlerService handlerService = (IHandlerService) PlatformUI.getWorkbench().getService( + IHandlerService.class); + try { + handlerService.executeCommand(discoveryWizardCommand.getId(), null); + } catch (Exception e1) { + IStatus status = new Status(IStatus.ERROR, TasksUiPlugin.ID_PLUGIN, NLS.bind( + Messages.SelectRepositoryConnectorPage_discoveryProblemMessage, + new Object[] { e1.getMessage() }), e1); + TasksUiInternal.logAndDisplayStatus( + Messages.SelectRepositoryConnectorPage_discoveryProblemTitle, status); } } + } else if (TasksUiInternal.isValidUrl(e.text)) { + TasksUiUtil.openUrl(e.text); } } + }; } + /** + * Extracts action from query part or a URL if applicable. + */ + public static String getAction(String action) { + if (action.startsWith("http")) { //$NON-NLS-1$ + URL url; + try { + url = new URL(action); + String query = url.getQuery(); + if (query != null && query.startsWith("action=")) { //$NON-NLS-1$ + int i = query.indexOf("&"); //$NON-NLS-1$ + if (i != -1) { + action = query.substring(7, i); + } else { + action = query.substring(7); + } + } else { + return null; + } + } catch (MalformedURLException e1) { + // ignore + return null; + } + } + return action.toLowerCase(); + } + } diff --git a/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/preferences/TasksUiPreferencePage.java b/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/preferences/TasksUiPreferencePage.java index 9dfa3266e..5fac8ff7f 100644 --- a/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/preferences/TasksUiPreferencePage.java +++ b/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/preferences/TasksUiPreferencePage.java @@ -111,8 +111,7 @@ public class TasksUiPreferencePage extends PreferencePage implements IWorkbenchP private Button showTaskTrimButton; - // Disabled for initial 3.4 release as per bug#263528 -// private Button taskListServiceMessageEnabledButton; + private Button taskListServiceMessageEnabledButton; public TasksUiPreferencePage() { super(); @@ -213,9 +212,8 @@ public class TasksUiPreferencePage extends PreferencePage implements IWorkbenchP getPreferenceStore().setValue(ITasksUiPreferenceConstants.TASK_LIST_TOOL_TIPS_ENABLED, taskListTooltipEnabledButton.getSelection()); - // Disabled for initial 3.4 release as per bug#263528 -// getPreferenceStore().setValue(ITasksUiPreferenceConstants.SERVICE_MESSAGES_ENABLED, -// taskListServiceMessageEnabledButton.getSelection()); + getPreferenceStore().setValue(ITasksUiPreferenceConstants.SERVICE_MESSAGES_ENABLED, + taskListServiceMessageEnabledButton.getSelection()); getPreferenceStore().setValue(ITasksUiPreferenceConstants.SHOW_TRIM, showTaskTrimButton.getSelection()); getPreferenceStore().setValue(ITasksUiPreferenceConstants.WEEK_START_DAY, getWeekStartValue()); @@ -288,9 +286,8 @@ public class TasksUiPreferencePage extends PreferencePage implements IWorkbenchP taskListTooltipEnabledButton.setSelection(getPreferenceStore().getBoolean( ITasksUiPreferenceConstants.TASK_LIST_TOOL_TIPS_ENABLED)); - // Disabled for initial 3.4 release as per bug#263528 -// taskListServiceMessageEnabledButton.setSelection(getPreferenceStore().getBoolean( -// ITasksUiPreferenceConstants.SERVICE_MESSAGES_ENABLED)); + taskListServiceMessageEnabledButton.setSelection(getPreferenceStore().getBoolean( + ITasksUiPreferenceConstants.SERVICE_MESSAGES_ENABLED)); showTaskTrimButton.setSelection(getPreferenceStore().getBoolean(ITasksUiPreferenceConstants.SHOW_TRIM)); weekStartCombo.select(getPreferenceStore().getInt(ITasksUiPreferenceConstants.WEEK_START_DAY) - 1); @@ -328,9 +325,8 @@ public class TasksUiPreferencePage extends PreferencePage implements IWorkbenchP taskListTooltipEnabledButton.setSelection(getPreferenceStore().getDefaultBoolean( ITasksUiPreferenceConstants.TASK_LIST_TOOL_TIPS_ENABLED)); - // Disabled for initial 3.4 release as per bug#263528 -// taskListServiceMessageEnabledButton.setSelection(getPreferenceStore().getDefaultBoolean( -// ITasksUiPreferenceConstants.SERVICE_MESSAGES_ENABLED)); + taskListServiceMessageEnabledButton.setSelection(getPreferenceStore().getDefaultBoolean( + ITasksUiPreferenceConstants.SERVICE_MESSAGES_ENABLED)); showTaskTrimButton.setSelection(getPreferenceStore().getDefaultBoolean(ITasksUiPreferenceConstants.SHOW_TRIM)); // synchQueries.setSelection(getPreferenceStore().getDefaultBoolean( @@ -519,11 +515,10 @@ public class TasksUiPreferencePage extends PreferencePage implements IWorkbenchP taskListTooltipEnabledButton.setSelection(getPreferenceStore().getBoolean( ITasksUiPreferenceConstants.TASK_LIST_TOOL_TIPS_ENABLED)); - // Disabled for initial 3.4 release as per bug#263528 -// taskListServiceMessageEnabledButton = new Button(group, SWT.CHECK); -// taskListServiceMessageEnabledButton.setText(Messages.TasksUiPreferencePage_show_service_messages); -// taskListServiceMessageEnabledButton.setSelection(getPreferenceStore().getBoolean( -// ITasksUiPreferenceConstants.SERVICE_MESSAGES_ENABLED)); + taskListServiceMessageEnabledButton = new Button(group, SWT.CHECK); + taskListServiceMessageEnabledButton.setText("Display notification when new connectors are available"); //$NON-NLS-1$ + taskListServiceMessageEnabledButton.setSelection(getPreferenceStore().getBoolean( + ITasksUiPreferenceConstants.SERVICE_MESSAGES_ENABLED)); } private void createTaskActivityGroup(Composite container) { diff --git a/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/util/TasksUiInternal.java b/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/util/TasksUiInternal.java index 3954cfd76..3e1e9a401 100644 --- a/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/util/TasksUiInternal.java +++ b/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/util/TasksUiInternal.java @@ -165,7 +165,7 @@ public class TasksUiInternal { */ public static Command getConfiguredDiscoveryWizardCommand() { ICommandService service = (ICommandService) PlatformUI.getWorkbench().getService(ICommandService.class); - final Command discoveryWizardCommand = service.getCommand("org.eclipse.mylyn.discovery.ui.discoveryWizardCommand"); //$NON-NLS-1$ + final Command discoveryWizardCommand = service.getCommand("org.eclipse.mylyn.tasks.ui.discoveryWizardCommand"); //$NON-NLS-1$ if (discoveryWizardCommand != null) { IHandlerService handlerService = (IHandlerService) PlatformUI.getWorkbench().getService( IHandlerService.class); |