mirror of https://github.com/sipwise/jitsi.git
parent
83b841bb40
commit
3ce23a1e74
@ -0,0 +1,508 @@
|
||||
/*
|
||||
* SIP Communicator, the OpenSource Java VoIP and Instant Messaging client.
|
||||
*
|
||||
* Distributable under LGPL license.
|
||||
* See terms of license at gnu.org.
|
||||
*/
|
||||
package net.java.sip.communicator.slick.protocol.rss;
|
||||
|
||||
/**
|
||||
* This class produces the RSS samples we use in our tests. Right now we're
|
||||
* using excerpts from a real life feed, but that could change to a more
|
||||
* lightweight approach.
|
||||
*
|
||||
* Feed components are stored as inline string to minimize overhead while
|
||||
* testing.
|
||||
*
|
||||
* @author Mihai Balan
|
||||
*/
|
||||
public class FeedFactory {
|
||||
/**
|
||||
* String representing the header of a RSS feed.
|
||||
*/
|
||||
private static String rssHeader =
|
||||
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
|
||||
+"<rss version=\"2.0\""
|
||||
+" xmlns:content=\"http://purl.org/rss/1.0/modules/content/\""
|
||||
+" xmlns:wfw=\"http://wellformedweb.org/CommentAPI/\""
|
||||
+" xmlns:dc=\"http://purl.org/dc/elements/1.1/\">"
|
||||
+" <channel>"
|
||||
+" <title>miChou's photoblog</title>"
|
||||
+" <link>http://mihaibalan.wordpress.com</link>"
|
||||
+" <description>The world through my eyes</description>"
|
||||
+" <pubDate>Mon, 20 Aug 2007 22:20:57 +0000</pubDate>"
|
||||
+" <generator>http://wordpress.org/?v=MU</generator>"
|
||||
+" <language>ro</language>";
|
||||
|
||||
/**
|
||||
* String containing the body of a RSS feed.
|
||||
*/
|
||||
private static String rssBody =
|
||||
" <item>"
|
||||
+" <title>Milky wave</title>"
|
||||
+" <link>http://mihaibalan.wordpress.com/2007/08/15/milky-wave/</link>"
|
||||
+" <comments>http://mihaibalan.wordpress.com/2007/08/15/milky-wave/#co"
|
||||
+"mments</comments>"
|
||||
+" <pubDate>Tue, 14 Aug 2007 22:02:48 +0000</pubDate>"
|
||||
+" <dc:creator>mich0u</dc:creator>"
|
||||
+" <category><![CDATA[flash]]></category>"
|
||||
+" <guid isPermaLink=\"false\">http://mihaibalan.wordpress.com/2007/08"
|
||||
+"/15/milky-wave/</guid>"
|
||||
+" <description><![CDATA["
|
||||
+"]]></description>"
|
||||
+" <content:encoded><![CDATA[<div class='snap_preview'><p align=\"cent"
|
||||
+"er\"><a href=\"http://www.flickr.com/photos/mi-chou/1092690810/\" title="
|
||||
+"\"Photo Sharing\"><img src=\"http://farm2.static.flickr.com/1419/10926908"
|
||||
+"10_79510d9695.jpg\" alt=\"Milky wave\" style=\"border:medium none;\" heig"
|
||||
+"ht=\"288\" width=\"500\" /></a></p>"
|
||||
+"</div>]]></content:encoded>"
|
||||
+" <wfw:commentRss>http://mihaibalan.wordpress.com/2007/08/15/milky-"
|
||||
+"wave/feed/</wfw:commentRss>"
|
||||
+" </item>"
|
||||
+" <item>"
|
||||
+" <title>Light patterns</title>"
|
||||
+" <link>http://mihaibalan.wordpress.com/2007/08/14/light-patterns/</"
|
||||
+"link>"
|
||||
+" <comments>http://mihaibalan.wordpress.com/2007/08/14/light-pattern"
|
||||
+"s/#comments</comments>"
|
||||
+" <pubDate>Mon, 13 Aug 2007 22:02:32 +0000</pubDate>"
|
||||
+" <dc:creator>mich0u</dc:creator>"
|
||||
+" <category><![CDATA[dark]]></category>"
|
||||
+" <category><![CDATA[architecture]]></category>"
|
||||
+" <guid isPermaLink=\"false\">http://mihaibalan.wordpress.com/2007/08"
|
||||
+"/14/light-patterns/</guid>"
|
||||
+" <description><![CDATA["
|
||||
+"]]></description>"
|
||||
+" <content:encoded><![CDATA[<div class='snap_preview'><p align=\"cent"
|
||||
+"er\"><a href=\"http://www.flickr.com/photos/mi-chou/1091949941/\" title="
|
||||
+"\"Photo Sharing\"><img src=\"http://farm2.static.flickr.com/1055/10919499"
|
||||
+"41_34853b5130.jpg\" alt=\"Light patterns\" style=\"border:medium none;\" "
|
||||
+"height=\"386\" width=\"500\" /></a></p>"
|
||||
+"</div>]]></content:encoded>"
|
||||
+" <wfw:commentRss>http://mihaibalan.wordpress.com/2007/08/14/light-p"
|
||||
+"atterns/feed/</wfw:commentRss>"
|
||||
+" </item>";
|
||||
|
||||
/**
|
||||
* String containing the updates to the RSS feed.
|
||||
*/
|
||||
private static String rssBodyUpdate =
|
||||
" <item>"
|
||||
+" <title>Tuig - The show goes on</title>"
|
||||
+" <link>http://mihaibalan.wordpress.com/2007/08/17/tuig-the-show-goes"
|
||||
+"-on/</link>"
|
||||
+" <comments>http://mihaibalan.wordpress.com/2007/08/17/tuig-the-show"
|
||||
+"-goes-on/#comments</comments>"
|
||||
+" <pubDate>Thu, 16 Aug 2007 22:05:53 +0000</pubDate>"
|
||||
+" <dc:creator>mich0u</dc:creator>"
|
||||
+" <category><![CDATA[water]]></category>"
|
||||
+" <category><![CDATA[people]]></category>"
|
||||
+" <guid isPermaLink=\"false\">http://mihaibalan.wordpress.com/2007/08"
|
||||
+"/17/tuig-the-show-goes-on/</guid>"
|
||||
+" <description><![CDATA["
|
||||
+"]]></description>"
|
||||
+" <content:encoded><![CDATA[<div class='snap_preview'><p align=\"cen"
|
||||
+"ter\"><a href=\"http://www.flickr.com/photos/mi-chou/1030251126/\" title="
|
||||
+"\"Photo Sharing\"><img src=\"http://farm2.static.flickr.com/1361/10302511"
|
||||
+"26_9a5d311039.jpg\" alt=\"Tuig - The show goes on\" style=\"border:medium"
|
||||
+" none;\" height=\"340\" width=\"500\" /></a></p>"
|
||||
+"</div>]]></content:encoded>"
|
||||
+" <wfw:commentRss>http://mihaibalan.wordpress.com/2007/08/17/tuig-the"
|
||||
+"-show-goes-on/feed/</wfw:commentRss>"
|
||||
+" </item>"
|
||||
+" <item>"
|
||||
+" <title>Tuig - Patiently waiting</title>"
|
||||
+" <link>http://mihaibalan.wordpress.com/2007/08/16/tuig-patiently-wai"
|
||||
+"ting/</link>"
|
||||
+" <comments>http://mihaibalan.wordpress.com/2007/08/16/tuig-patiently"
|
||||
+"-waiting/#comments</comments>"
|
||||
+" <pubDate>Wed, 15 Aug 2007 22:03:55 +0000</pubDate>"
|
||||
+" <dc:creator>mich0u</dc:creator>"
|
||||
+" <category><![CDATA[sky]]></category>"
|
||||
+" <category><![CDATA[urban]]></category>"
|
||||
+" <category><![CDATA[dark]]></category>"
|
||||
+" <guid isPermaLink=\"false\">http://mihaibalan.wordpress.com/2007/0"
|
||||
+"8/16/tuig-patiently-waiting/</guid>"
|
||||
+" <description><![CDATA["
|
||||
+"]]></description>"
|
||||
+" <content:encoded><![CDATA[<div class='snap_preview'><p align=\"cent"
|
||||
+"er\"><a href=\"http://www.flickr.com/photos/mi-chou/1030250394/\" title="
|
||||
+"\"Photo Sharing\"><img src=\"http://farm2.static.flickr.com/1029/10302503"
|
||||
+"94_687df58297.jpg\" alt=\"Tuig - Patiently waiting\" style=\"border:mediu"
|
||||
+"m none;\" height=\"500\" width=\"410\" /></a></p>"
|
||||
+"<p> <a href=\"http://mihaibalan.wordpress.com/2007/08/16/tuig-patiently-w"
|
||||
+"aiting/#more-118\" class=\"more-link\">(more…)</a></p>"
|
||||
+"</div>]]></content:encoded>"
|
||||
+" <wfw:commentRss>http://mihaibalan.wordpress.com/2007/08/16/tuig-pa"
|
||||
+"tiently-waiting/feed/</wfw:commentRss>"
|
||||
+" </item>";
|
||||
|
||||
/**
|
||||
* String containing the body of a new RSS feed.
|
||||
*/
|
||||
private static String rssBodyNew = " <item>"
|
||||
+" <title>I see trees of green and skies of blue</title>"
|
||||
+" <link>http://mihaibalan.wordpress.com/2007/08/21/i-see-trees-of-gr"
|
||||
+"een-and-skies-of-blue/</link>"
|
||||
+" <comments>http://mihaibalan.wordpress.com/2007/08/21/i-see-trees-of"
|
||||
+"-green-and-skies-of-blue/#comments</comments>"
|
||||
+" <pubDate>Mon, 20 Aug 2007 22:20:57 +0000</pubDate>"
|
||||
+" <dc:creator>mich0u</dc:creator>"
|
||||
+" <category><![CDATA[tree]]></category>"
|
||||
+" <category><![CDATA[bucharest]]></category>"
|
||||
+" <category><![CDATA[architecture]]></category>"
|
||||
+" <guid isPermaLink=\"false\">http://mihaibalan.wordpress.com/2007"
|
||||
+"/08/21/i-see-trees-of-green-and-skies-of-blue/</guid>"
|
||||
+" <description><![CDATA["
|
||||
+"]]></description>"
|
||||
+" <content:encoded><![CDATA[<div class='snap_preview'><p align=\"cent"
|
||||
+"er\"><a href=\"http://www.zooomr.com/photos/michou/2997760/\" title=\"Ph"
|
||||
+"oto Sharing\"><img src=\"http://static.zooomr.com/images/2997760_f5a39d2a"
|
||||
+"db.jpg\" alt=\"I see trees of green, and skies of blue\" style=\"border:"
|
||||
+"medium none;\" height=\"340\" width=\"500\" /></a></p>"
|
||||
+"</div>]]></content:encoded>"
|
||||
+" <wfw:commentRss>http://mihaibalan.wordpress.com/2007/08/21/i-see"
|
||||
+"-trees-of-green-and-skies-of-blue/feed/</wfw:commentRss>"
|
||||
+" </item>"
|
||||
+" <item>"
|
||||
+" <title>Tuig - If I could turn back time</title>"
|
||||
+" <link>http://mihaibalan.wordpress.com/2007/08/20/tuig-if-i-could-"
|
||||
+"turn-back-time/</link>"
|
||||
+" <comments>http://mihaibalan.wordpress.com/2007/08/20/tuig-if-i-"
|
||||
+"could-turn-back-time/#comments</comments>"
|
||||
+" <pubDate>Sun, 19 Aug 2007 22:05:53 +0000</pubDate>"
|
||||
+" <dc:creator>mich0u</dc:creator>"
|
||||
+" <category><![CDATA[light]]></category>"
|
||||
+" <category><![CDATA[long exposure]]></category>"
|
||||
+" <category><![CDATA[dark]]></category>"
|
||||
+" <guid isPermaLink=\"false\">http://mihaibalan.wordpress.com/2007/"
|
||||
+"08/20/tuig-if-i-could-turn-back-time/</guid>"
|
||||
+" <description><![CDATA["
|
||||
+"]]></description>"
|
||||
+" <content:encoded><![CDATA[<div class='snap_preview'><p align=\"cent"
|
||||
+"er\"><a href=\"http://www.flickr.com/photos/mi-chou/1029399905/\" title="
|
||||
+"\"Photo Sharing\"><img src=\"http://farm2.static.flickr.com/1191/10293999"
|
||||
+"05_08e5d41b89.jpg\" alt=\"Tuig - If I could roll back time\" style=\""
|
||||
+"border:medium none;\" height=\"383\" width=\"500\" /></a></p>"
|
||||
+"<p> <a href=\"http://mihaibalan.wordpress.com/2007/08/20/tuig-if-i-could-"
|
||||
+"turn-back-time/#more-122\" class=\"more-link\">(more…)</a></p>"
|
||||
+"</div>]]></content:encoded>"
|
||||
+" <wfw:commentRss>http://mihaibalan.wordpress.com/2007/08/20/tuig-if"
|
||||
+"-i-could-turn-back-time/feed/</wfw:commentRss>"
|
||||
+" </item>";
|
||||
|
||||
/**
|
||||
* String containing some invalid mark-up in the RSS feed.
|
||||
*/
|
||||
private static String rssBodyInvalid =
|
||||
"<some-invalid-tag attr='value1'>Lorem ipsum</some-invalid-tg>";
|
||||
|
||||
/**
|
||||
* String containing the footer of a RSS feed.
|
||||
*/
|
||||
private static String rssFooter = "</channel></rss>";
|
||||
|
||||
/**
|
||||
* String containing the header of a ATOM feed.
|
||||
*/
|
||||
private static String atomHeader =
|
||||
"<?xml version='1.0' encoding='UTF-8'?>"
|
||||
+"<?xml-stylesheet href=\"http://www.blogger.com/styles/atom.css\" type=\""
|
||||
+"text/css\"?>"
|
||||
+"<feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.co"
|
||||
+"m/-/spec/opensearchrss/1.0/'>"
|
||||
+" <id>tag:blogger.com,1999:blog-3490925879145756058</id><updated>2007-"
|
||||
+"08-08T10:24:42.424-07:00</updated><title type='text'>miChou's Summer of "
|
||||
+"Code blog</title><link rel='alternate' type='text/html' href='http://ete"
|
||||
+"-de-code-a-la-chou.blogspot.com/'/>"
|
||||
+" <link rel='http://schemas.google.com/g/2005#feed' type='application/"
|
||||
+"atom+xml' href='http://ete-de-code-a-la-chou.blogspot.com/feeds/posts/de"
|
||||
+"fault'/>"
|
||||
+" <link rel='self' type='application/atom+xml' href='http://ete-de-cod"
|
||||
+"e-a-la-chou.blogspot.com/feeds/posts/default'/>"
|
||||
+" <author>"
|
||||
+" <name>Mihai Balan</name>"
|
||||
+" </author>"
|
||||
+" <generator version='7.00' uri='http://www.blogger.com'>Blogger</gene"
|
||||
+"rator><openSearch:totalResults>6</openSearch:totalResults><openSearch:st"
|
||||
+"artIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearc"
|
||||
+"h:itemsPerPage>";
|
||||
|
||||
/**
|
||||
* String containing the body of an ATOM feed.
|
||||
*/
|
||||
private static String atomBody =
|
||||
"<entry><id>tag:blogger.com,1999:blog-3490925879145756058.post-445569517"
|
||||
+"5541848605</id><published>2007-06-05T02:15:00.000-07:00</published><upda"
|
||||
+"ted>2007-06-05T03:34:35.892-07:00</updated><category scheme='http://www."
|
||||
+"blogger.com/atom/ns#' term='soc'/>"
|
||||
+" <category scheme='http://www.blogger.com/atom/ns#' term='todo'/>"
|
||||
+""
|
||||
+" <title type='text'>Happy hacking!</title><content type='html'>Fi"
|
||||
+"nally the second semester is over, and the summer exams sessions is abou"
|
||||
+"t to begin (that means I have the first exam tomorrow - Digital Computer"
|
||||
+"s 2).And in between all this, I should also get my exams going :)</conte"
|
||||
+"nt><link rel='alternate' type='text/html' href='http://ete-de-code-a-la-"
|
||||
+"chou.blogspot.com/2007/06/happy-hacking.html' title='Happy hacking!'/>"
|
||||
+" <link rel='replies' type='text/html' href='http://www.blogger.co"
|
||||
+"m/comment.g?blogID=3490925879145756058&postID=4455695175541848605' t"
|
||||
+"itle='0 Comments'/>"
|
||||
+" <link rel='replies' type='application/atom+xml' href='http://ete"
|
||||
+"-de-code-a-la-chou.blogspot.com/feeds/4455695175541848605/comments/defau"
|
||||
+"lt' title='Post Comments'/>"
|
||||
+" <link rel='self' type='application/atom+xml' href='http://ete-de"
|
||||
+"-code-a-la-chou.blogspot.com/feeds/posts/default/4455695175541848605'/>"
|
||||
+" <link rel='edit' type='application/atom+xml' href='http://www.bl"
|
||||
+"ogger.com/feeds/3490925879145756058/posts/default/4455695175541848605'/>"
|
||||
+""
|
||||
+" <author>"
|
||||
+" <name>Mihai Balan</name>"
|
||||
+" </author>"
|
||||
+" </entry>"
|
||||
+" <entry>"
|
||||
+" <id>tag:blogger.com,1999:blog-3490925879145756058.post-160551373"
|
||||
+"861169805</id><published>2007-05-31T13:34:00.000-07:00</published><updat"
|
||||
+"ed>2007-06-01T04:21:00.167-07:00</updated><category scheme='http://www.b"
|
||||
+"logger.com/atom/ns#' term='soc'/>"
|
||||
+" <category scheme='http://www.blogger.com/atom/ns#' term='francai"
|
||||
+"s'/>"
|
||||
+" <category scheme='http://www.blogger.com/atom/ns#' term='bla-bla"
|
||||
+"'/>"
|
||||
+" <title type='text'>Un debut attarde</title><content type='html'>"
|
||||
+"<span style=\"font-style: italic;font-size:100%;\" ><span style="
|
||||
+"\"font-family:georgia;\">Bien qu'on m'ait dit que toute communication "
|
||||
+"regardant SIP se fera en anglais je prends le risque d'ecrire ce premier "
|
||||
+"post en francais.</content><link rel='alternate' type='text/html' href='h"
|
||||
+"ttp://ete-de-code-a-la-chou.blogspot.com/2007/05/un-debut-attarde.html' "
|
||||
+"title='Un debut attarde'/>"
|
||||
+" <link rel='replies' type='text/html' href='http://www.blogger.co"
|
||||
+"m/comment.g?blogID=3490925879145756058&postID=160551373861169805' ti"
|
||||
+"tle='0 Comments'/>"
|
||||
+" <link rel='replies' type='application/atom+xml' href='http://ete"
|
||||
+"-de-code-a-la-chou.blogspot.com/feeds/160551373861169805/comments/defaul"
|
||||
+"t' title='Post Comments'/>"
|
||||
+" <link rel='self' type='application/atom+xml' href='http://ete-de"
|
||||
+"-code-a-la-chou.blogspot.com/feeds/posts/default/160551373861169805'/>"
|
||||
+" <link rel='edit' type='application/atom+xml' href='http://www.bl"
|
||||
+"ogger.com/feeds/3490925879145756058/posts/default/160551373861169805'/>"
|
||||
+" <author>"
|
||||
+" <name>Mihai Balan</name>"
|
||||
+" </author>"
|
||||
+" </entry>";
|
||||
|
||||
/**
|
||||
* String containing the updates to the ATOM feed.
|
||||
*/
|
||||
private static String atomBodyUpdate =
|
||||
"<entry><id>tag:blogger.com,1999:blog-3490925879145756058.post-722978588"
|
||||
+"3825532193</id><published>2007-06-25T14:29:00.000-07:00</published><upda"
|
||||
+"ted>2007-06-26T06:12:44.479-07:00</updated><category scheme='http://www."
|
||||
+"blogger.com/atom/ns#' term='bugzilla'/>"
|
||||
+" <category scheme='http://www.blogger.com/atom/ns#' term='todo'/>"
|
||||
+""
|
||||
+" <category scheme='http://www.blogger.com/atom/ns#' term='google'"
|
||||
+"/>"
|
||||
+" <category scheme='http://www.blogger.com/atom/ns#' term='rss'/>"
|
||||
+" <title type='text'>Google politics</title><content type='html'>O"
|
||||
+"ne of the problems well known in the current implementation of the RSS s"
|
||||
+"upport in SIP Communicator was the inability to retrieve feeds from news"
|
||||
+".google.com (and you must admit, news.google.com is quite a source of ne"
|
||||
+"ws ;) ).<br /><br /> A brief look at the exception returned"
|
||||
+" by the plugin points out the problem. The server is sending a HTTP/403 "
|
||||
+"(Forbidden) response code instead of the HTTP/200 (OK) response code.</c"
|
||||
+"ontent><link rel='alternate' type='text/html' href='http://ete-de-code-a"
|
||||
+"-la-chou.blogspot.com/2007/06/google-politics.html' title='Google politi"
|
||||
+"cs'/>"
|
||||
+" <link rel='replies' type='text/html' href='http://www.blogger.co"
|
||||
+"m/comment.g?blogID=3490925879145756058&postID=7229785883825532193' t"
|
||||
+"itle='0 Comments'/>"
|
||||
+" <link rel='replies' type='application/atom+xml' href='http://ete"
|
||||
+"-de-code-a-la-chou.blogspot.com/feeds/7229785883825532193/comments/defau"
|
||||
+"lt' title='Post Comments'/>"
|
||||
+" <link rel='self' type='application/atom+xml' href='http://ete-de"
|
||||
+"-code-a-la-chou.blogspot.com/feeds/posts/default/7229785883825532193'/>"
|
||||
+" <link rel='edit' type='application/atom+xml' href='http://www.bl"
|
||||
+"ogger.com/feeds/3490925879145756058/posts/default/7229785883825532193'/>"
|
||||
+""
|
||||
+" <author>"
|
||||
+" <name>Mihai Balan</name>"
|
||||
+" </author>"
|
||||
+" </entry>";
|
||||
|
||||
/**
|
||||
* String containing a new ATOM feed.
|
||||
*/
|
||||
private static String atomBodyNew =
|
||||
"<entry><id>tag:blogger.com,1999:blog-3490925879145756058.post-325829288"
|
||||
+"5225110686</id><published>2007-08-08T09:59:00.000-07:00</published><upda"
|
||||
+"ted>2007-08-08T10:24:42.470-07:00</updated><category scheme='http://www."
|
||||
+"blogger.com/atom/ns#' term='todo'/>"
|
||||
+" <category scheme='http://www.blogger.com/atom/ns#' term='new fea"
|
||||
+"ture'/>"
|
||||
+" <category scheme='http://www.blogger.com/atom/ns#' term='emil'/>"
|
||||
+""
|
||||
+" <category scheme='http://www.blogger.com/atom/ns#' term='rss'/>"
|
||||
+" <title type='text'>check out. again...</title><content type='htm"
|
||||
+"l'><div style=\"text-align: justify;\">It seems I do have a strange"
|
||||
+" problem when it comes to using CVS. It's not version control systems in "
|
||||
+"general, but CVS. Or at least, the CVS I'm using here, on Sip Communicat"
|
||||
+"or. Somehow, I never get it right.</content><link rel='alternate' type='"
|
||||
+"text/html' href='http://ete-de-code-a-la-chou.blogspot.com/2007/08/check"
|
||||
+"-out-again.html' title='check out. again...'/>"
|
||||
+" <link rel='replies' type='text/html' href='http://www.blogger.co"
|
||||
+"m/comment.g?blogID=3490925879145756058&postID=3258292885225110686' t"
|
||||
+"itle='0 Comments'/>"
|
||||
+" <link rel='replies' type='application/atom+xml' href='http://ete"
|
||||
+"-de-code-a-la-chou.blogspot.com/feeds/3258292885225110686/comments/defau"
|
||||
+"lt' title='Post Comments'/>"
|
||||
+" <link rel='self' type='application/atom+xml' href='http://ete-de"
|
||||
+"-code-a-la-chou.blogspot.com/feeds/posts/default/3258292885225110686'/>"
|
||||
+" <link rel='edit' type='application/atom+xml' href='http://www.bl"
|
||||
+"ogger.com/feeds/3490925879145756058/posts/default/3258292885225110686'/>"
|
||||
+""
|
||||
+" <author>"
|
||||
+" <name>Mihai Balan</name>"
|
||||
+" </author>"
|
||||
+" </entry>"
|
||||
+" <entry>"
|
||||
+" <id>tag:blogger.com,1999:blog-3490925879145756058.post-186104691"
|
||||
+"5714479007</id><published>2007-07-06T13:23:00.000-07:00</published><upda"
|
||||
+"ted>2007-07-06T13:54:46.478-07:00</updated><category scheme='http://www."
|
||||
+"blogger.com/atom/ns#' term='new feature'/>"
|
||||
+" <category scheme='http://www.blogger.com/atom/ns#' term='questio"
|
||||
+"n'/>"
|
||||
+" <category scheme='http://www.blogger.com/atom/ns#' term='rss'/>"
|
||||
+" <title type='text'>Favicon - check!</title><content type='html'>"
|
||||
+"<div style=\"text-align: justify;\">Finally, favicon retrieval supp"
|
||||
+"ort is here. What is this all about? Almost all IM protocols out there al"
|
||||
+"low you to specify and associate an image to your account (a so called a"
|
||||
+"vatar), either natively (e.g. Y!M), either through extensions (e.g. XMPP"
|
||||
+"/Jabber).</content><link rel='alternate' type='text/html' href='http://e"
|
||||
+"te-de-code-a-la-chou.blogspot.com/2007/07/favicon-check.html' title='Fav"
|
||||
+"icon - check!'/>"
|
||||
+" <link rel='replies' type='text/html' href='http://www.blogger.co"
|
||||
+"m/comment.g?blogID=3490925879145756058&postID=1861046915714479007' t"
|
||||
+"itle='0 Comments'/>"
|
||||
+" <link rel='replies' type='application/atom+xml' href='http://ete"
|
||||
+"-de-code-a-la-chou.blogspot.com/feeds/1861046915714479007/comments/defau"
|
||||
+"lt' title='Post Comments'/>"
|
||||
+" <link rel='self' type='application/atom+xml' href='http://ete-de"
|
||||
+"-code-a-la-chou.blogspot.com/feeds/posts/default/1861046915714479007'/>"
|
||||
+" <link rel='edit' type='application/atom+xml' href='http://www.bl"
|
||||
+"ogger.com/feeds/3490925879145756058/posts/default/1861046915714479007'/>"
|
||||
+""
|
||||
+" <author>"
|
||||
+" <name>Mihai Balan</name>"
|
||||
+" </author>"
|
||||
+" </entry>"
|
||||
+" <entry>"
|
||||
+" <id>tag:blogger.com,1999:blog-3490925879145756058.post-717349866"
|
||||
+"079669848</id><published>2007-06-29T12:35:00.000-07:00</published><updat"
|
||||
+"ed>2007-06-29T12:39:34.816-07:00</updated><category scheme='http://www.b"
|
||||
+"logger.com/atom/ns#' term='bugzilla'/>"
|
||||
+" <category scheme='http://www.blogger.com/atom/ns#' term='todo'/>"
|
||||
+""
|
||||
+" <title type='text'>Interim objectives</title><content type='html"
|
||||
+"'>I know I've been a little late setting these, but now it's kinda' sett"
|
||||
+"led.</content><link rel='alternate' type='text/html' href='http://ete-de"
|
||||
+"-code-a-la-chou.blogspot.com/2007/06/interim-objectives.html' title='Int"
|
||||
+"erim objectives'/>"
|
||||
+" <link rel='replies' type='text/html' href='http://www.blogger.co"
|
||||
+"m/comment.g?blogID=3490925879145756058&postID=717349866079669848' ti"
|
||||
+"tle='0 Comments'/>"
|
||||
+" <link rel='replies' type='application/atom+xml' href='http://ete"
|
||||
+"-de-code-a-la-chou.blogspot.com/feeds/717349866079669848/comments/defaul"
|
||||
+"t' title='Post Comments'/>"
|
||||
+" <link rel='self' type='application/atom+xml' href='http://ete-de"
|
||||
+"-code-a-la-chou.blogspot.com/feeds/posts/default/717349866079669848'/>"
|
||||
+" <link rel='edit' type='application/atom+xml' href='http://www.bl"
|
||||
+"ogger.com/feeds/3490925879145756058/posts/default/717349866079669848'/>"
|
||||
+" <author>"
|
||||
+" <name>Mihai Balan</name>"
|
||||
+" </author>"
|
||||
+" </entry>";
|
||||
|
||||
/**
|
||||
* String containing some invalid markup in the ATOM feed.
|
||||
*/
|
||||
private static String atomBodyInvalid =
|
||||
"<some-invalid-tag attr='value1'>Lorem ipsum</some-invalid-tg>";
|
||||
|
||||
/**
|
||||
* String containing the footer of the ATOM feed.
|
||||
*/
|
||||
private static String atomFooter = "</feed>";
|
||||
|
||||
/**
|
||||
* Returns a <code>String</code> representing an RSS feed.
|
||||
* @return textual representation of the RSS feed.
|
||||
*/
|
||||
public static String getRss()
|
||||
{
|
||||
return rssHeader + rssBody + rssFooter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a <code>String</code> representing the updated RSS feed.
|
||||
* @return textual representation of the RSS feed.
|
||||
*/
|
||||
public static String getRssUpdated()
|
||||
{
|
||||
return rssHeader + rssBodyUpdate + rssBody + rssFooter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a <code>String</code> representing a new version of the RSS feed.
|
||||
* @return textual representation of the RSS feed.
|
||||
*/
|
||||
public static String getRssNew()
|
||||
{
|
||||
return rssHeader + rssBodyNew + rssFooter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a <code>String</code> representing an invalid RSS feed.
|
||||
* @return textual representation of the RSS feed.
|
||||
*/
|
||||
public static String getRssInvalid()
|
||||
{
|
||||
return rssHeader + rssBodyInvalid + rssFooter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a <code>String</code> representing an ATOM feed.
|
||||
* @return textual representation of the RSS feed.
|
||||
*/
|
||||
public static String getAtom()
|
||||
{
|
||||
return atomHeader + atomBody + atomFooter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a <code>String</code> representing the updated ATOM feed.
|
||||
* @return textual representation of the RSS feed.
|
||||
*/
|
||||
public static String getAtomUpdated()
|
||||
{
|
||||
return atomHeader + atomBodyUpdate + atomBody + atomFooter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a <code>String</code> representing a new version of the ATOM
|
||||
* feed.
|
||||
* @return textual representation of the RSS feed.
|
||||
*/
|
||||
public static String getAtomNew()
|
||||
{
|
||||
return atomHeader + atomBodyNew + atomFooter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a <code>String</code> representing an invalid ATOM feed.
|
||||
* @return textual representation of the RSS feed.
|
||||
*/
|
||||
public static String getAtomInvalid()
|
||||
{
|
||||
return atomHeader + atomBodyInvalid + atomFooter;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,67 @@
|
||||
/*
|
||||
* SIP Communicator, the OpenSource Java VoIP and Instant Messaging client.
|
||||
*
|
||||
* Distributable under LGPL license.
|
||||
* See terms of license at gnu.org.
|
||||
*/
|
||||
package net.java.sip.communicator.slick.protocol.rss;
|
||||
|
||||
import java.util.*;
|
||||
import junit.framework.*;
|
||||
import net.java.sip.communicator.util.*;
|
||||
|
||||
import org.osgi.framework.*;
|
||||
|
||||
/**
|
||||
* RSS specific testing for an RSS Protocol provider Service implementation.
|
||||
* [...]
|
||||
* @author Mihai Balan
|
||||
*/
|
||||
public class RssProtocolProviderServiceLick
|
||||
extends TestSuite
|
||||
implements BundleActivator
|
||||
{
|
||||
/**
|
||||
* Initializes and registers all tests that we'll run as a part of this
|
||||
* SLICK.
|
||||
*
|
||||
* @param bundleContext a currently valid bundle context.
|
||||
*/
|
||||
public void start(BundleContext bundleContext)
|
||||
{
|
||||
Logger logger =
|
||||
Logger.getLogger(RssProtocolProviderServiceLick.class);
|
||||
logger.setLevelAll();
|
||||
logger.debug("***Start() called on RSS slick***");
|
||||
|
||||
setName("RssProtocolProviderServiceLick");
|
||||
|
||||
Hashtable properties = new Hashtable();
|
||||
properties.put("service.pid", getName());
|
||||
|
||||
RssSlickFixture.bc = bundleContext;
|
||||
|
||||
//test account installation
|
||||
addTestSuite(TestAccountInstallation.class);
|
||||
|
||||
//test Protocol Provider Service implementation
|
||||
addTestSuite(TestProtocolProviderServiceRssImpl.class);
|
||||
|
||||
//test account uninstallation
|
||||
addTest(TestAccountUninstallation.suite());
|
||||
addTestSuite(TestAccountUninstallationPersistence.class);
|
||||
|
||||
bundleContext.registerService(getClass().getName(), this, properties);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepares the slick for shutdown.
|
||||
*
|
||||
* @param context a currently valid bundle context.
|
||||
*/
|
||||
public void stop(BundleContext context)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,155 @@
|
||||
/*
|
||||
* SIP Communicator, the OpenSource Java VoIP and Instant Messaging client.
|
||||
*
|
||||
* Distributable under LGPL license.
|
||||
* See terms of license at gnu.org.
|
||||
*/
|
||||
package net.java.sip.communicator.slick.protocol.rss;
|
||||
|
||||
import java.util.*;
|
||||
import junit.framework.*;
|
||||
import org.osgi.framework.*;
|
||||
|
||||
import net.java.sip.communicator.service.protocol.*;
|
||||
|
||||
/**
|
||||
* Contains constants and methods used by almost all of our tests.
|
||||
*
|
||||
* @author Mihai Balan
|
||||
*/
|
||||
public class RssSlickFixture
|
||||
extends TestCase
|
||||
{
|
||||
/**
|
||||
* To be set by the slick itself upon activation.
|
||||
*/
|
||||
public static BundleContext bc = null;
|
||||
|
||||
/**
|
||||
* And OSGi service reference for the protocol provider corresponding to our
|
||||
* testing account.
|
||||
*/
|
||||
public ServiceReference providerServiceReference = null;
|
||||
|
||||
/**
|
||||
* Protocol provider corresponding to the testing account.
|
||||
*/
|
||||
public ProtocolProviderService provider = null;
|
||||
|
||||
/**
|
||||
* The user ID associated with the testing account.
|
||||
*/
|
||||
//public String userId = null;
|
||||
|
||||
public ProtocolProviderFactory providerFactory = null;
|
||||
|
||||
/**
|
||||
* A reference to the bundle containing the tested ProtocolProvider
|
||||
* implementation. This reference is set during the account installation
|
||||
* testing and used during the account installation persistence testing.
|
||||
*/
|
||||
public static Bundle providerBundle = null;
|
||||
|
||||
/**
|
||||
* A <code>HashTable</code> containing group names mapped against array
|
||||
* lists of buddy screen names.
|
||||
*/
|
||||
public static Hashtable preInstalledBuddyList = null;
|
||||
//XXX: Do I really need that? :-\
|
||||
|
||||
/**
|
||||
* Initializes protocol provider references and whatever else there is to
|
||||
* initialize.
|
||||
*
|
||||
* @throws java.lang.Exception in case we meet problems while retriving
|
||||
* protocol providers through OSGI
|
||||
*/
|
||||
public void setUp()
|
||||
throws Exception
|
||||
{
|
||||
//get a reference to the provider factory
|
||||
ServiceReference[] serRefs = null;
|
||||
String osgiFilter = "(" + ProtocolProviderFactory.PROTOCOL
|
||||
+ "=" + ProtocolNames.RSS + ")";
|
||||
|
||||
try {
|
||||
serRefs = bc.getServiceReferences(
|
||||
ProtocolProviderFactory.class.getName(), osgiFilter);
|
||||
} catch (InvalidSyntaxException ise)
|
||||
{
|
||||
//shouldn't happen as the filter is static (typos maybe? :D)
|
||||
fail(osgiFilter + "is not a valid OSGi filter");
|
||||
}
|
||||
|
||||
assertTrue("Failed to find a provider factory service for protocol RSS",
|
||||
serRefs != null && serRefs.length > 0);
|
||||
|
||||
providerFactory = (ProtocolProviderFactory)bc.getService(serRefs[0]);
|
||||
|
||||
//find the protocol providers exported for the two accounts
|
||||
ServiceReference[] rssProviderRefs = bc.getServiceReferences(
|
||||
ProtocolProviderService.class.getName(),
|
||||
"(&("+ProtocolProviderFactory.PROTOCOL+"="+ProtocolNames.RSS+"))");
|
||||
|
||||
//make sure we found a service
|
||||
assertNotNull("No protocol provider was found for RSS account ",
|
||||
rssProviderRefs);
|
||||
assertTrue("No protocol provider was found for RSS account",
|
||||
rssProviderRefs.length > 0);
|
||||
|
||||
//save the service for other tests to use.
|
||||
providerServiceReference = rssProviderRefs[0];
|
||||
provider = (ProtocolProviderService)bc.getService(
|
||||
providerServiceReference);
|
||||
}
|
||||
|
||||
/**
|
||||
* Un get service references used in here.
|
||||
*/
|
||||
public void tearDown()
|
||||
{
|
||||
bc.ungetService(providerServiceReference);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the bundle that has registered the protocol provider service
|
||||
* implementation that we're currently testing. The method would go through
|
||||
* all bundles currently installed in the framework and return the first
|
||||
* one that exports the same protocol provider instance as the one we test
|
||||
* in this slick.
|
||||
*
|
||||
* @param provider the provider whose bundle we're looking for.
|
||||
* @return the Bundle that has registered the protocol provider service
|
||||
* we're testing in the slick.
|
||||
*/
|
||||
public static Bundle findProtocolProviderBundle(
|
||||
ProtocolProviderService provider)
|
||||
{
|
||||
Bundle[] bundles = bc.getBundles();
|
||||
|
||||
for (int i = 0; i < bundles.length; i++)
|
||||
{
|
||||
ServiceReference[] registeredServices
|
||||
= bundles[i].getRegisteredServices();
|
||||
|
||||
if (registeredServices == null)
|
||||
continue;
|
||||
|
||||
for (int j = 0; j < registeredServices.length; j++)
|
||||
{
|
||||
Object service
|
||||
= bc.getService(registeredServices[j]);
|
||||
if (service == provider)
|
||||
return bundles[i];
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public void clearProvidersList()
|
||||
throws Exception
|
||||
{
|
||||
//XXX: FTM, do_nothing()
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,133 @@
|
||||
/*
|
||||
* SIP Communicator, the OpenSource Java VoIP and Instant Messaging client.
|
||||
*
|
||||
* Distributable under LGPL license.
|
||||
* See terms of license at gnu.org.
|
||||
*/
|
||||
package net.java.sip.communicator.slick.protocol.rss;
|
||||
|
||||
import org.osgi.framework.*;
|
||||
import net.java.sip.communicator.service.protocol.*;
|
||||
import net.java.sip.communicator.util.*;
|
||||
import junit.framework.*;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Installs a test account and verifies it is available after installation.
|
||||
*
|
||||
* @author Mihai Balan
|
||||
*/
|
||||
public class TestAccountInstallation
|
||||
extends TestCase
|
||||
{
|
||||
private static final Logger logger =
|
||||
Logger.getLogger(TestAccountInstallation.class);
|
||||
|
||||
/**
|
||||
* Creates a test with the specified method name.
|
||||
* @param name the name of the method tu execute.
|
||||
*/
|
||||
public TestAccountInstallation(String name)
|
||||
{
|
||||
super(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* JUnit setup method.
|
||||
*/
|
||||
protected void setUp() throws Exception
|
||||
{
|
||||
super.setUp();
|
||||
}
|
||||
|
||||
/**
|
||||
* JUnit cleanup method.
|
||||
*/
|
||||
protected void tearDown() throws Exception
|
||||
{
|
||||
super.tearDown();
|
||||
}
|
||||
|
||||
/**
|
||||
* Installs and account and verifies whether the installation succedded.
|
||||
*/
|
||||
public void testInstallAccount()
|
||||
{
|
||||
Hashtable accountProperties = new Hashtable();
|
||||
|
||||
ServiceReference[] serRefs = null;
|
||||
String osgiFilter = "(" + ProtocolProviderFactory.PROTOCOL + "="
|
||||
+ ProtocolNames.RSS + ")";
|
||||
|
||||
accountProperties.put(ProtocolProviderFactory.USER_ID, "RSS");
|
||||
|
||||
try {
|
||||
serRefs = RssSlickFixture.bc.getServiceReferences(
|
||||
ProtocolProviderFactory.class.getName(), osgiFilter);
|
||||
} catch (InvalidSyntaxException ise)
|
||||
{
|
||||
//shouldn't happen as the filter is static
|
||||
fail(osgiFilter + "is not a valid filter");
|
||||
}
|
||||
|
||||
//couldn't find a provider factory service.
|
||||
assertTrue("Failed to find a provider factory service or protocol RSS",
|
||||
serRefs != null && serRefs.length > 0);
|
||||
|
||||
ProtocolProviderFactory rssProviderFactory = (ProtocolProviderFactory)
|
||||
RssSlickFixture.bc.getService(serRefs[0]);
|
||||
|
||||
//there shouldn't be any account installed
|
||||
assertTrue("There was an account already registered with the account "
|
||||
+ "manager",
|
||||
rssProviderFactory.getRegisteredAccounts().size() == 0);
|
||||
|
||||
try {
|
||||
rssProviderFactory.installAccount(null, accountProperties);
|
||||
fail("Installing an account with a null account id must result in a"
|
||||
+ " NullPointerException!");
|
||||
} catch(NullPointerException npe)
|
||||
{
|
||||
//that's ought to happen
|
||||
}
|
||||
|
||||
rssProviderFactory.installAccount("RSS", accountProperties);
|
||||
|
||||
//try to install the same account twice and check for exceptions
|
||||
try {
|
||||
rssProviderFactory.installAccount("RSS", accountProperties);
|
||||
fail("An IllegalStateException must be thrown when trying to "
|
||||
+ "install a duplicate account.");
|
||||
} catch(IllegalStateException ise)
|
||||
{
|
||||
//that's ought to happen
|
||||
}
|
||||
|
||||
assertTrue("Newly installed account is not in the account manager's "
|
||||
+ "registered accounts!",
|
||||
rssProviderFactory.getRegisteredAccounts().size() == 1);
|
||||
|
||||
osgiFilter = "(&(" + ProtocolProviderFactory.PROTOCOL + "="
|
||||
+ ProtocolNames.RSS + ")"
|
||||
+ "(" + ProtocolProviderFactory.USER_ID + "=RSS))";
|
||||
|
||||
try {
|
||||
serRefs = RssSlickFixture.bc.getServiceReferences(
|
||||
ProtocolProviderService.class.getName(), osgiFilter);
|
||||
} catch(InvalidSyntaxException ise)
|
||||
{
|
||||
fail(osgiFilter + " is not a valid filter");
|
||||
}
|
||||
|
||||
assertTrue("A protocol provider was apparently not installed as"
|
||||
+ " requested",
|
||||
serRefs != null && serRefs.length > 0);
|
||||
|
||||
Object rssProtocolProvider =
|
||||
RssSlickFixture.bc.getService(serRefs[0]);
|
||||
|
||||
assertTrue("The installed protocol provider does not implement the"
|
||||
+ "protocol provider service.",
|
||||
rssProtocolProvider instanceof ProtocolProviderService);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,211 @@
|
||||
/*
|
||||
* SIP Communicator, the OpenSource Java VoIP and Instant Messaging client.
|
||||
*
|
||||
* Distributable under LGPL license.
|
||||
* See terms of license at gnu.org.
|
||||
*/
|
||||
package net.java.sip.communicator.slick.protocol.rss;
|
||||
|
||||
import junit.framework.*;
|
||||
import org.osgi.framework.*;
|
||||
import net.java.sip.communicator.util.*;
|
||||
import net.java.sip.communicator.service.protocol.*;
|
||||
|
||||
/**
|
||||
* Tests whether accounts are uninstalled properly. It is important that
|
||||
* tests from this class be called last since they will install the accounts
|
||||
* that have been used to test the implementations. Apart from uninstallation
|
||||
* tests the class also contains tests that remove and reinstall the protocol
|
||||
* provider bundle in order to verify that accounts are persistent.
|
||||
*
|
||||
* @author Mihai Balan
|
||||
*/
|
||||
public class TestAccountUninstallation
|
||||
extends TestCase
|
||||
{
|
||||
private Logger logger = Logger.getLogger(TestAccountUninstallation.class);
|
||||
|
||||
private RssSlickFixture fixture = new RssSlickFixture();
|
||||
|
||||
/**
|
||||
* Constructs a test instance
|
||||
* @param name The name of the test.
|
||||
*/
|
||||
public TestAccountUninstallation(String name)
|
||||
{
|
||||
super(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* JUnit setup method.
|
||||
* @throws Exception in case anything goes wrong.
|
||||
*/
|
||||
public void setUp() throws Exception
|
||||
{
|
||||
super.setUp();
|
||||
fixture.setUp();
|
||||
}
|
||||
|
||||
/**
|
||||
* JUnit teardown method.
|
||||
* @throws Exception in case anything goes wrong.
|
||||
*/
|
||||
public void tearDown() throws Exception
|
||||
{
|
||||
fixture.tearDown();
|
||||
super.tearDown();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a suite containing tests in this class in the order that we'd
|
||||
* like them executed.
|
||||
* @return a Test suite containing tests in this class in the order that
|
||||
* we'd like them executed.
|
||||
*/
|
||||
public static Test suite()
|
||||
{
|
||||
TestSuite suite = new TestSuite();
|
||||
|
||||
suite.addTest(
|
||||
new TestAccountUninstallation("testInstallationPersistence"));
|
||||
suite.addTest(
|
||||
new TestAccountUninstallation("testUninstallAccount"));
|
||||
|
||||
return suite;
|
||||
}
|
||||
|
||||
/**
|
||||
* Stops and removes the tested bundle, verifies that it has unregistered
|
||||
* its provider, then reloads and restarts the bundle and verifies that
|
||||
* the protocol provider is reRegistered in the bundle context.
|
||||
*
|
||||
* @throws java.lang.Exception if an exception occurs during testing.
|
||||
*/
|
||||
public void testInstallationPersistence() throws Exception
|
||||
{
|
||||
Bundle providerBundle =
|
||||
fixture.findProtocolProviderBundle(fixture.provider);
|
||||
|
||||
//set the global providerBundle reference that we will be using
|
||||
//in the last series of tests (Account uninstallation persistency)
|
||||
RssSlickFixture.providerBundle = providerBundle;
|
||||
|
||||
assertNotNull("Couldn't find a bundle for the protocol provider",
|
||||
providerBundle);
|
||||
|
||||
providerBundle.stop();
|
||||
assertTrue("Couldn't stop protocol provider bundle. State was "
|
||||
+ providerBundle.getSymbolicName(),
|
||||
providerBundle.getState() != Bundle.ACTIVE
|
||||
&& providerBundle.getState() != Bundle.STOPPING);
|
||||
|
||||
providerBundle.uninstall();
|
||||
assertEquals("Couldn't uninstall protocol provider bundle.",
|
||||
providerBundle.getState(), Bundle.UNINSTALLED);
|
||||
|
||||
//verify that the provider is no longer available
|
||||
ServiceReference providerRefs[] = null;
|
||||
try {
|
||||
providerRefs = fixture.bc.getServiceReferences(
|
||||
ProtocolProviderService.class.getName(),
|
||||
"(&(" + ProtocolProviderFactory.PROTOCOL + "="
|
||||
+ ProtocolNames.RSS + "))");
|
||||
} catch (InvalidSyntaxException ise)
|
||||
{
|
||||
fail("Invalid OSGi filter. Exception was" + ise.getMessage());
|
||||
}
|
||||
|
||||
//verify the provider really uninstalled
|
||||
assertTrue("Protocol provider still present after being explicitly" +
|
||||
" uninstalled",
|
||||
providerRefs == null || providerRefs.length == 0);
|
||||
assertTrue("The RSS protocol provider factory didn't completely "
|
||||
+ "uninstalled the provider service",
|
||||
fixture.providerFactory.getRegisteredAccounts().size() == 0 &&
|
||||
fixture.providerFactory.getProviderForAccount(
|
||||
fixture.provider.getAccountID()) == null);
|
||||
|
||||
//reinstall provider
|
||||
providerBundle = fixture.bc.installBundle(providerBundle.getLocation());
|
||||
RssSlickFixture.providerBundle = providerBundle;
|
||||
|
||||
assertTrue("Couldn't reinstall provider bundle",
|
||||
providerBundle.getState() == Bundle.INSTALLED);
|
||||
|
||||
providerBundle.start();
|
||||
assertTrue("Couldn't start provider",
|
||||
providerBundle.getState() == Bundle.ACTIVE);
|
||||
|
||||
providerRefs = null;
|
||||
try {
|
||||
providerRefs = fixture.bc.getServiceReferences(
|
||||
ProtocolProviderService.class.getName(),
|
||||
"(&(" + ProtocolProviderFactory.PROTOCOL + "="
|
||||
+ ProtocolNames.RSS + "))");
|
||||
} catch (InvalidSyntaxException ise)
|
||||
{
|
||||
fail("Invalid OSGi filter. Exception was" + ise.getMessage());
|
||||
}
|
||||
assertTrue("The protocol provider hasn't been restored after being "
|
||||
+ "reinstalled",
|
||||
providerRefs != null && providerRefs.length > 0);
|
||||
|
||||
ServiceReference factoryRefs[] = null;
|
||||
try {
|
||||
factoryRefs = fixture.bc.getServiceReferences(
|
||||
ProtocolProviderFactory.class.getName(),
|
||||
"(" + ProtocolProviderFactory.PROTOCOL + "=RSS)");
|
||||
} catch (InvalidSyntaxException ise)
|
||||
{
|
||||
fail("Invalid OSGi filter. Exception was " + ise.getMessage());
|
||||
}
|
||||
|
||||
fixture.providerFactory =
|
||||
(ProtocolProviderFactory) fixture.bc.getService(factoryRefs[0]);
|
||||
fixture.provider =
|
||||
(ProtocolProviderService) fixture.bc.getService(providerRefs[0]);
|
||||
|
||||
assertFalse("RSS provider did not restore its own reference to the"
|
||||
+ " provider that we just reinstalled.",
|
||||
fixture.providerFactory.getRegisteredAccounts().isEmpty()
|
||||
&& fixture.providerFactory.getProviderForAccount(
|
||||
fixture.provider.getAccountID()) == null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unistalls our test account and makes sure it really has been removed.
|
||||
*/
|
||||
public void testUninstallAccount() throws Exception
|
||||
{
|
||||
assertTrue("No accounts found.",
|
||||
! fixture.providerFactory.getRegisteredAccounts().isEmpty());
|
||||
|
||||
assertNotNull("Found no provider corresponding to RSS",
|
||||
fixture.providerFactory.getProviderForAccount(
|
||||
fixture.provider.getAccountID()));
|
||||
|
||||
assertTrue("Failed to remove provider",
|
||||
fixture.providerFactory.uninstallAccount(
|
||||
fixture.provider.getAccountID()));
|
||||
|
||||
ServiceReference[] providerRefs = null;
|
||||
try {
|
||||
providerRefs = fixture.bc.getServiceReferences(
|
||||
ProtocolProviderService.class.getName(),
|
||||
"(" + ProtocolProviderFactory.PROTOCOL + "=" + ProtocolNames.RSS
|
||||
+ ")");
|
||||
} catch (InvalidSyntaxException ise)
|
||||
{
|
||||
fail("Invalid OSGi filter.Exception was: " + ise.getMessage());
|
||||
}
|
||||
|
||||
assertTrue("Protocol provider service still registered as OSGi service",
|
||||
providerRefs == null || providerRefs.length == 0);
|
||||
|
||||
assertTrue("Provider factory didn't properly uninstalled the provider"
|
||||
+ "service we just uninstalled",
|
||||
fixture.providerFactory.getRegisteredAccounts().isEmpty()
|
||||
&& fixture.providerFactory.getProviderForAccount(
|
||||
fixture.provider.getAccountID()) == null);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,92 @@
|
||||
/*
|
||||
* SIP Communicator, the OpenSource Java VoIP and Instant Messaging client.
|
||||
*
|
||||
* Distributable under LGPL license.
|
||||
* See terms of license at gnu.org.
|
||||
*/
|
||||
package net.java.sip.communicator.slick.protocol.rss;
|
||||
|
||||
import junit.framework.*;
|
||||
import org.osgi.framework.*;
|
||||
import net.java.sip.communicator.service.configuration.*;
|
||||
import net.java.sip.communicator.service.protocol.*;
|
||||
|
||||
/**
|
||||
* Contains tests verifying persistence of account uninstallation. In other
|
||||
* words we try to make sure that once uninstalled an account remains
|
||||
* uninstalled.
|
||||
*
|
||||
* @author Mihai Balan
|
||||
*/
|
||||
public class TestAccountUninstallationPersistence
|
||||
extends TestCase
|
||||
{
|
||||
/**
|
||||
* Creates a new test instance wrapper around the test with the specified
|
||||
* name.
|
||||
*
|
||||
* @param testName the name of the test that we will be executing.
|
||||
*/
|
||||
public TestAccountUninstallationPersistence(String testName)
|
||||
{
|
||||
super(testName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves a reference to the RSS bundle, stops and uninstalls it and then
|
||||
* reinstalls it in order to make sure that accounts are not reloaded once
|
||||
* removed.
|
||||
*
|
||||
* @throws Exception if anything goes wrong while manipulating the bundles.
|
||||
*/
|
||||
public void testAccountUninstallationPersistence()
|
||||
throws Exception
|
||||
{
|
||||
Bundle providerBundle = RssSlickFixture.providerBundle;
|
||||
providerBundle.stop();
|
||||
|
||||
assertTrue("Couldn't stop the protocol provider bundle. State was"
|
||||
+ providerBundle.getState(),
|
||||
providerBundle.getState() != Bundle.ACTIVE
|
||||
&& providerBundle.getState() != Bundle.STOPPING);
|
||||
|
||||
providerBundle.uninstall();
|
||||
assertEquals("Couldn't stop the protocol provider bundle.",
|
||||
providerBundle.getState(), Bundle.UNINSTALLED);
|
||||
|
||||
//now reinstall the bundle and restart the provider
|
||||
providerBundle = RssSlickFixture.bc.installBundle(
|
||||
providerBundle.getLocation());
|
||||
assertEquals("Couldn't reinstall protocol provider bundle.",
|
||||
providerBundle.getState(), Bundle.INSTALLED);
|
||||
|
||||
providerBundle.start();
|
||||
assertEquals("Couldn't restart protocol provider bundle.",
|
||||
providerBundle.getState(), Bundle.ACTIVE);
|
||||
|
||||
//verify the provider is not reinstalled
|
||||
ServiceReference[] providerRefs = null;
|
||||
try {
|
||||
providerRefs = RssSlickFixture.bc.getServiceReferences(
|
||||
ProtocolProviderService.class.getName(),
|
||||
"(" + ProtocolProviderFactory.PROTOCOL + "=" + ProtocolNames.RSS
|
||||
+ ")");
|
||||
} catch (InvalidSyntaxException ise)
|
||||
{
|
||||
fail("OSGi filter is wrong. Error was: " + ise.getMessage());
|
||||
}
|
||||
|
||||
//make sure we didn't retrieve a service
|
||||
assertTrue("An RSS protocol provider service was still registered as an"
|
||||
+ " OSGi service even after being explicitly uninstalled",
|
||||
providerRefs == null || providerRefs.length == 0);
|
||||
|
||||
//now delete configuration file for a fresh start for the next test
|
||||
ServiceReference confRef = RssSlickFixture.bc.getServiceReference(
|
||||
ConfigurationService.class.getName());
|
||||
ConfigurationService confServ =
|
||||
(ConfigurationService) RssSlickFixture.bc.getService(confRef);
|
||||
|
||||
confServ.purgeStoredConfiguration();
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,235 @@
|
||||
/*
|
||||
* SIP Communicator, the OpenSource Java VoIP and Instant Messaging client.
|
||||
*
|
||||
* Distributable under LGPL license.
|
||||
* See terms of license at gnu.org.
|
||||
*/
|
||||
package net.java.sip.communicator.slick.protocol.rss;
|
||||
|
||||
import junit.framework.*;
|
||||
import net.java.sip.communicator.service.protocol.*;
|
||||
import net.java.sip.communicator.service.protocol.event.*;
|
||||
import net.java.sip.communicator.util.*;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* This class performs testing on protocol provider methods. It verifies that
|
||||
* the protocol provider service implements the declared operation sets and also
|
||||
* tests the process of registering an account.
|
||||
*
|
||||
* @author Mihai Balan
|
||||
*/
|
||||
public class TestProtocolProviderServiceRssImpl
|
||||
extends TestCase
|
||||
{
|
||||
/**
|
||||
* Time in miliseconds to wait for registration to complete. Is subject to
|
||||
* further fine-tuning.
|
||||
*/
|
||||
public static final int WAIT_DELAY = 10000;
|
||||
|
||||
public static final Logger logger =
|
||||
Logger.getLogger(TestProtocolProviderServiceRssImpl.class);
|
||||
|
||||
/**
|
||||
* Test's fixture.
|
||||
*/
|
||||
private RssSlickFixture fixture = new RssSlickFixture();
|
||||
|
||||
public RegistrationEventCollector eventCollector =
|
||||
new RegistrationEventCollector();
|
||||
|
||||
/**
|
||||
* Creates a test case that runs the specified test.
|
||||
*
|
||||
* @param testName the name of the method the test should run.
|
||||
*/
|
||||
public TestProtocolProviderServiceRssImpl(String testName)
|
||||
{
|
||||
super(testName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the fixture.
|
||||
*
|
||||
* @throws Exception if <code>super.setUp()</code> throws one.
|
||||
*/
|
||||
public void setUp() throws Exception
|
||||
{
|
||||
super.setUp();
|
||||
fixture.setUp();
|
||||
}
|
||||
|
||||
/**
|
||||
* Cleans up after the test.
|
||||
*
|
||||
* @throws Exception if <code>fixture.tearDown()</code> fails.
|
||||
*/
|
||||
public void tearDown() throws Exception
|
||||
{
|
||||
fixture.tearDown();
|
||||
super.tearDown();
|
||||
}
|
||||
|
||||
/**
|
||||
* This methods makes sure that the instance of the RSS protocol provider
|
||||
* that we are going to use is properly initialized and registered. It also
|
||||
* verifies that a registration event is fired upon successful registration
|
||||
* and collected by our event collector.
|
||||
*
|
||||
* @throws OperationFailedException if <code>provider.register()</code>
|
||||
* fails.
|
||||
*/
|
||||
public void testRegister() throws OperationFailedException
|
||||
{
|
||||
//registering as a listener & starting registration with a
|
||||
//null SecurityAuthority
|
||||
fixture.provider.addRegistrationStateChangeListener(
|
||||
this.eventCollector);
|
||||
fixture.provider.register(new NullSecurityAuthority());
|
||||
|
||||
//give it a little time to do his magic ;)
|
||||
logger.debug("Waiting for registration to complete...");
|
||||
eventCollector.waitForEvent(WAIT_DELAY);
|
||||
|
||||
//make sure we received events...
|
||||
assertTrue("No events were dispatched during the registration process.",
|
||||
eventCollector.collectedStates.size() > 0);
|
||||
//...and they were the right ones
|
||||
assertTrue("No registration event notifying of registration was"
|
||||
+ " dispatched."
|
||||
+ " All events were:" + eventCollector.collectedStates,
|
||||
eventCollector.collectedStates.contains(
|
||||
RegistrationState.REGISTERED));
|
||||
|
||||
//if everything is ok, we leave it alone
|
||||
fixture.provider.removeRegistrationStateChangeListener(eventCollector);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method verifies that all operation sets have the type they are
|
||||
* declared to have.
|
||||
*
|
||||
* @throws ClassNotFoundException if a class name found in the keys for the
|
||||
* supported operation sets doesn't correspond to a class that the
|
||||
* class loader can find.
|
||||
*/
|
||||
public void testOperationsSets() throws ClassNotFoundException
|
||||
{
|
||||
Map supportedOperationSets =
|
||||
fixture.provider.getSupportedOperationSets();
|
||||
|
||||
//get the keys for the supported operation set. The keys are strings
|
||||
//corresponding to class names.
|
||||
Iterator setNames = supportedOperationSets.keySet().iterator();
|
||||
while (setNames.hasNext())
|
||||
{
|
||||
String key = (String) setNames.next();
|
||||
Object opSet = supportedOperationSets.get(key);
|
||||
|
||||
assertTrue(opSet + " was not an instance of " + key +"as declared",
|
||||
Class.forName(key).isInstance(opSet));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This class acts as a very simple registration listener for the protocol
|
||||
* provider and simply records all events it receives and notifies
|
||||
* (<code>notifyAll()</code>) all objects waiting for an instance of this
|
||||
* class upon receiving an event that signals a completed registration.
|
||||
*
|
||||
* TODO: This class is just the same as the one in
|
||||
* TestProtocolProviderServiceGibberishImpl.java . Is there any reason for
|
||||
* duplicating code this way?
|
||||
*
|
||||
* @author Emil Ivov
|
||||
* @author Mihai Balan
|
||||
*/
|
||||
public class RegistrationEventCollector
|
||||
implements RegistrationStateChangeListener
|
||||
{
|
||||
/**
|
||||
* We store all the received events in this list. It's made public to
|
||||
* ease later inspection by unit tests.
|
||||
*/
|
||||
public List collectedStates = new LinkedList();
|
||||
|
||||
/**
|
||||
* This method simply records all received events in a <code>List</code>
|
||||
* that can be easily inspected by unit tests. In case we receive a
|
||||
* registration event notifying us of a completed registration, the
|
||||
* method calls <code>notifyAll()</code>.
|
||||
*
|
||||
* @param e a <code>RegistrationStateChangeEvent</code> decribing the
|
||||
* status change.
|
||||
*/
|
||||
public void registrationStateChanged(RegistrationStateChangeEvent e)
|
||||
{
|
||||
logger.debug("Received a RegistrationChangeEvent: " + e.toString());
|
||||
|
||||
collectedStates.add(e.getNewState());
|
||||
|
||||
if (e.getNewState().equals(RegistrationState.REGISTERED))
|
||||
{
|
||||
logger.debug("We're registered. Notifying waiting threads");
|
||||
|
||||
synchronized(this)
|
||||
{
|
||||
notifyAll();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Blocks until an event notifying us of the awaited status change is
|
||||
* received or until <code>waitFor</code> miliseconds pass, whichever
|
||||
* comes first.
|
||||
*
|
||||
* @param waitFor the number of seconds to wait for an event. If no
|
||||
* event is received, we simply return.
|
||||
*/
|
||||
public void waitForEvent(long waitFor)
|
||||
{
|
||||
logger.trace("Waiting for a RegistrationChangeEvent");
|
||||
|
||||
synchronized(this)
|
||||
{
|
||||
if (collectedStates.contains(RegistrationState.REGISTERED))
|
||||
{
|
||||
logger.trace("Event already received" + collectedStates);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
wait(waitFor);
|
||||
|
||||
if (collectedStates.size() > 0)
|
||||
logger.trace("Received a RegistrationStateChangeEvent.");
|
||||
else
|
||||
logger.trace("No registrationStateChangeEvent received"
|
||||
+ " for" + waitFor + "ms.");
|
||||
} catch(InterruptedException ie)
|
||||
{
|
||||
logger.debug("Interrupted while waiting for "
|
||||
+ "a RegistrationStateChangeEvent", ie);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Dummy implementation of a <code>SecurityAuthority</code>. It simply
|
||||
* returns null credentials as the RSS "authentication" protocol requires
|
||||
* none.
|
||||
*
|
||||
* @author Mihai Balan
|
||||
*/
|
||||
public class NullSecurityAuthority
|
||||
implements SecurityAuthority
|
||||
{
|
||||
public UserCredentials obtainCredentials(String realm,
|
||||
UserCredentials defaultValues) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,188 @@
|
||||
/*
|
||||
* SIP Communicator, the OpenSource Java VoIP and Instant Messaging client.
|
||||
*
|
||||
* Distributable under LGPL license.
|
||||
* See terms of license at gnu.org.
|
||||
*/
|
||||
package net.java.sip.communicator.slick.protocol.rss;
|
||||
|
||||
import java.net.*;
|
||||
import java.io.*;
|
||||
|
||||
/**
|
||||
* This classed is used in the automatic testing of the RSS protocol. It acts as
|
||||
* a <b>very</b> simple HTTP server that can serve RSS files. It has the ability
|
||||
* to simulate an update to the file, or to send an invalid file.
|
||||
*
|
||||
* The usual flow when using a <code>TestingServer</code> is as follows:
|
||||
* <ol>
|
||||
* <li>Create <code>TestingServer</code> object.</li>
|
||||
* <li>Set server behaviour through calls to <code>setAtomUsage()</code> and
|
||||
* <code>setServerBehaviour()</code>.</li>
|
||||
* <li>Start the server with <code>start()</code>.</li>
|
||||
* <li>Retrieve contents served by the server.</li>
|
||||
* <li>Stop the server with <code>stop()</code>.</li>
|
||||
* <li>If necessary rewind from 2.</li>
|
||||
* </ol>
|
||||
*
|
||||
* @see setAtomUsage, setServerBehaviour, start, stop
|
||||
* @author Mihai Balan
|
||||
*/
|
||||
public class TestingServer
|
||||
{
|
||||
/* Java 1.5 specific - could simplfy things a lot when the switch is decided
|
||||
* enum ServerResponse
|
||||
* {
|
||||
* VALID, VALID_UPDATE, VALID_NEW, INVALID
|
||||
* }
|
||||
*/
|
||||
/**
|
||||
* Numeric constant specifying an invalid file to be served.
|
||||
*/
|
||||
public static final int INVALID = 0;
|
||||
|
||||
/**
|
||||
* Numeric constant specifying a valid file to be served.
|
||||
*/
|
||||
public static final int VALID = 1;
|
||||
|
||||
/**
|
||||
* Numeric constant specifying a valid, updated file to be served.
|
||||
*/
|
||||
public static final int VALID_UPDATE = 2;
|
||||
|
||||
/**
|
||||
* Numeric constant specifying a valid, new file to be served.
|
||||
*/
|
||||
public static final int VALID_NEW = 3;
|
||||
|
||||
/**
|
||||
* <code>true</code> if ATOM-like files are used, <code>false</code>
|
||||
* otherwise.
|
||||
*/
|
||||
private boolean usesAtom;
|
||||
|
||||
/**
|
||||
* Flag specifying the current type of file used.
|
||||
*/
|
||||
private int currentFile = VALID;
|
||||
|
||||
/**
|
||||
* ServerSocket used to listen for incoming connections.
|
||||
*/
|
||||
private ServerSocket server = null;
|
||||
|
||||
/**
|
||||
* Thread for responding to client requests.
|
||||
*/
|
||||
private TestingServerThread runner = null;
|
||||
|
||||
/**
|
||||
* <code>true</code> if the server was successfully launched (through a call
|
||||
* to <code>start()</code>, <code>false</code> otherwise.
|
||||
*/
|
||||
private boolean serverActive;
|
||||
|
||||
/**
|
||||
* Public constructor. Creates the server and binds it to port 8080 of the
|
||||
* loop-back address. It uses port 8080 instead of the more
|
||||
* standard port 80, because on Linux machines binding on ports smaller than
|
||||
* 1023 requires root privileges.
|
||||
* @throws IOException in case the server cannot bind to the specified
|
||||
* address/port, it throws an IOException detailing the problem.
|
||||
*/
|
||||
public TestingServer()
|
||||
throws IOException
|
||||
{
|
||||
server = new ServerSocket(8080, 20,
|
||||
InetAddress.getByName(null));
|
||||
usesAtom = false;
|
||||
serverActive = false;
|
||||
currentFile = INVALID;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether or not to use ATOM-like files or not
|
||||
* @param usesAtom <code>true</code> to serve ATOM-like files,
|
||||
* <code>false</code> otherwise.
|
||||
*/
|
||||
public void setAtomUsage(boolean usesAtom)
|
||||
{
|
||||
this.usesAtom = usesAtom;
|
||||
}
|
||||
|
||||
/**
|
||||
* Accessor for the field variable <code>usesAtom</code>
|
||||
* @return <code>true</code> if ATOM-like files are used, <code>false</code>
|
||||
* otherwise.
|
||||
*/
|
||||
public boolean usesAtom()
|
||||
{
|
||||
return this.usesAtom;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current state of the server.
|
||||
* @return <code>true</code> if a successful call to <code>start()</code>
|
||||
* has been issued and the server hasn't yet processed any request,
|
||||
* <code>false</code> otherwise.
|
||||
*/
|
||||
public boolean isActive()
|
||||
{
|
||||
return serverActive;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the type of file the server serves.
|
||||
* @param type int enum specifying the type of file.
|
||||
*/
|
||||
public void setServerBehaviour(int type)
|
||||
{
|
||||
if (type == INVALID || type == VALID || type == VALID_UPDATE
|
||||
|| type == VALID_NEW )
|
||||
currentFile = type;
|
||||
else
|
||||
currentFile = INVALID;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the type of file currently server by the server.
|
||||
* @return file type.
|
||||
*/
|
||||
public int getServerBehaviour()
|
||||
{
|
||||
return currentFile;
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts the listening process for incoming connections in a separate
|
||||
* thread.
|
||||
*/
|
||||
public void start()
|
||||
{
|
||||
//only allow one "instance" of the server to be running at a given time
|
||||
if (serverActive)
|
||||
return;
|
||||
|
||||
//create new thread and launch
|
||||
runner = new TestingServerThread(this, server);
|
||||
serverActive = true;
|
||||
runner.start();
|
||||
}
|
||||
|
||||
/**
|
||||
* Takes the server into an inactive state. If the listening thread is still
|
||||
* running it waits for it to end.
|
||||
* @throws InterruptedException
|
||||
*/
|
||||
public void stop() throws InterruptedException
|
||||
{
|
||||
//wait for listening thread to end
|
||||
if (runner.isAlive())
|
||||
runner.join();
|
||||
|
||||
//restore server state
|
||||
serverActive = false;
|
||||
runner = null;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,185 @@
|
||||
/*
|
||||
* SIP Communicator, the OpenSource Java VoIP and Instant Messaging client.
|
||||
*
|
||||
* Distributable under LGPL license.
|
||||
* See terms of license at gnu.org.
|
||||
*/
|
||||
package net.java.sip.communicator.slick.protocol.rss;
|
||||
|
||||
import java.net.*;
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
import java.text.*;
|
||||
|
||||
/**
|
||||
* This class represents the separate thread that a <code>TestingServer</code>
|
||||
* uses to listen for incoming connections.
|
||||
* A reference to the object that launched the thread is also kept too in order
|
||||
* to have easier access to the server settings.
|
||||
*
|
||||
* @author Mihai Balan
|
||||
*/
|
||||
public class TestingServerThread
|
||||
extends Thread
|
||||
{
|
||||
/**
|
||||
* The server that launched us.
|
||||
*/
|
||||
private TestingServer launcher = null;
|
||||
|
||||
/**
|
||||
* The server's <code>ServerSocket</code>. We keep a reference to it to as
|
||||
* the call to <code>ServerSocket.accept()</code> is made in the thread (us)
|
||||
* and not in the server to avoid deadlocks.
|
||||
*/
|
||||
private ServerSocket serverSocket;
|
||||
/**
|
||||
* <code>Socket</code> used for network I/O.
|
||||
*/
|
||||
private Socket socket;
|
||||
|
||||
/**
|
||||
* Creates a new thread for listening for connections.
|
||||
* @param launcher the <code>TestingServer</code> object that created us.
|
||||
* @param serverSock the <code>ServerSocket</code> used to listen for
|
||||
* connections on.
|
||||
*/
|
||||
public TestingServerThread(TestingServer launcher, ServerSocket serverSock)
|
||||
{
|
||||
/* would a check for null (mainly for the launcher) and an eventual
|
||||
* NullPointerException make sense here?*/
|
||||
this.launcher = launcher;
|
||||
this.serverSocket = serverSock;
|
||||
}
|
||||
|
||||
/**
|
||||
* Effectively launches the server thread. It starts listening for
|
||||
* connections on <code>serverSocket</code>, and upon a successful request
|
||||
* serves the file according to the <code>launcher</code>'s settings.
|
||||
*/
|
||||
public void run()
|
||||
{
|
||||
if (launcher.isActive())
|
||||
{
|
||||
try {
|
||||
socket = serverSocket.accept();
|
||||
|
||||
BufferedReader in = new BufferedReader(
|
||||
new InputStreamReader(socket.getInputStream()));
|
||||
processRequest(in);
|
||||
|
||||
launcher.stop();
|
||||
|
||||
} catch (IOException e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
socket = null;
|
||||
} catch (InterruptedException ie)
|
||||
{
|
||||
ie.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes the HTTP request and initiates the sending of a response
|
||||
* according to the server settings.
|
||||
*
|
||||
* @param in network end-point from which we read.
|
||||
*
|
||||
* @throws IOException
|
||||
*/
|
||||
public void processRequest(BufferedReader in)
|
||||
throws IOException
|
||||
{
|
||||
String crtLine;
|
||||
String httpVersion = null;
|
||||
boolean gotRequest = false;
|
||||
|
||||
//XXX: Debug
|
||||
//System.out.println("Processing request. Dump follows:");
|
||||
|
||||
//look for the get string and totally and blindly ignore all other
|
||||
//HTTP headers
|
||||
while (! "".equals(crtLine = in.readLine().trim()) && crtLine != null)
|
||||
{
|
||||
//XXX: Debug
|
||||
//System.out.println("> " + crtLine);
|
||||
if (crtLine.startsWith("GET /"))
|
||||
{
|
||||
gotRequest = true;
|
||||
int httpPos = -1;
|
||||
httpPos = crtLine.lastIndexOf(" HTTP/");
|
||||
if (httpPos != -1)
|
||||
httpVersion = crtLine.substring(httpPos + 1);
|
||||
else
|
||||
httpVersion = "HTTP/1.0";
|
||||
}
|
||||
}
|
||||
|
||||
//if no file was requested, just abort
|
||||
if (! gotRequest)
|
||||
return;
|
||||
|
||||
BufferedWriter out = new BufferedWriter(
|
||||
new OutputStreamWriter(socket.getOutputStream()));
|
||||
|
||||
sendResponse(out, httpVersion);
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds and sends the HTTP response according to the server settings.
|
||||
*
|
||||
* @param out the network end-point to which we write to.
|
||||
* @param httpVersion textual representation of the HTTP version used.
|
||||
* Should either be "HTTP/1.0" or "HTTP/1.1".
|
||||
*
|
||||
* @throws IOException
|
||||
*/
|
||||
public void sendResponse(BufferedWriter out, String httpVersion)
|
||||
throws IOException
|
||||
{
|
||||
String content = "";
|
||||
SimpleDateFormat dateFormatter =
|
||||
new SimpleDateFormat("EEE, d MMM yyyy HH:mm:ss Z");
|
||||
|
||||
//getting output
|
||||
switch (launcher.getServerBehaviour())
|
||||
{
|
||||
case TestingServer.INVALID:
|
||||
content = launcher.usesAtom() ? FeedFactory.getAtomInvalid()
|
||||
: FeedFactory.getRssInvalid();
|
||||
break;
|
||||
case TestingServer.VALID:
|
||||
content = launcher.usesAtom() ? FeedFactory.getAtom()
|
||||
: FeedFactory.getRss();
|
||||
break;
|
||||
case TestingServer.VALID_UPDATE:
|
||||
content = launcher.usesAtom() ? FeedFactory.getAtomUpdated()
|
||||
: FeedFactory.getRssUpdated();
|
||||
break;
|
||||
case TestingServer.VALID_NEW:
|
||||
content = launcher.usesAtom() ? FeedFactory.getAtomNew()
|
||||
: FeedFactory.getRssNew();
|
||||
break;
|
||||
}
|
||||
|
||||
//XXX: Debug
|
||||
//System.out.println("Sending response headers...");
|
||||
|
||||
//building response HTTP headers
|
||||
out.write(httpVersion + "200 OK\r\n");
|
||||
out.write("Server: RssTestingServer/0.0.1\r\n");
|
||||
out.write("Date: " + dateFormatter.format(new Date()) + "\r\n");
|
||||
out.write("Content-Type: text/html; charset=utf-8\r\n");
|
||||
out.write("Content-length: " + content.length() + "\r\n");
|
||||
out.write("\r\n");
|
||||
|
||||
//outputting the file
|
||||
out.write(content);
|
||||
|
||||
out.close();
|
||||
socket.close();
|
||||
socket = null;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,12 @@
|
||||
Bundle-Activator: net.java.sip.communicator.slick.protocol.rss.RssProtocolProviderServiceLick
|
||||
Bundle-Name: RSS Protocol Provider Service Leveraging Implementation Compatibility Kit
|
||||
Bundle-Description: A Service Leveraging Implementation Compatibility Kit for the RSS implementation of the ProtocolProvider Service
|
||||
Bundle-Vendor: sip-communicator.org
|
||||
Bundle-Version: 0.0.1
|
||||
Import-Package: net.java.sip.communicator.service.configuration,
|
||||
net.java.sip.communicator.service.configuration.event,
|
||||
junit.framework,
|
||||
org.osgi.framework,
|
||||
net.java.sip.communicator.util,
|
||||
net.java.sip.communicator.service.protocol,
|
||||
net.java.sip.communicator.service.protocol.event
|
||||
Loading…
Reference in new issue