### Eclipse Workspace Patch 1.0 #P org.eclipse.mylyn.commons.ui Index: src/org/eclipse/mylyn/internal/provisional/commons/ui/ServiceMessageControl.java =================================================================== RCS file: /cvsroot/mylyn/org.eclipse.mylyn.commons/org.eclipse.mylyn.commons.ui/src/org/eclipse/mylyn/internal/provisional/commons/ui/ServiceMessageControl.java,v retrieving revision 1.5 diff -u -r1.5 ServiceMessageControl.java --- src/org/eclipse/mylyn/internal/provisional/commons/ui/ServiceMessageControl.java 24 Feb 2011 05:18:15 -0000 1.5 +++ src/org/eclipse/mylyn/internal/provisional/commons/ui/ServiceMessageControl.java 29 May 2011 14:37:56 -0000 @@ -100,8 +100,19 @@ private String eventId; + private String preferencesPageId; + public ServiceMessageControl(Composite parent) { this.parent = parent; + setPreferencesPageId(NOTIFICATIONS_PREF_PAGE); + } + + public String getPreferencesPageId() { + return preferencesPageId; + } + + public void setPreferencesPageId(String preferencesPageId) { + this.preferencesPageId = preferencesPageId; } /** @@ -195,55 +206,33 @@ buttonsComp.setLayout(gLayout); - // Disabled for initial 3.4 release as per bug#263528 - // settingsLink = new ImageHyperlink(buttonsComp, SWT.NONE); - // settingsLink.setImage(CommonImages.getImage(CommonImages.NOTIFICATION_PREFERENCES)); - // settingsLink.addHyperlinkListener(new HyperlinkAdapter() { - // @Override - // public void linkActivated(HyperlinkEvent e) { - // PreferenceDialog pref = PreferencesUtil.createPreferenceDialogOn( - // TaskListServiceMessageControl.this.parent.getShell(), - // "org.eclipse.mylyn.tasks.ui.preferences", null, null); //$NON-NLS-1$ - // if (pref != null) { - // pref.open(); - // } - // } - // - // @Override - // public void linkEntered(HyperlinkEvent e) { - // settingsLink.setImage(CommonImages.getImage(CommonImages.NOTIFICATION_PREFERENCES_HOVER)); - // } - // - // @Override - // public void linkExited(HyperlinkEvent e) { - // settingsLink.setImage(CommonImages.getImage(CommonImages.NOTIFICATION_PREFERENCES)); - // } - // }); - configureLink = new ImageHyperlink(buttonsComp, SWT.NONE); - configureLink.setImage(CommonImages.getImage(CommonImages.NOTIFICATION_CONFIGURE)); - configureLink.addHyperlinkListener(new HyperlinkAdapter() { - @Override - public void linkEntered(HyperlinkEvent e) { - configureLink.setImage(CommonImages.getImage(CommonImages.NOTIFICATION_CONFIGURE_HOVER)); - } + if (getPreferencesPageId() != null) { + configureLink = new ImageHyperlink(buttonsComp, SWT.NONE); + configureLink.setImage(CommonImages.getImage(CommonImages.NOTIFICATION_CONFIGURE)); + configureLink.addHyperlinkListener(new HyperlinkAdapter() { + @Override + public void linkEntered(HyperlinkEvent e) { + configureLink.setImage(CommonImages.getImage(CommonImages.NOTIFICATION_CONFIGURE_HOVER)); + } - @Override - public void linkExited(HyperlinkEvent e) { - configureLink.setImage(CommonImages.getImage(CommonImages.NOTIFICATION_CONFIGURE)); - } + @Override + public void linkExited(HyperlinkEvent e) { + configureLink.setImage(CommonImages.getImage(CommonImages.NOTIFICATION_CONFIGURE)); + } - @Override - public void linkActivated(HyperlinkEvent e) { - PreferenceDialog pd = PreferencesUtil.createPreferenceDialogOn(getShell(), NOTIFICATIONS_PREF_PAGE, - new String[0], eventId); - // Only close the message if the did not cancel the operation - if (pd != null) { - pd.open(); + @Override + public void linkActivated(HyperlinkEvent e) { + PreferenceDialog pd = PreferencesUtil.createPreferenceDialogOn(getShell(), getPreferencesPageId(), + new String[0], eventId); + // Only close the message if the did not cancel the operation + if (pd != null) { + pd.open(); + } } - } - }); - // Initially invisible, must have eventId for this to be of any use. - configureLink.setVisible(eventId != null); + }); + // Initially invisible, must have eventId for this to be of any use. + configureLink.setVisible(eventId != null); + } closeLink = new ImageHyperlink(buttonsComp, SWT.NONE); closeLink.setImage(CommonImages.getImage(CommonImages.NOTIFICATION_CLOSE)); @@ -291,7 +280,7 @@ protected void setDescription(String description) { descriptionLabel.setText(description); - parent.layout(true); + parent.layout(true, true); } /** @@ -315,7 +304,9 @@ */ protected void setEventId(String eventId) { this.eventId = eventId; - configureLink.setVisible(eventId != null); + if (configureLink != null) { + configureLink.setVisible(eventId != null); + } } /** #P org.eclipse.mylyn.tasks.core Index: META-INF/MANIFEST.MF =================================================================== RCS file: /cvsroot/mylyn/org.eclipse.mylyn.tasks/org.eclipse.mylyn.tasks.core/META-INF/MANIFEST.MF,v retrieving revision 1.368 diff -u -r1.368 MANIFEST.MF --- META-INF/MANIFEST.MF 27 Mar 2011 23:45:01 -0000 1.368 +++ META-INF/MANIFEST.MF 29 May 2011 14:37:57 -0000 @@ -19,4 +19,9 @@ 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 Index: src/org/eclipse/mylyn/internal/tasks/core/notifications/Environment.java =================================================================== RCS file: src/org/eclipse/mylyn/internal/tasks/core/notifications/Environment.java diff -N src/org/eclipse/mylyn/internal/tasks/core/notifications/Environment.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/mylyn/internal/tasks/core/notifications/Environment.java 1 Jan 1970 00:00:00 -0000 @@ -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 environment; + + public Environment() { + environment = new Hashtable(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 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 requiredFeatures = entry.getFilters("requires"); //$NON-NLS-1$ + for (String requiredFeature : requiredFeatures) { + if (!getInstalledFeatures(monitor).contains(parseFeature(requiredFeature))) { + return false; + } + } + List 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 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; + } + +} Index: src/org/eclipse/mylyn/internal/tasks/core/notifications/FeedEntry.java =================================================================== RCS file: src/org/eclipse/mylyn/internal/tasks/core/notifications/FeedEntry.java diff -N src/org/eclipse/mylyn/internal/tasks/core/notifications/FeedEntry.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/mylyn/internal/tasks/core/notifications/FeedEntry.java 1 Jan 1970 00:00:00 -0000 @@ -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 getFilters(String key) { + Assert.isNotNull(key); + List result = new ArrayList(); + 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; + } + +} Index: src/org/eclipse/mylyn/internal/tasks/core/notifications/FeedReader.java =================================================================== RCS file: src/org/eclipse/mylyn/internal/tasks/core/notifications/FeedReader.java diff -N src/org/eclipse/mylyn/internal/tasks/core/notifications/FeedReader.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/mylyn/internal/tasks/core/notifications/FeedReader.java 1 Jan 1970 00:00:00 -0000 @@ -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 entries; + + public FeedReader(Environment environment) { + this.environment = environment; + this.entries = new ArrayList(); + } + + 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 getEntries() { + return entries; + } + +} Index: src/org/eclipse/mylyn/internal/tasks/core/notifications/ServiceMessage.java =================================================================== RCS file: /cvsroot/mylyn/org.eclipse.mylyn.tasks/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/internal/tasks/core/notifications/ServiceMessage.java,v retrieving revision 1.1 diff -u -r1.1 ServiceMessage.java --- src/org/eclipse/mylyn/internal/tasks/core/notifications/ServiceMessage.java 25 May 2010 20:03:25 -0000 1.1 +++ src/org/eclipse/mylyn/internal/tasks/core/notifications/ServiceMessage.java 29 May 2011 14:37:58 -0000 @@ -14,10 +14,10 @@ /** * @author Robert Elves */ -public class ServiceMessage { +public class ServiceMessage implements Comparable { public enum Element { - ID, TITLE, DESCRIPTION, URL, IMAGE, VERSION + ID, TITLE, DESCRIPTION, URL, IMAGE }; private String id; @@ -30,8 +30,6 @@ private String image; - private String version; - private String eTag; private String lastModified; @@ -72,10 +70,6 @@ return lastModified; } - public String getVersion() { - return version; - } - public void setId(String id) { this.id = id; } @@ -96,12 +90,33 @@ 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(); + } + } Index: src/org/eclipse/mylyn/internal/tasks/core/notifications/ServiceMessageManager.java =================================================================== RCS file: /cvsroot/mylyn/org.eclipse.mylyn.tasks/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/internal/tasks/core/notifications/ServiceMessageManager.java,v retrieving revision 1.5 diff -u -r1.5 ServiceMessageManager.java --- src/org/eclipse/mylyn/internal/tasks/core/notifications/ServiceMessageManager.java 8 Jun 2010 23:10:12 -0000 1.5 +++ src/org/eclipse/mylyn/internal/tasks/core/notifications/ServiceMessageManager.java 29 May 2011 14:37:58 -0000 @@ -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 @@ 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 messages = Collections.emptyList(); + private volatile List messages = Collections.emptyList(); private Job messageCheckJob; @@ -63,11 +60,19 @@ 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 @@ 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 @@ 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 @@ listeners.remove(listener); } - private void notifyListeners(List messages) { + private void notifyListeners(List messages) { this.messages = messages; for (final ServiceMessage message : messages) { message.setETag(eTag); message.setLastModified(lastModified); } + ArrayList sortedMessages = new ArrayList(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 int updateServiceMessage(IProgressMonitor monitor) { int status = -1; - List messages = null; + List messages = null; try { HttpClient httpClient = new HttpClient(WebUtil.getConnectionManager()); WebUtil.configureHttpClient(httpClient, null); @@ -203,13 +213,7 @@ 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 @@ } 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 @@ return status; } + private void logStatus(IStatus status) { + if (!statusLogged) { + statusLogged = true; + //StatusHandler.log(status); + } + } + +// private List 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 readMessages(InputStream in, IProgressMonitor monitor) throws IOException { + FeedReader reader = new FeedReader(environment); + reader.parse(in, monitor); + return reader.getEntries(); + } + } Index: src/org/eclipse/mylyn/internal/tasks/core/notifications/ServiceMessageXmlHandler.java =================================================================== RCS file: /cvsroot/mylyn/org.eclipse.mylyn.tasks/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/internal/tasks/core/notifications/ServiceMessageXmlHandler.java,v retrieving revision 1.1 diff -u -r1.1 ServiceMessageXmlHandler.java --- src/org/eclipse/mylyn/internal/tasks/core/notifications/ServiceMessageXmlHandler.java 25 May 2010 20:03:25 -0000 1.1 +++ src/org/eclipse/mylyn/internal/tasks/core/notifications/ServiceMessageXmlHandler.java 29 May 2011 14:37:58 -0000 @@ -75,9 +75,6 @@ case IMAGE: message.setImage(parsedText); break; - case VERSION: - message.setVersion(parsedText); - break; } } catch (IllegalArgumentException e) { // ignore unrecognized elements #P org.eclipse.mylyn.tasks.tests Index: META-INF/MANIFEST.MF =================================================================== RCS file: /cvsroot/mylyn/org.eclipse.mylyn.tasks/org.eclipse.mylyn.tasks.tests/META-INF/MANIFEST.MF,v retrieving revision 1.64 diff -u -r1.64 MANIFEST.MF --- META-INF/MANIFEST.MF 27 Mar 2011 23:45:04 -0000 1.64 +++ META-INF/MANIFEST.MF 29 May 2011 14:37:59 -0000 @@ -33,10 +33,12 @@ 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 Index: src/org/eclipse/mylyn/tasks/tests/core/EnvironmentTest.java =================================================================== RCS file: src/org/eclipse/mylyn/tasks/tests/core/EnvironmentTest.java diff -N src/org/eclipse/mylyn/tasks/tests/core/EnvironmentTest.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/mylyn/tasks/tests/core/EnvironmentTest.java 1 Jan 1970 00:00:00 -0000 @@ -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 map; + + public StubEntry(Map map) { + this.map = map; + } + + @Override + public List 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 installedFeatures; + + @Override + protected void setUp() throws Exception { + installedFeatures = new HashSet(); + environment = new Environment() { + @Override + public Set 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 values = new HashMap(); + 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 values = new HashMap(); + 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 values = new HashMap(); + 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 values = new HashMap(); + 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)); + } + +} Index: src/org/eclipse/mylyn/tasks/tests/core/FeedReaderTest.java =================================================================== RCS file: src/org/eclipse/mylyn/tasks/tests/core/FeedReaderTest.java diff -N src/org/eclipse/mylyn/tasks/tests/core/FeedReaderTest.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/mylyn/tasks/tests/core/FeedReaderTest.java 1 Jan 1970 00:00:00 -0000 @@ -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 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. Show connectors.", + 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. See New and Noteworthy for details.", + entry.getDescription()); + } + +} Index: src/org/eclipse/mylyn/tasks/tests/ui/TaskListServiceMessageControlTest.java =================================================================== RCS file: src/org/eclipse/mylyn/tasks/tests/ui/TaskListServiceMessageControlTest.java diff -N src/org/eclipse/mylyn/tasks/tests/ui/TaskListServiceMessageControlTest.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/mylyn/tasks/tests/ui/TaskListServiceMessageControlTest.java 1 Jan 1970 00:00:00 -0000 @@ -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")); + } + +} Index: testdata/FeedReaderTest/update1.xml =================================================================== RCS file: testdata/FeedReaderTest/update1.xml diff -N testdata/FeedReaderTest/update1.xml --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ testdata/FeedReaderTest/update1.xml 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,41 @@ + + + +Mylyn Updates +http://eclipse.org/mylyn +Mylyn Updates +Fri, 27 May 2011 17:33:37 +0000 +en + +Mylyn 3.6 is now available +http://eclipse.org/mylyn/new/ +Thu, 24 Mar 2011 14:00:07 +0000 +Steffen Pingel +runtimeVersion=1.5.0 +requires=org.eclipse.mylyn +Mylyn +20110527-0000 +Mylyn 3.7 is now available. <a href="http://eclipse.org/mylyn/new/">See New and Noteworthy</a> for details. + + +New Connectors +http://eclipse.org/mylyn/new/ +Fri, 27 May 2011 12:00:00 +0000 +Steffen Pingel +frameworkVersion=[0.0.0,3.7.0) +20110527-0001 +New connectors are now available. <a href="#discovery">Show connectors</a>. + + +Filtered Item +http://eclipse.org/mylyn/new/ +Fri, 27 May 2011 12:00:00 +0000 +Steffen Pingel +frameworkVersion=[1.0.0,2.0.0) +20110527-0002 +Specifies an unsatisfiable framework version. + + + #P org.eclipse.mylyn.tasks.ui Index: META-INF/MANIFEST.MF =================================================================== RCS file: /cvsroot/mylyn/org.eclipse.mylyn.tasks/org.eclipse.mylyn.tasks.ui/META-INF/MANIFEST.MF,v retrieving revision 1.424 diff -u -r1.424 MANIFEST.MF --- META-INF/MANIFEST.MF 24 May 2011 00:08:57 -0000 1.424 +++ META-INF/MANIFEST.MF 29 May 2011 14:38:02 -0000 @@ -26,7 +26,8 @@ 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, Index: plugin.xml =================================================================== RCS file: /cvsroot/mylyn/org.eclipse.mylyn.tasks/org.eclipse.mylyn.tasks.ui/plugin.xml,v retrieving revision 1.394 diff -u -r1.394 plugin.xml --- plugin.xml 24 May 2011 00:08:57 -0000 1.394 +++ plugin.xml 29 May 2011 14:38:02 -0000 @@ -2105,5 +2105,27 @@ - + + + + + + + + + + + + + + Index: src/org/eclipse/mylyn/internal/tasks/ui/TasksUiPlugin.java =================================================================== RCS file: /cvsroot/mylyn/org.eclipse.mylyn.tasks/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/TasksUiPlugin.java,v retrieving revision 1.147 diff -u -r1.147 TasksUiPlugin.java --- src/org/eclipse/mylyn/internal/tasks/ui/TasksUiPlugin.java 15 May 2011 17:09:54 -0000 1.147 +++ src/org/eclipse/mylyn/internal/tasks/ui/TasksUiPlugin.java 29 May 2011 14:38:02 -0000 @@ -58,6 +58,7 @@ 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.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 @@ 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 installedFeatures; + + @Override + public Set 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 @@ 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 @@ 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() { Index: src/org/eclipse/mylyn/internal/tasks/ui/commands/ShowTasksConnectorDiscoveryWizardCommandHandler.java =================================================================== RCS file: src/org/eclipse/mylyn/internal/tasks/ui/commands/ShowTasksConnectorDiscoveryWizardCommandHandler.java diff -N src/org/eclipse/mylyn/internal/tasks/ui/commands/ShowTasksConnectorDiscoveryWizardCommandHandler.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/mylyn/internal/tasks/ui/commands/ShowTasksConnectorDiscoveryWizardCommandHandler.java 1 Jan 1970 00:00:00 -0000 @@ -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; + } +} Index: src/org/eclipse/mylyn/internal/tasks/ui/notifications/TaskListServiceMessageControl.java =================================================================== RCS file: /cvsroot/mylyn/org.eclipse.mylyn.tasks/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/notifications/TaskListServiceMessageControl.java,v retrieving revision 1.12 diff -u -r1.12 TaskListServiceMessageControl.java --- src/org/eclipse/mylyn/internal/tasks/ui/notifications/TaskListServiceMessageControl.java 10 Mar 2011 09:50:56 -0000 1.12 +++ src/org/eclipse/mylyn/internal/tasks/ui/notifications/TaskListServiceMessageControl.java 29 May 2011 14:38:04 -0000 @@ -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.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.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 TaskListServiceMessageControl(Composite parent) { super(parent); + setPreferencesPageId(TasksUiPreferencePage.ID); } static ExecutionEvent createExecutionEvent(Command command, IHandlerService handlerService) { @@ -83,12 +85,15 @@ 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 @@ } } - 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 @@ this.currentMessage = message; setTitle(message.getTitle()); - setDescription(message.getDescription()); setTitleImage(Dialog.getImage(message.getImage())); + setDescription(message.getDescription()); } } @@ -136,35 +126,67 @@ 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(); + } + } Index: src/org/eclipse/mylyn/internal/tasks/ui/preferences/TasksUiPreferencePage.java =================================================================== RCS file: /cvsroot/mylyn/org.eclipse.mylyn.tasks/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/preferences/TasksUiPreferencePage.java,v retrieving revision 1.48 diff -u -r1.48 TasksUiPreferencePage.java --- src/org/eclipse/mylyn/internal/tasks/ui/preferences/TasksUiPreferencePage.java 9 Feb 2011 06:09:06 -0000 1.48 +++ src/org/eclipse/mylyn/internal/tasks/ui/preferences/TasksUiPreferencePage.java 29 May 2011 14:38:04 -0000 @@ -111,8 +111,7 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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) { Index: src/org/eclipse/mylyn/internal/tasks/ui/util/TasksUiInternal.java =================================================================== RCS file: /cvsroot/mylyn/org.eclipse.mylyn.tasks/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/util/TasksUiInternal.java,v retrieving revision 1.124 diff -u -r1.124 TasksUiInternal.java --- src/org/eclipse/mylyn/internal/tasks/ui/util/TasksUiInternal.java 17 May 2011 20:50:34 -0000 1.124 +++ src/org/eclipse/mylyn/internal/tasks/ui/util/TasksUiInternal.java 29 May 2011 14:38:05 -0000 @@ -165,7 +165,7 @@ */ 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); #P org.eclipse.mylyn.tests.standalone Index: src/org/eclipse/mylyn/tests/AllHeadlessStandaloneTest.java =================================================================== RCS file: /cvsroot/mylyn/org.eclipse.mylyn/org.eclipse.mylyn.tests.standalone/src/org/eclipse/mylyn/tests/AllHeadlessStandaloneTest.java,v retrieving revision 1.4 diff -u -r1.4 AllHeadlessStandaloneTest.java --- src/org/eclipse/mylyn/tests/AllHeadlessStandaloneTest.java 5 Mar 2011 07:14:10 -0000 1.4 +++ src/org/eclipse/mylyn/tests/AllHeadlessStandaloneTest.java 29 May 2011 14:38:06 -0000 @@ -21,6 +21,8 @@ import org.eclipse.mylyn.tasks.tests.TaskListTest; import org.eclipse.mylyn.tasks.tests.TasksUtilTest; import org.eclipse.mylyn.tasks.tests.core.DefaultTaskSchemaTest; +import org.eclipse.mylyn.tasks.tests.core.EnvironmentTest; +import org.eclipse.mylyn.tasks.tests.core.FeedReaderTest; import org.eclipse.mylyn.tasks.tests.core.ITasksCoreConstantsTest; import org.eclipse.mylyn.tasks.tests.core.TaskListUnmatchedContainerTest; import org.eclipse.mylyn.tasks.tests.core.TaskRepositoryLocationTest; @@ -46,6 +48,8 @@ // commons suite.addTestSuite(WebUtilTest.class); suite.addTestSuite(SslProtocolSocketFactoryTest.class); + suite.addTestSuite(FeedReaderTest.class); + suite.addTestSuite(EnvironmentTest.class); // context // disabled due to failure: bug 257972