412953: Remove jdom and rome dependencies

Replaces use of Rome with custom RSS parser implementation.

Also-By: Steffen Pingel <steffen.pingel@tasktop.com>
Task-Url: https://bugs.eclipse.org/bugs/show_bug.cgi?id=412953
Signed-off-by: Krzysztof Daniel <kdaniel@redhat.com>
Change-Id: Ifdb18ffd1de5f4e3d58bee351fabca10370af117
diff --git a/org.eclipse.mylyn.commons-target/mylyn-commons-e3.6.target b/org.eclipse.mylyn.commons-target/mylyn-commons-e3.6.target
index 5dd27f2..9f8cd72 100644
--- a/org.eclipse.mylyn.commons-target/mylyn-commons-e3.6.target
+++ b/org.eclipse.mylyn.commons-target/mylyn-commons-e3.6.target
@@ -6,7 +6,6 @@
 <location includeAllPlatforms="false" includeMode="slicer" includeSource="true" type="InstallableUnit">
 <unit id="com.google.gson" version="2.1.0.v201303041604"/>
 <unit id="com.google.guava" version="12.0.0.v201212092141"/>
-<unit id="com.sun.syndication" version="0.9.0.v200803061811"/>
 <unit id="com.thoughtworks.qdox" version="1.6.3.v20081201-1400"/>
 <unit id="javax.activation" version="1.1.0.v201211130549"/>
 <unit id="javax.mail" version="1.4.0.v201005080615"/>
@@ -34,7 +33,6 @@
 <unit id="org.hamcrest.integration" version="1.1.0.v201303031500"/>
 <unit id="org.hamcrest.library" version="1.1.0.v20090501071000"/>
 <unit id="org.hamcrest.text" version="1.1.0.v20090501071000"/>
-<unit id="org.jdom" version="1.1.1.v201101151400"/>
 <unit id="org.mockito" version="1.8.4.v201303031500"/>
 <unit id="org.objenesis" version="1.0.0.v201105211943"/>
 <repository location="http://download.eclipse.org/tools/orbit/downloads/drops/S20130914154012/repository/"/>
diff --git a/org.eclipse.mylyn.commons.notifications-feature/feature.xml b/org.eclipse.mylyn.commons.notifications-feature/feature.xml
index 1b99195..da5c2a6 100644
--- a/org.eclipse.mylyn.commons.notifications-feature/feature.xml
+++ b/org.eclipse.mylyn.commons.notifications-feature/feature.xml
@@ -29,13 +29,6 @@
    </license>
 
    <requires>
-      <import plugin="org.eclipse.mylyn.commons.net" version="3.10.0" match="compatible"/>
-      <import plugin="org.apache.commons.codec" version="1.3.0" match="compatible"/>
-      <import plugin="org.apache.commons.lang" version="2.3.0" match="compatible"/>
-      <import plugin="org.apache.commons.logging" version="1.0.4" match="compatible"/>
-      <import plugin="org.apache.commons.httpclient" version="3.1.0" match="compatible"/>
-      <import plugin="com.sun.syndication" version="0.9.0" match="compatible"/>
-      <import plugin="org.jdom" version="1.1.0" match="compatible"/>
       <import feature="org.eclipse.mylyn.commons" version="3.10.0" match="greaterOrEqual"/>
    </requires>
 
diff --git a/org.eclipse.mylyn.commons.notifications.core/META-INF/MANIFEST.MF b/org.eclipse.mylyn.commons.notifications.core/META-INF/MANIFEST.MF
index 6f6907f..a88b758 100644
--- a/org.eclipse.mylyn.commons.notifications.core/META-INF/MANIFEST.MF
+++ b/org.eclipse.mylyn.commons.notifications.core/META-INF/MANIFEST.MF
@@ -5,7 +5,7 @@
 Bundle-Version: 1.2.0.qualifier
 Bundle-Vendor: %Bundle-Vendor
 Bundle-RequiredExecutionEnvironment: JavaSE-1.6
-Export-Package: org.eclipse.mylyn.commons.notifications.core;x-friends:="org.eclipse.mylyn.commons.notifications.ui"
+Export-Package: org.eclipse.mylyn.commons.notifications.core;x-friends:="org.eclipse.mylyn.commons.notifications.ui,org.eclipse.mylyn.commons.notifications.feed"
 Require-Bundle: org.eclipse.core.runtime,
  org.eclipse.mylyn.commons.core
 Bundle-ClassPath: .
diff --git a/org.eclipse.mylyn.commons.notifications.feed/META-INF/MANIFEST.MF b/org.eclipse.mylyn.commons.notifications.feed/META-INF/MANIFEST.MF
index 633ce76..dbbc78f 100644
--- a/org.eclipse.mylyn.commons.notifications.feed/META-INF/MANIFEST.MF
+++ b/org.eclipse.mylyn.commons.notifications.feed/META-INF/MANIFEST.MF
@@ -9,13 +9,8 @@
  org.eclipse.mylyn.internal.commons.notifications.feed;x-internal:=true
 Require-Bundle: org.eclipse.core.runtime,
  org.eclipse.mylyn.commons.core,
- org.eclipse.mylyn.commons.net,
  org.eclipse.mylyn.commons.notifications.core
 Bundle-ClassPath: .
 Bundle-Localization: plugin
 Bundle-ActivationPolicy: lazy
-Import-Package: com.sun.syndication.feed;version="0.9.0",
- com.sun.syndication.feed.module;version="0.9.0",
- com.sun.syndication.feed.synd;version="0.9.0",
- com.sun.syndication.io;version="0.9.0",
- org.jdom;version="1.0.0"
+
diff --git a/org.eclipse.mylyn.commons.notifications.feed/src/org/eclipse/mylyn/commons/notifications/feed/ServiceMessageManager.java b/org.eclipse.mylyn.commons.notifications.feed/src/org/eclipse/mylyn/commons/notifications/feed/ServiceMessageManager.java
index 9c3c39f..5a6812d 100644
--- a/org.eclipse.mylyn.commons.notifications.feed/src/org/eclipse/mylyn/commons/notifications/feed/ServiceMessageManager.java
+++ b/org.eclipse.mylyn.commons.notifications.feed/src/org/eclipse/mylyn/commons/notifications/feed/ServiceMessageManager.java
@@ -8,31 +8,26 @@
 
 package org.eclipse.mylyn.commons.notifications.feed;
 
+import java.io.BufferedInputStream;
 import java.io.IOException;
 import java.io.InputStream;
+import java.net.HttpURLConnection;
+import java.net.URL;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
 import java.util.concurrent.CopyOnWriteArrayList;
 
-import org.apache.commons.httpclient.Header;
-import org.apache.commons.httpclient.HostConfiguration;
-import org.apache.commons.httpclient.HttpClient;
-import org.apache.commons.httpclient.HttpStatus;
-import org.apache.commons.httpclient.methods.GetMethod;
 import org.eclipse.core.runtime.Assert;
 import org.eclipse.core.runtime.IProgressMonitor;
 import org.eclipse.core.runtime.ISafeRunnable;
 import org.eclipse.core.runtime.IStatus;
 import org.eclipse.core.runtime.SafeRunner;
 import org.eclipse.core.runtime.Status;
-import org.eclipse.core.runtime.SubProgressMonitor;
 import org.eclipse.core.runtime.jobs.IJobChangeEvent;
 import org.eclipse.core.runtime.jobs.Job;
 import org.eclipse.core.runtime.jobs.JobChangeAdapter;
 import org.eclipse.mylyn.commons.core.StatusHandler;
-import org.eclipse.mylyn.commons.net.WebLocation;
-import org.eclipse.mylyn.commons.net.WebUtil;
 import org.eclipse.mylyn.commons.notifications.core.NotificationEnvironment;
 import org.eclipse.mylyn.internal.commons.notifications.feed.FeedReader;
 import org.eclipse.mylyn.internal.commons.notifications.feed.INotificationsFeed;
@@ -182,45 +177,42 @@
 		int status = -1;
 		List<? extends ServiceMessage> messages = null;
 		try {
-			HttpClient httpClient = new HttpClient(WebUtil.getConnectionManager());
-			WebUtil.configureHttpClient(httpClient, null);
-
-			WebLocation location = new WebLocation(url);
-			HostConfiguration hostConfiguration = WebUtil.createHostConfiguration(httpClient, location,
-					new SubProgressMonitor(monitor, 1));
-
-			GetMethod method = new GetMethod(url);
-			method.setRequestHeader("If-Modified-Since", lastModified); //$NON-NLS-1$
-			method.setRequestHeader("If-None-Match", eTag); //$NON-NLS-1$
+			HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection();
+			if (lastModified != null && lastModified.length() > 0) {
+				try {
+					connection.setIfModifiedSince(Long.parseLong(lastModified));
+				} catch (NumberFormatException e) {
+					// ignore
+				}
+			}
+			if (eTag != null && eTag.length() > 0) {
+				connection.setRequestProperty("If-None-Match", eTag); //$NON-NLS-1$
+			}
 
 			try {
-				status = WebUtil.execute(httpClient, hostConfiguration, method, monitor);
-				if (status == HttpStatus.SC_OK && !monitor.isCanceled()) {
-					Header lastModifiedHeader = method.getResponseHeader("Last-Modified"); //$NON-NLS-1$
-					if (lastModifiedHeader != null) {
-						lastModified = lastModifiedHeader.getValue();
-					}
-					Header eTagHeader = method.getResponseHeader("ETag"); //$NON-NLS-1$
-					if (eTagHeader != null) {
-						eTag = eTagHeader.getValue();
-					}
+				connection.connect();
 
-					InputStream in = WebUtil.getResponseBodyAsStream(method, monitor);
+				status = connection.getResponseCode();
+				if (status == HttpURLConnection.HTTP_OK && !monitor.isCanceled()) {
+					lastModified = connection.getHeaderField("Last-Modified"); //$NON-NLS-1$
+					eTag = connection.getHeaderField("ETag"); //$NON-NLS-1$
+
+					InputStream in = new BufferedInputStream(connection.getInputStream());
 					try {
 						messages = readMessages(in, monitor);
 					} finally {
 						in.close();
 					}
-				} else if (status == HttpStatus.SC_NOT_FOUND) {
+				} else if (status == HttpURLConnection.HTTP_NOT_FOUND) {
 					// no messages
-				} else if (status == HttpStatus.SC_NOT_MODIFIED) {
+				} else if (status == HttpURLConnection.HTTP_NOT_MODIFIED) {
 					// no new messages
 				} else {
 					logStatus(new Status(IStatus.WARNING, INotificationsFeed.ID_PLUGIN,
-							"Http error retrieving service message: " + HttpStatus.getStatusText(status))); //$NON-NLS-1$
+							"Http error retrieving service message: " + connection.getResponseMessage())); //$NON-NLS-1$
 				}
 			} finally {
-				WebUtil.releaseConnection(method, monitor);
+				connection.disconnect();
 			}
 		} catch (Exception e) {
 			logStatus(new Status(IStatus.WARNING, INotificationsFeed.ID_PLUGIN,
diff --git a/org.eclipse.mylyn.commons.notifications.feed/src/org/eclipse/mylyn/internal/commons/notifications/feed/FeedEntry.java b/org.eclipse.mylyn.commons.notifications.feed/src/org/eclipse/mylyn/internal/commons/notifications/feed/FeedEntry.java
index c4e0304..a902356 100644
--- a/org.eclipse.mylyn.commons.notifications.feed/src/org/eclipse/mylyn/internal/commons/notifications/feed/FeedEntry.java
+++ b/org.eclipse.mylyn.commons.notifications.feed/src/org/eclipse/mylyn/internal/commons/notifications/feed/FeedEntry.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2011 Tasktop Technologies and others.
+ * Copyright (c) 2013 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
@@ -7,38 +7,51 @@
  *
  * Contributors:
  *     Tasktop Technologies - initial API and implementation
+ *     Red Hat, Inc - Bug 412953.
  *******************************************************************************/
 
 package org.eclipse.mylyn.internal.commons.notifications.feed;
 
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
 import java.util.ArrayList;
-import java.util.Iterator;
+import java.util.Date;
 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;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.mylyn.commons.core.StatusHandler;
 
 /**
  * @author Steffen Pingel
  */
 public class FeedEntry extends ServiceMessage {
 
-	private final SyndEntry source;
+	private final RSSItem source;
 
-	public FeedEntry(String eventId, SyndEntry source) {
+	public FeedEntry(String eventId, RSSItem source) {
 		super(eventId);
 		this.source = source;
-		setId(source.getUri());
+		setId(source.getGuid());
 		setTitle(source.getTitle());
 		if (source.getDescription() != null) {
-			setDescription(source.getDescription().getValue());
+			setDescription(source.getDescription());
 		}
 		setUrl(source.getLink());
 		setImage("dialog_messasge_info_image"); //$NON-NLS-1$
-		setDate(source.getPublishedDate());
+		setDate(getDate(source));
+	}
+
+	private Date getDate(RSSItem source) {
+		SimpleDateFormat sdf = new SimpleDateFormat("E, dd MMM yyyy hh:mm:ss ZZZZ"); //$NON-NLS-1$
+		try {
+			return sdf.parse(source.getPubDate());
+		} catch (ParseException e) {
+			StatusHandler.log(new Status(IStatus.ERROR, INotificationsFeed.ID_PLUGIN, "Processing pub date of \"" //$NON-NLS-1$
+					+ source + "\" failed", e)); //$NON-NLS-1$
+		}
+		return null;
 	}
 
 	public FeedEntry(String eventId) {
@@ -46,52 +59,35 @@
 		this.source = null;
 	}
 
-	public SyndEntry getSource() {
+	public RSSItem 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 (source.getSubjects() != null) {
+			for (String subject : source.getSubjects()) {
+				String value = parseFilter(key, subject);
 				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 (source.getSubjects() != null) {
+			for (String subject : source.getSubjects()) {
+				String value = parseFilter(key, subject);
 				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;
 	}
 
diff --git a/org.eclipse.mylyn.commons.notifications.feed/src/org/eclipse/mylyn/internal/commons/notifications/feed/FeedReader.java b/org.eclipse.mylyn.commons.notifications.feed/src/org/eclipse/mylyn/internal/commons/notifications/feed/FeedReader.java
index 2940574..469677e 100644
--- a/org.eclipse.mylyn.commons.notifications.feed/src/org/eclipse/mylyn/internal/commons/notifications/feed/FeedReader.java
+++ b/org.eclipse.mylyn.commons.notifications.feed/src/org/eclipse/mylyn/internal/commons/notifications/feed/FeedReader.java
@@ -7,15 +7,21 @@
  *
  * Contributors:
  *     Tasktop Technologies - initial API and implementation
+ *     Red Hat, Inc - Bug 412953.
  *******************************************************************************/
 
 package org.eclipse.mylyn.internal.commons.notifications.feed;
 
+import java.io.IOException;
 import java.io.InputStream;
 import java.util.ArrayList;
-import java.util.Iterator;
 import java.util.List;
 
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.JAXBElement;
+import javax.xml.bind.Unmarshaller;
+import javax.xml.transform.stream.StreamSource;
+
 import org.eclipse.core.runtime.IAdaptable;
 import org.eclipse.core.runtime.IProgressMonitor;
 import org.eclipse.core.runtime.IStatus;
@@ -23,11 +29,6 @@
 import org.eclipse.mylyn.commons.notifications.core.IFilterable;
 import org.eclipse.mylyn.commons.notifications.core.NotificationEnvironment;
 
-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
  */
@@ -46,12 +47,14 @@
 	}
 
 	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();
-				final FeedEntry entry = createEntry(syndEntry);
+			JAXBContext jc = JAXBContext.newInstance(RSS.class);
+			Unmarshaller unmarshaller = jc.createUnmarshaller();
+			JAXBElement<RSS> rss = unmarshaller.unmarshal(new StreamSource(in), RSS.class);
+
+			for (RSSItem rssItem : rss.getValue().getItems()) {
+				final FeedEntry entry = createEntry(rssItem);
 				if (environment.matches(new IAdaptable() {
 					public Object getAdapter(@SuppressWarnings("rawtypes") Class adapter) {
 						if (adapter == IFilterable.class) {
@@ -76,11 +79,17 @@
 			return Status.OK_STATUS;
 		} catch (Exception e) {
 			return new Status(IStatus.ERROR, INotificationsFeed.ID_PLUGIN, IStatus.ERROR, "Failed to parse RSS feed", e); //$NON-NLS-1$ 
+		} finally {
+			try {
+				in.close();
+			} catch (IOException e) {
+				//ignore
+			}
 		}
 	}
 
-	protected FeedEntry createEntry(SyndEntry syndEntry) {
-		return new FeedEntry(eventId, syndEntry);
+	protected FeedEntry createEntry(RSSItem rssItem) {
+		return new FeedEntry(eventId, rssItem);
 	}
 
 	public List<FeedEntry> getEntries() {
diff --git a/org.eclipse.mylyn.commons.notifications.feed/src/org/eclipse/mylyn/internal/commons/notifications/feed/RSS.java b/org.eclipse.mylyn.commons.notifications.feed/src/org/eclipse/mylyn/internal/commons/notifications/feed/RSS.java
new file mode 100644
index 0000000..0be36d1
--- /dev/null
+++ b/org.eclipse.mylyn.commons.notifications.feed/src/org/eclipse/mylyn/internal/commons/notifications/feed/RSS.java
@@ -0,0 +1,42 @@
+/*******************************************************************************
+ * Copyright (c) 2013 Red Hat, Inc 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:
+ *     Red Hat, Inc - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.mylyn.internal.commons.notifications.feed;
+
+import java.util.ArrayList;
+
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlElementWrapper;
+import javax.xml.bind.annotation.XmlRootElement;
+
+@XmlRootElement(name = "rss")
+public class RSS {
+
+	private ArrayList<RSSItem> items;
+
+	/**
+	 * @return the items
+	 */
+	@XmlElementWrapper(name = "channel")
+	@XmlElement(name = "item")
+	public ArrayList<RSSItem> getItems() {
+		return items;
+	}
+
+	/**
+	 * @param items
+	 *            the items to set
+	 */
+	public void setItems(ArrayList<RSSItem> items) {
+		this.items = items;
+	}
+
+}
\ No newline at end of file
diff --git a/org.eclipse.mylyn.commons.notifications.feed/src/org/eclipse/mylyn/internal/commons/notifications/feed/RSSItem.java b/org.eclipse.mylyn.commons.notifications.feed/src/org/eclipse/mylyn/internal/commons/notifications/feed/RSSItem.java
new file mode 100644
index 0000000..6b5737e
--- /dev/null
+++ b/org.eclipse.mylyn.commons.notifications.feed/src/org/eclipse/mylyn/internal/commons/notifications/feed/RSSItem.java
@@ -0,0 +1,184 @@
+/*******************************************************************************
+ * Copyright (c) 2013 Red Hat, Inc 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:
+ *     Red Hat, Inc - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.mylyn.internal.commons.notifications.feed;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.xml.bind.annotation.XmlElement;
+
+public class RSSItem {
+
+	private String title;
+
+	private String link;
+
+	private String pubDate;
+
+	private String creator;
+
+	private ArrayList<String> subjects;
+
+	private String description;
+
+	private ArrayList<String> categories;
+
+	private String guid;
+
+	/**
+	 * @return the guid
+	 */
+	@XmlElement(name = "guid")
+	public String getGuid() {
+		return guid;
+	}
+
+	/**
+	 * @param guid
+	 *            the guid to set
+	 */
+	public void setGuid(String guid) {
+		this.guid = guid;
+	}
+
+	/**
+	 * @return the categories
+	 */
+	@XmlElement(name = "category", nillable = true)
+	public List<String> getCategories() {
+		if (categories == null) {
+			synchronized (this) {
+				if (categories == null) {
+					categories = new ArrayList<String>(0);
+				}
+			}
+		}
+		return categories;
+	}
+
+	/**
+	 * @param categories
+	 *            the categories to set
+	 */
+	public void setCategories(ArrayList<String> categories) {
+		this.categories = categories;
+	}
+
+	/**
+	 * @return the link
+	 */
+	@XmlElement(name = "link")
+	public String getLink() {
+		return link;
+	}
+
+	/**
+	 * @param link
+	 *            the link to set
+	 */
+	public void setLink(String link) {
+		this.link = link;
+	}
+
+	/**
+	 * @return the description
+	 */
+	@XmlElement(name = "description")
+	public String getDescription() {
+		return description;
+	}
+
+	/**
+	 * @param description
+	 *            the description to set
+	 */
+	public void setDescription(String description) {
+		this.description = description;
+	}
+
+	/**
+	 * @return the title
+	 */
+	@XmlElement(name = "title")
+	public String getTitle() {
+		return title;
+	}
+
+	/**
+	 * @param title
+	 *            the title to set
+	 */
+	public void setTitle(String title) {
+		this.title = title;
+	}
+
+	/**
+	 * @return the pubDate
+	 */
+	@XmlElement(name = "pubDate")
+	public String getPubDate() {
+		return pubDate;
+	}
+
+	/**
+	 * @param pubDate
+	 *            the pubDate to set
+	 */
+	public void setPubDate(String pubDate) {
+		this.pubDate = pubDate;
+	}
+
+	/**
+	 * @return the creator
+	 */
+	@XmlElement(name = "creator", namespace = "http://purl.org/dc/elements/1.1/")
+	public String getCreator() {
+		return creator;
+	}
+
+	/**
+	 * @param creator
+	 *            the creator to set
+	 */
+	public void setCreator(String creator) {
+		this.creator = creator;
+	}
+
+	/**
+	 * @return the subject
+	 */
+	@XmlElement(name = "subject", namespace = "http://purl.org/dc/elements/1.1/")
+	public List<String> getSubjects() {
+		if (subjects == null) {
+			synchronized (this) {
+				if (subjects == null) {
+					subjects = new ArrayList<String>(0);
+				}
+			}
+		}
+		return subjects;
+	}
+
+	/**
+	 * @param subject
+	 *            the subject to set
+	 */
+	public void setSubjects(ArrayList<String> subjects) {
+		this.subjects = subjects;
+	}
+
+	@Override
+	public String toString() {
+		return "RSSItem [title=" + title + ", link=" + link + ", pubDate=" + pubDate + ", guid=" + guid + "]"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$
+	}
+
+}
diff --git a/org.eclipse.mylyn.commons.notifications.tests/META-INF/MANIFEST.MF b/org.eclipse.mylyn.commons.notifications.tests/META-INF/MANIFEST.MF
index 9218756..0394a40 100644
--- a/org.eclipse.mylyn.commons.notifications.tests/META-INF/MANIFEST.MF
+++ b/org.eclipse.mylyn.commons.notifications.tests/META-INF/MANIFEST.MF
@@ -14,9 +14,3 @@
  org.eclipse.mylyn.commons.notifications.tests.core;x-internal:=true,
  org.eclipse.mylyn.commons.notifications.tests.feed;x-internal:=true
 Bundle-RequiredExecutionEnvironment: JavaSE-1.6
-Import-Package: com.sun.syndication.feed;version="0.9.0",
- com.sun.syndication.feed.module;version="0.9.0",
- com.sun.syndication.feed.synd;version="0.9.0",
- com.sun.syndication.io;version="0.9.0",
- org.apache.commons.httpclient;version="[3.1.0,4.0.0)",
- org.jdom;version="1.0.0"
diff --git a/org.eclipse.mylyn.commons.notifications.tests/src/org/eclipse/mylyn/commons/notifications/tests/AllNotificationsTests.java b/org.eclipse.mylyn.commons.notifications.tests/src/org/eclipse/mylyn/commons/notifications/tests/AllNotificationsTests.java
index 11aa9de..2a19ad8 100644
--- a/org.eclipse.mylyn.commons.notifications.tests/src/org/eclipse/mylyn/commons/notifications/tests/AllNotificationsTests.java
+++ b/org.eclipse.mylyn.commons.notifications.tests/src/org/eclipse/mylyn/commons/notifications/tests/AllNotificationsTests.java
@@ -16,6 +16,7 @@
 
 import org.eclipse.mylyn.commons.notifications.tests.core.NotificationEnvironmentTest;
 import org.eclipse.mylyn.commons.notifications.tests.feed.FeedReaderTest;
+import org.eclipse.mylyn.commons.notifications.tests.feed.ServiceMessageManagerTest;
 
 /**
  * @author Steffen Pingel
@@ -26,6 +27,7 @@
 		TestSuite suite = new TestSuite(AllNotificationsTests.class.getName());
 		suite.addTestSuite(NotificationEnvironmentTest.class);
 		suite.addTestSuite(FeedReaderTest.class);
+		suite.addTestSuite(ServiceMessageManagerTest.class);
 		return suite;
 	}
 
diff --git a/org.eclipse.mylyn.commons.notifications.tests/src/org/eclipse/mylyn/commons/notifications/tests/feed/ServiceMessageManagerTest.java b/org.eclipse.mylyn.commons.notifications.tests/src/org/eclipse/mylyn/commons/notifications/tests/feed/ServiceMessageManagerTest.java
index ff975eb..eeabac6 100644
--- a/org.eclipse.mylyn.commons.notifications.tests/src/org/eclipse/mylyn/commons/notifications/tests/feed/ServiceMessageManagerTest.java
+++ b/org.eclipse.mylyn.commons.notifications.tests/src/org/eclipse/mylyn/commons/notifications/tests/feed/ServiceMessageManagerTest.java
@@ -11,9 +11,10 @@
 
 package org.eclipse.mylyn.commons.notifications.tests.feed;
 
+import java.net.HttpURLConnection;
+
 import junit.framework.TestCase;
 
-import org.apache.commons.httpclient.HttpStatus;
 import org.eclipse.core.runtime.NullProgressMonitor;
 import org.eclipse.mylyn.commons.notifications.feed.ServiceMessageManager;
 import org.eclipse.mylyn.internal.commons.notifications.feed.ServiceMessage;
@@ -23,12 +24,12 @@
  */
 public class ServiceMessageManagerTest extends TestCase {
 
-	private static final String MESSAGE_XML_URL = "http://mylyn.eclipse.org/message.xml";
+	private static final String MESSAGE_XML_URL = "http://mylyn.org/message.xml";
 
 	public void testRetrievingMessage() throws Exception {
 		ServiceMessageManager manager = new ServiceMessageManager(MESSAGE_XML_URL, "", "", 0l);
 		int status = manager.refresh(new NullProgressMonitor());
-		assertEquals(HttpStatus.SC_OK, status);
+		assertEquals(HttpURLConnection.HTTP_OK, status);
 		assertEquals(2, manager.getServiceMessages().size());
 
 		ServiceMessage message = manager.getServiceMessages().get(1);
@@ -36,21 +37,20 @@
 		assertEquals("140 character description here....", message.getDescription());
 		assertEquals("Mylyn 3.4 now available!", message.getTitle());
 		assertEquals("http://eclipse.org/mylyn/downloads", message.getUrl());
-		assertEquals("Mylyn 3.4 now available!", message.getTitle());
 		assertEquals("dialog_messasge_info_image", message.getImage());
 	}
 
 	public void testETag() throws Exception {
 		ServiceMessageManager manager = new ServiceMessageManager(MESSAGE_XML_URL, "", "", 0l);
 		int status = manager.refresh(new NullProgressMonitor());
-		assertEquals(HttpStatus.SC_OK, status);
+		assertEquals(HttpURLConnection.HTTP_OK, status);
 		ServiceMessage message = manager.getServiceMessages().get(0);
 
 		assertNotNull(message.getLastModified());
 		assertNotNull(message.getETag());
 
 		status = manager.refresh(new NullProgressMonitor());
-		assertEquals(HttpStatus.SC_NOT_MODIFIED, status);
+		assertEquals(HttpURLConnection.HTTP_NOT_MODIFIED, status);
 	}
 
 }
diff --git a/org.eclipse.mylyn.commons.notifications.tests/testdata/ServiceMessageManagerTest/message.xml b/org.eclipse.mylyn.commons.notifications.tests/testdata/ServiceMessageManagerTest/message.xml
new file mode 100644
index 0000000..06e2310
--- /dev/null
+++ b/org.eclipse.mylyn.commons.notifications.tests/testdata/ServiceMessageManagerTest/message.xml
@@ -0,0 +1,16 @@
+<rss>
+<channel>
+<item>
+<guid>0</guid>
+<pubDate>Fri, 27 May 2011 12:00:00 +0000</pubDate>
+</item>
+<item>
+<guid>1</guid>
+<pubDate>Fri, 27 May 2011 12:00:00 +0000</pubDate>
+<description>140 character description here....</description>
+<title>Mylyn 3.4 now available!</title>
+<link>http://eclipse.org/mylyn/downloads</link>
+<image>dialog_messasge_info_image</image>
+</item>
+</channel>
+</rss>
\ No newline at end of file
diff --git a/org.eclipse.mylyn.commons.sdk-feature/feature.xml b/org.eclipse.mylyn.commons.sdk-feature/feature.xml
index 8312aa8..3317c7e 100644
--- a/org.eclipse.mylyn.commons.sdk-feature/feature.xml
+++ b/org.eclipse.mylyn.commons.sdk-feature/feature.xml
@@ -274,13 +274,6 @@
          unpack="false"/>
 
    <plugin
-         id="org.jdom"
-         download-size="0"
-         install-size="0"
-         version="0.0.0"
-         unpack="false"/>
-
-   <plugin
          id="com.google.gson"
          download-size="0"
          install-size="0"
@@ -288,13 +281,6 @@
          unpack="false"/>
 
    <plugin
-         id="com.sun.syndication"
-         download-size="0"
-         install-size="0"
-         version="0.0.0"
-         unpack="false"/>
-
-   <plugin
          id="org.apache.httpcomponents.httpcore"
          download-size="0"
          install-size="0"