From 3ce23a1e74b79c4abc1836938854c8e61c81641e Mon Sep 17 00:00:00 2001 From: Benoit Pradelle Date: Mon, 17 Sep 2007 18:28:38 +0000 Subject: [PATCH] Added the Rss tests, written by Mihai Balan --- build.xml | 13 +- lib/felix.unit.test.properties | 3 + lib/testing.properties | 3 +- .../service/protocol/ProtocolNames.java | 6 + .../slick/protocol/rss/FeedFactory.java | 508 ++++++++++++++++++ .../rss/RssProtocolProviderServiceLick.java | 67 +++ .../slick/protocol/rss/RssSlickFixture.java | 155 ++++++ .../protocol/rss/TestAccountInstallation.java | 133 +++++ .../rss/TestAccountUninstallation.java | 211 ++++++++ .../TestAccountUninstallationPersistence.java | 92 ++++ .../TestProtocolProviderServiceRssImpl.java | 235 ++++++++ .../slick/protocol/rss/TestingServer.java | 188 +++++++ .../protocol/rss/TestingServerThread.java | 185 +++++++ .../rss/rss.provider.slick.manifest.mf | 12 + 14 files changed, 1809 insertions(+), 2 deletions(-) create mode 100755 test/net/java/sip/communicator/slick/protocol/rss/FeedFactory.java create mode 100755 test/net/java/sip/communicator/slick/protocol/rss/RssProtocolProviderServiceLick.java create mode 100755 test/net/java/sip/communicator/slick/protocol/rss/RssSlickFixture.java create mode 100755 test/net/java/sip/communicator/slick/protocol/rss/TestAccountInstallation.java create mode 100755 test/net/java/sip/communicator/slick/protocol/rss/TestAccountUninstallation.java create mode 100755 test/net/java/sip/communicator/slick/protocol/rss/TestAccountUninstallationPersistence.java create mode 100755 test/net/java/sip/communicator/slick/protocol/rss/TestProtocolProviderServiceRssImpl.java create mode 100755 test/net/java/sip/communicator/slick/protocol/rss/TestingServer.java create mode 100755 test/net/java/sip/communicator/slick/protocol/rss/TestingServerThread.java create mode 100755 test/net/java/sip/communicator/slick/protocol/rss/rss.provider.slick.manifest.mf diff --git a/build.xml b/build.xml index 5b8fd9d85..12d979156 100644 --- a/build.xml +++ b/build.xml @@ -872,7 +872,7 @@ bundle-systray,bundle-browserlauncher,bundle-gibberish, bundle-gibberish-slick,bundle-plugin-gibberishaccregwizz, bundle-plugin-extended-callhistory-search, - bundle-rss,bundle-plugin-rssaccregwizz, + bundle-rss, bundle-rss-slick,bundle-plugin-rssaccregwizz, bundle-zeroconf,bundle-plugin-zeroconfaccregwizz, bundle-irc,bundle-plugin-ircaccregwizz, bundle-pluginmanager,bundle-notification"/> @@ -1600,6 +1600,17 @@ javax.swing.event, javax.swing.border"/> prefix="resources/images/rss"/> + + + + + + + + diff --git a/lib/felix.unit.test.properties b/lib/felix.unit.test.properties index 9f50ba2b5..811caa189 100644 --- a/lib/felix.unit.test.properties +++ b/lib/felix.unit.test.properties @@ -8,6 +8,7 @@ org.osgi.framework.system.packages= org.osgi.framework; \ javax.swing.event; \ javax.swing.table; \ javax.swing.text; \ + javax.imageio;\ org.w3c.dom; \ org.xml.sax; \ org.xml.sax.helpers; \ @@ -61,6 +62,7 @@ felix.auto.start.4= \ file:sc-bundles/history.jar \ file:sc-bundles/protocol-icq.jar \ file:sc-bundles/smacklib.jar \ + file:sc-bundles/protocol-rss.jar \ file:sc-bundles/protocol-jabber.jar \ file:sc-bundles/protocol-msn.jar \ file:sc-bundles/protocol-sip.jar \ @@ -86,6 +88,7 @@ felix.auto.start.5= \ file:sc-bundles/protocol-msn-slick.jar \ file:sc-bundles/protocol-yahoo-slick.jar \ file:sc-bundles/protocol-gibberish-slick.jar \ + file:sc-bundles/protocol-rss-slick.jar \ file:sc-bundles/msghistory-slick.jar \ file:sc-bundles/callhistory-slick.jar diff --git a/lib/testing.properties b/lib/testing.properties index 77859b1b4..1d282e8a9 100644 --- a/lib/testing.properties +++ b/lib/testing.properties @@ -14,7 +14,8 @@ net.java.sip.communicator.slick.runner.TEST_LIST=ConfigurationServiceLick \ JabberProtocolProviderSlick \ YahooProtocolProviderSlick \ MsnProtocolProviderSlick \ - GibberishProtocolProviderServiceLick + GibberishProtocolProviderServiceLick \ + RssProtocolProviderServiceLick # MediaServiceLick \ diff --git a/src/net/java/sip/communicator/service/protocol/ProtocolNames.java b/src/net/java/sip/communicator/service/protocol/ProtocolNames.java index d215465a7..043f28e15 100644 --- a/src/net/java/sip/communicator/service/protocol/ProtocolNames.java +++ b/src/net/java/sip/communicator/service/protocol/ProtocolNames.java @@ -69,4 +69,10 @@ public interface ProtocolNames * The Zeroconf protcool. */ public static final String ZEROCONF = "Zeroconf"; + + /** + * The RSS protocol. + */ + public static final String RSS = "RSS"; + } diff --git a/test/net/java/sip/communicator/slick/protocol/rss/FeedFactory.java b/test/net/java/sip/communicator/slick/protocol/rss/FeedFactory.java new file mode 100755 index 000000000..c8dc70b00 --- /dev/null +++ b/test/net/java/sip/communicator/slick/protocol/rss/FeedFactory.java @@ -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 = + "" + +"" + +" " + +" miChou's photoblog" + +" http://mihaibalan.wordpress.com" + +" The world through my eyes" + +" Mon, 20 Aug 2007 22:20:57 +0000" + +" http://wordpress.org/?v=MU" + +" ro"; + + /** + * String containing the body of a RSS feed. + */ + private static String rssBody = + " " + +" Milky wave" + +" http://mihaibalan.wordpress.com/2007/08/15/milky-wave/" + +" http://mihaibalan.wordpress.com/2007/08/15/milky-wave/#co" + +"mments" + +" Tue, 14 Aug 2007 22:02:48 +0000" + +" mich0u" + +" " + +" http://mihaibalan.wordpress.com/2007/08" + +"/15/milky-wave/" + +" " + +"

\"Milky

" + +"]]>
" + +" http://mihaibalan.wordpress.com/2007/08/15/milky-" + +"wave/feed/" + +"
" + +" " + +" Light patterns" + +" http://mihaibalan.wordpress.com/2007/08/14/light-patterns/" + +" http://mihaibalan.wordpress.com/2007/08/14/light-pattern" + +"s/#comments" + +" Mon, 13 Aug 2007 22:02:32 +0000" + +" mich0u" + +" " + +" " + +" http://mihaibalan.wordpress.com/2007/08" + +"/14/light-patterns/" + +" " + +"

\"Light

" + +"]]>
" + +" http://mihaibalan.wordpress.com/2007/08/14/light-p" + +"atterns/feed/" + +"
"; + + /** + * String containing the updates to the RSS feed. + */ + private static String rssBodyUpdate = + " " + +" Tuig - The show goes on" + +" http://mihaibalan.wordpress.com/2007/08/17/tuig-the-show-goes" + +"-on/" + +" http://mihaibalan.wordpress.com/2007/08/17/tuig-the-show" + +"-goes-on/#comments" + +" Thu, 16 Aug 2007 22:05:53 +0000" + +" mich0u" + +" " + +" " + +" http://mihaibalan.wordpress.com/2007/08" + +"/17/tuig-the-show-goes-on/" + +" " + +"

\"Tuig

" + +"]]>
" + +" http://mihaibalan.wordpress.com/2007/08/17/tuig-the" + +"-show-goes-on/feed/" + +"
" + +" " + +" Tuig - Patiently waiting" + +" http://mihaibalan.wordpress.com/2007/08/16/tuig-patiently-wai" + +"ting/" + +" http://mihaibalan.wordpress.com/2007/08/16/tuig-patiently" + +"-waiting/#comments" + +" Wed, 15 Aug 2007 22:03:55 +0000" + +" mich0u" + +" " + +" " + +" " + +" http://mihaibalan.wordpress.com/2007/0" + +"8/16/tuig-patiently-waiting/" + +" " + +"

\"Tuig

" + +"

(more…)

" + +"]]>
" + +" http://mihaibalan.wordpress.com/2007/08/16/tuig-pa" + +"tiently-waiting/feed/" + +"
"; + + /** + * String containing the body of a new RSS feed. + */ + private static String rssBodyNew = " " + +" I see trees of green and skies of blue" + +" http://mihaibalan.wordpress.com/2007/08/21/i-see-trees-of-gr" + +"een-and-skies-of-blue/" + +" http://mihaibalan.wordpress.com/2007/08/21/i-see-trees-of" + +"-green-and-skies-of-blue/#comments" + +" Mon, 20 Aug 2007 22:20:57 +0000" + +" mich0u" + +" " + +" " + +" " + +" http://mihaibalan.wordpress.com/2007" + +"/08/21/i-see-trees-of-green-and-skies-of-blue/" + +" " + +"

\"I

" + +"]]>
" + +" http://mihaibalan.wordpress.com/2007/08/21/i-see" + +"-trees-of-green-and-skies-of-blue/feed/" + +"
" + +" " + +" Tuig - If I could turn back time" + +" http://mihaibalan.wordpress.com/2007/08/20/tuig-if-i-could-" + +"turn-back-time/" + +" http://mihaibalan.wordpress.com/2007/08/20/tuig-if-i-" + +"could-turn-back-time/#comments" + +" Sun, 19 Aug 2007 22:05:53 +0000" + +" mich0u" + +" " + +" " + +" " + +" http://mihaibalan.wordpress.com/2007/" + +"08/20/tuig-if-i-could-turn-back-time/" + +" " + +"

\"Tuig

" + +"

(more…)

" + +"]]>
" + +" http://mihaibalan.wordpress.com/2007/08/20/tuig-if" + +"-i-could-turn-back-time/feed/" + +"
"; + + /** + * String containing some invalid mark-up in the RSS feed. + */ + private static String rssBodyInvalid = + "Lorem ipsum"; + + /** + * String containing the footer of a RSS feed. + */ + private static String rssFooter = "
"; + + /** + * String containing the header of a ATOM feed. + */ + private static String atomHeader = + "" + +"" + +"" + +" tag:blogger.com,1999:blog-34909258791457560582007-" + +"08-08T10:24:42.424-07:00miChou's Summer of " + +"Code blog" + +" " + +" " + +" " + +" Mihai Balan" + +" " + +" Blogger6125"; + + /** + * String containing the body of an ATOM feed. + */ + private static String atomBody = + "tag:blogger.com,1999:blog-3490925879145756058.post-445569517" + +"55418486052007-06-05T02:15:00.000-07:002007-06-05T03:34:35.892-07:00" + +" " + +"" + +" Happy hacking!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 :)" + +" " + +" " + +" " + +" " + +"" + +" " + +" Mihai Balan" + +" " + +" " + +" " + +" tag:blogger.com,1999:blog-3490925879145756058.post-160551373" + +"8611698052007-05-31T13:34:00.000-07:002007-06-01T04:21:00.167-07:00" + +" " + +" " + +" Un debut attarde" + +"<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." + +" " + +" " + +" " + +" " + +" " + +" Mihai Balan" + +" " + +" "; + + /** + * String containing the updates to the ATOM feed. + */ + private static String atomBodyUpdate = + "tag:blogger.com,1999:blog-3490925879145756058.post-722978588" + +"38255321932007-06-25T14:29:00.000-07:002007-06-26T06:12:44.479-07:00" + +" " + +"" + +" " + +" " + +" Google politicsO" + +"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." + +" " + +" " + +" " + +" " + +"" + +" " + +" Mihai Balan" + +" " + +" "; + + /** + * String containing a new ATOM feed. + */ + private static String atomBodyNew = + "tag:blogger.com,1999:blog-3490925879145756058.post-325829288" + +"52251106862007-08-08T09:59:00.000-07:002007-08-08T10:24:42.470-07:00" + +" " + +" " + +"" + +" " + +" check out. again...<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." + +" " + +" " + +" " + +" " + +"" + +" " + +" Mihai Balan" + +" " + +" " + +" " + +" tag:blogger.com,1999:blog-3490925879145756058.post-186104691" + +"57144790072007-07-06T13:23:00.000-07:002007-07-06T13:54:46.478-07:00" + +" " + +" " + +" Favicon - check!" + +"<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)." + +" " + +" " + +" " + +" " + +"" + +" " + +" Mihai Balan" + +" " + +" " + +" " + +" tag:blogger.com,1999:blog-3490925879145756058.post-717349866" + +"0796698482007-06-29T12:35:00.000-07:002007-06-29T12:39:34.816-07:00" + +" " + +"" + +" Interim objectivesI know I've been a little late setting these, but now it's kinda' sett" + +"led." + +" " + +" " + +" " + +" " + +" " + +" Mihai Balan" + +" " + +" "; + + /** + * String containing some invalid markup in the ATOM feed. + */ + private static String atomBodyInvalid = + "Lorem ipsum"; + + /** + * String containing the footer of the ATOM feed. + */ + private static String atomFooter = ""; + + /** + * Returns a String representing an RSS feed. + * @return textual representation of the RSS feed. + */ + public static String getRss() + { + return rssHeader + rssBody + rssFooter; + } + + /** + * Returns a String representing the updated RSS feed. + * @return textual representation of the RSS feed. + */ + public static String getRssUpdated() + { + return rssHeader + rssBodyUpdate + rssBody + rssFooter; + } + + /** + * Returns a String 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 String representing an invalid RSS feed. + * @return textual representation of the RSS feed. + */ + public static String getRssInvalid() + { + return rssHeader + rssBodyInvalid + rssFooter; + } + + /** + * Returns a String representing an ATOM feed. + * @return textual representation of the RSS feed. + */ + public static String getAtom() + { + return atomHeader + atomBody + atomFooter; + } + + /** + * Returns a String representing the updated ATOM feed. + * @return textual representation of the RSS feed. + */ + public static String getAtomUpdated() + { + return atomHeader + atomBodyUpdate + atomBody + atomFooter; + } + + /** + * Returns a String 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 String representing an invalid ATOM feed. + * @return textual representation of the RSS feed. + */ + public static String getAtomInvalid() + { + return atomHeader + atomBodyInvalid + atomFooter; + } +} diff --git a/test/net/java/sip/communicator/slick/protocol/rss/RssProtocolProviderServiceLick.java b/test/net/java/sip/communicator/slick/protocol/rss/RssProtocolProviderServiceLick.java new file mode 100755 index 000000000..92ebcdb5d --- /dev/null +++ b/test/net/java/sip/communicator/slick/protocol/rss/RssProtocolProviderServiceLick.java @@ -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) + { + + } + +} diff --git a/test/net/java/sip/communicator/slick/protocol/rss/RssSlickFixture.java b/test/net/java/sip/communicator/slick/protocol/rss/RssSlickFixture.java new file mode 100755 index 000000000..8d1018d68 --- /dev/null +++ b/test/net/java/sip/communicator/slick/protocol/rss/RssSlickFixture.java @@ -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 HashTable 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() + } +} diff --git a/test/net/java/sip/communicator/slick/protocol/rss/TestAccountInstallation.java b/test/net/java/sip/communicator/slick/protocol/rss/TestAccountInstallation.java new file mode 100755 index 000000000..f361d4f01 --- /dev/null +++ b/test/net/java/sip/communicator/slick/protocol/rss/TestAccountInstallation.java @@ -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); + } +} diff --git a/test/net/java/sip/communicator/slick/protocol/rss/TestAccountUninstallation.java b/test/net/java/sip/communicator/slick/protocol/rss/TestAccountUninstallation.java new file mode 100755 index 000000000..658adce6a --- /dev/null +++ b/test/net/java/sip/communicator/slick/protocol/rss/TestAccountUninstallation.java @@ -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); + } +} diff --git a/test/net/java/sip/communicator/slick/protocol/rss/TestAccountUninstallationPersistence.java b/test/net/java/sip/communicator/slick/protocol/rss/TestAccountUninstallationPersistence.java new file mode 100755 index 000000000..d0da2fb8b --- /dev/null +++ b/test/net/java/sip/communicator/slick/protocol/rss/TestAccountUninstallationPersistence.java @@ -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(); + } +} diff --git a/test/net/java/sip/communicator/slick/protocol/rss/TestProtocolProviderServiceRssImpl.java b/test/net/java/sip/communicator/slick/protocol/rss/TestProtocolProviderServiceRssImpl.java new file mode 100755 index 000000000..a1ce66ef0 --- /dev/null +++ b/test/net/java/sip/communicator/slick/protocol/rss/TestProtocolProviderServiceRssImpl.java @@ -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 super.setUp() throws one. + */ + public void setUp() throws Exception + { + super.setUp(); + fixture.setUp(); + } + + /** + * Cleans up after the test. + * + * @throws Exception if fixture.tearDown() 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 provider.register() + * 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 + * (notifyAll()) 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 List + * that can be easily inspected by unit tests. In case we receive a + * registration event notifying us of a completed registration, the + * method calls notifyAll(). + * + * @param e a RegistrationStateChangeEvent 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 waitFor 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 SecurityAuthority. 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; + } + } +} diff --git a/test/net/java/sip/communicator/slick/protocol/rss/TestingServer.java b/test/net/java/sip/communicator/slick/protocol/rss/TestingServer.java new file mode 100755 index 000000000..2bafc972b --- /dev/null +++ b/test/net/java/sip/communicator/slick/protocol/rss/TestingServer.java @@ -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 very 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 TestingServer is as follows: + *
    + *
  1. Create TestingServer object.
  2. + *
  3. Set server behaviour through calls to setAtomUsage() and + * setServerBehaviour().
  4. + *
  5. Start the server with start().
  6. + *
  7. Retrieve contents served by the server.
  8. + *
  9. Stop the server with stop().
  10. + *
  11. If necessary rewind from 2.
  12. + *
+ * + * @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; + + /** + * true if ATOM-like files are used, false + * 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; + + /** + * true if the server was successfully launched (through a call + * to start(), false 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 true to serve ATOM-like files, + * false otherwise. + */ + public void setAtomUsage(boolean usesAtom) + { + this.usesAtom = usesAtom; + } + + /** + * Accessor for the field variable usesAtom + * @return true if ATOM-like files are used, false + * otherwise. + */ + public boolean usesAtom() + { + return this.usesAtom; + } + + /** + * Returns the current state of the server. + * @return true if a successful call to start() + * has been issued and the server hasn't yet processed any request, + * false 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; + } +} diff --git a/test/net/java/sip/communicator/slick/protocol/rss/TestingServerThread.java b/test/net/java/sip/communicator/slick/protocol/rss/TestingServerThread.java new file mode 100755 index 000000000..0dea8faf4 --- /dev/null +++ b/test/net/java/sip/communicator/slick/protocol/rss/TestingServerThread.java @@ -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 TestingServer + * 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 ServerSocket. We keep a reference to it to as + * the call to ServerSocket.accept() is made in the thread (us) + * and not in the server to avoid deadlocks. + */ + private ServerSocket serverSocket; + /** + * Socket used for network I/O. + */ + private Socket socket; + + /** + * Creates a new thread for listening for connections. + * @param launcher the TestingServer object that created us. + * @param serverSock the ServerSocket 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 serverSocket, and upon a successful request + * serves the file according to the launcher'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; + } +} diff --git a/test/net/java/sip/communicator/slick/protocol/rss/rss.provider.slick.manifest.mf b/test/net/java/sip/communicator/slick/protocol/rss/rss.provider.slick.manifest.mf new file mode 100755 index 000000000..81b8c7369 --- /dev/null +++ b/test/net/java/sip/communicator/slick/protocol/rss/rss.provider.slick.manifest.mf @@ -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 \ No newline at end of file