diff --git a/lib/felix.client.run.properties.rss b/lib/felix.client.run.properties.rss
new file mode 100644
index 000000000..3827cd884
--- /dev/null
+++ b/lib/felix.client.run.properties.rss
@@ -0,0 +1,114 @@
+#
+# Framework config properties.
+#
+org.osgi.framework.system.packages= org.osgi.framework; \
+ javax.swing; \
+ javax.swing.event; \
+ javax.swing.table; \
+ javax.swing.text; \
+ javax.swing.text.html; \
+ javax.accessibility; \
+ javax.swing.plaf; \
+ javax.swing.plaf.metal; \
+ javax.swing.plaf.basic; \
+ javax.imageio; \
+ javax.swing.tree; \
+ javax.swing.undo; \
+ javax.swing.event; \
+ javax.swing.border; \
+ javax.swing.filechooser; \
+ org.w3c.dom; \
+ org.xml.sax; \
+ javax.xml.parsers;\
+ org.apache.xml.serialize; \
+ javax.xml.transform; \
+ javax.xml.transform.dom; \
+ javax.xml.transform.stream; \
+ sun.security.action; \
+ sun.misc; \
+ javax.net; \
+ javax.net.ssl; \
+ javax.naming; \
+ javax.naming.directory; \
+ javax.sound;\
+ javax.sound.sampled; \
+ org.jdesktop.jdic.tray; \
+ org.jdesktop.jdic.desktop; \
+ com.apple.eio; \
+ org.xml.sax.helpers;
+
+felix.auto.start.10= reference:file:lib/bundle/org.apache.felix.servicebinder-0.8.0-SNAPSHOT.jar
+#reference:file:lib/bundle/org.apache.felix.bundlerepository-0.8.0-SNAPSHOT.jar
+#\
+# file:lib/bundle/shell.jar \
+# \
+# file:lib/bundle/servicebinder.jar \
+# file:lib/bundle/tablelayout.jar
+
+felix.auto.start.20= \
+ reference:file:sc-bundles/util.jar
+
+
+felix.auto.start.40= \
+ reference:file:sc-bundles/configuration.jar \
+ reference:file:sc-bundles/version.jar \
+ reference:file:sc-bundles/version-impl.jar \
+ reference:file:sc-bundles/splashscreen.jar \
+
+felix.auto.start.50= \
+ reference:file:sc-bundles/fileaccess.jar \
+ reference:file:sc-bundles/browserlauncher.jar \
+ reference:file:sc-bundles/protocol.jar \
+ reference:file:sc-bundles/contactlist.jar \
+ reference:file:sc-bundles/media.jar \
+ reference:file:sc-bundles/protocol-icq.jar \
+ reference:file:sc-bundles/smacklib.jar \
+ reference:file:sc-bundles/protocol-jabber.jar \
+ reference:file:sc-bundles/protocol-msn.jar \
+ reference:file:sc-bundles/protocol-yahoo.jar \
+ reference:file:sc-bundles/protocol-gibberish.jar \
+ reference:file:sc-bundles/netaddr.jar \
+ reference:file:sc-bundles/protocol-zeroconf.jar \
+ reference:file:sc-bundles/meta-cl.jar
+
+felix.auto.start.60= \
+ reference:file:sc-bundles/history.jar \
+ reference:file:sc-bundles/msghistory.jar \
+ reference:file:sc-bundles/callhistory.jar \
+ reference:file:sc-bundles/audionotifier.jar
+
+
+ felix.auto.start.66= \
+ reference:file:sc-bundles/swing-ui.jar \
+ reference:file:sc-bundles/systray.jar
+
+ felix.auto.start.67= \
+ reference:file:sc-bundles/pluginmanager.jar \
+ reference:file:sc-bundles/icqaccregwizz.jar \
+ reference:file:sc-bundles/aimaccregwizz.jar \
+ reference:file:sc-bundles/jabberaccregwizz.jar \
+ reference:file:sc-bundles/msnaccregwizz.jar \
+ reference:file:sc-bundles/yahooaccregwizz.jar \
+ reference:file:sc-bundles/gibberishaccregwizz.jar \
+ reference:file:sc-bundles/extendedcallhistorysearch.jar \
+ reference:file:sc-bundles/zeroconfaccregwizz.jar \
+ reference:file:sc-bundles/shutdown.jar
+
+# Uncomment the following lines if you want to run the architect viewer
+# bundle.
+#oscar.auto.start.100= \
+# file:lib/bundle/architectureviewer1.1.jar
+
+#Specify the directory where oscar should deploy its bundles
+ felix.cache.profiledir=sip-communicator.bin
+#felix.cache.profiledir=${user.home}/.sip-communicator/profiledir
+
+felix.startlevel.framework=100
+felix.startlevel.bundle=100
+#
+# Bundle config properties.
+#
+#org.osgi.service.http.port=8080
+#osgi.shell.telnet=on
+#oscar.repository.url=file:/home/rickhall/projects/noscar/repository.xml
+oscar.embedded.execution=false
diff --git a/lib/installer-exclude/aclibico-2.1.jar b/lib/installer-exclude/aclibico-2.1.jar
new file mode 100644
index 000000000..5f6b57673
Binary files /dev/null and b/lib/installer-exclude/aclibico-2.1.jar differ
diff --git a/src/net/java/sip/communicator/impl/protocol/rss/ContactRssImpl.java b/src/net/java/sip/communicator/impl/protocol/rss/ContactRssImpl.java
index a9a771a46..7b67289ce 100644
--- a/src/net/java/sip/communicator/impl/protocol/rss/ContactRssImpl.java
+++ b/src/net/java/sip/communicator/impl/protocol/rss/ContactRssImpl.java
@@ -12,10 +12,17 @@
import net.java.sip.communicator.util.*;
import java.net.*;
+import com.ctreber.aclib.image.ico.*;
+import java.io.*;
+import java.awt.*;
+import javax.imageio.*;
+import java.awt.image.*;
+
/**
* An implementation of a rss Contact.
*
* @author Jean-Albert Vescovo
+ * @author Mihai Balan
*/
public class ContactRssImpl
implements Contact
@@ -30,6 +37,11 @@ public class ContactRssImpl
private static SimpleDateFormat DATE_FORMATTER =
new SimpleDateFormat("yyyy.MM.dd-HH:mm:ss");
+ /**
+ * The path within the bundle for the default RSS 64x64 icon.
+ */
+ private String defaultIconPath = "resources/images/rss/rss64x64.png";
+
/**
* The source flow for this contact.
*/
@@ -200,14 +212,124 @@ private void convertStringToDate(String lastDate)
}
/**
- * Returns a byte array containing an image (most often a photo or an
- * avatar) that the contact uses as a representation.
+ * Returns a byte array containing an image to represent the feed. This is
+ * acquired either via the favicon.ico file on the server where the
+ * feed resides, either a default standard RSS icon is returned.
*
- * @return byte[] an image representing the contact.
+ * @return byte[] the binary representation of the best available image in
+ * the icon, or null in case the image is invalid or inexistent.
*/
public byte[] getImage()
{
- return null;
+ Image selectedIcon;
+
+ //we use these to get the best possible icon in case our favicon is a
+ //multi-page icon.
+ int maxWidth = 0;
+ int maxColors = 0;
+ int crtDescriptor = -1;
+
+ //used for ICO to PNG translation. Uses PNG as it's the "safest" choice.
+ ByteArrayOutputStream output = new ByteArrayOutputStream();
+ byte[] result = null;
+
+ URL feedLocation = getRssURL();
+
+ //TODO: Fix aclico log4j-related errors
+
+ try
+ {
+ URL location = new URL(feedLocation.getProtocol() + "://"
+ + feedLocation.getHost() + "/favicon.ico");
+ ICOFile favicon = new ICOFile(location);
+
+ logger.trace("Icon has " + favicon.getImageCount() + " pages");
+
+ for (int i = 0; i < favicon.getDescriptors().size(); i++)
+ {
+ BitmapDescriptor bmpDesc = favicon.getDescriptor(i);
+ if ((maxWidth < bmpDesc.getWidth()))
+ {
+ maxWidth = bmpDesc.getWidth();
+ maxColors = bmpDesc.getColorCount();
+ crtDescriptor = i;
+ }
+
+ if ((maxColors < bmpDesc.getColorCount()))
+ {
+ maxWidth = bmpDesc.getWidth();
+ maxColors = bmpDesc.getColorCount();
+ crtDescriptor = i;
+ }
+ }
+
+ //if icons is either invalid or contains no data, return the default
+ // RSS icon.
+ if (crtDescriptor == -1)
+ {
+ return getDefaultRssIcon();
+ }
+
+ selectedIcon = favicon.getDescriptor(crtDescriptor).getImageRGB();
+
+ //decode ICO as a PNG and return the result
+ ImageIO.write((BufferedImage)selectedIcon, "PNG", output);
+ result = output.toByteArray();
+
+ logger.trace("Result has " + result.length + " bytes");
+ logger.trace("Icon is " + maxWidth + " px X " + maxWidth + " px @ "
+ + maxColors + " colors");
+
+ output.close();
+ return result;
+ }
+ catch (MalformedURLException murlex)
+ {
+ //this shouldn't happen. Ever.
+ logger.error("Malformed URL " + murlex,
+ murlex);
+ }
+ catch (IOException ioex)
+ {
+ logger.error("I/O Error on favicon retrieval. " + ioex,
+ ioex);
+ }
+ return getDefaultRssIcon();
+ }
+
+ /**
+ * Returns the default icon in case the feed has no favicon on the server.
+ * Uses the defaultIconPath to locate the default icon to be
+ * displayed.
+ *
+ * @return binary representation of the default icon
+ */
+ private byte[] getDefaultRssIcon()
+ {
+ logger.trace("Loading default icon at " + defaultIconPath);
+
+ InputStream is = ContactRssImpl.class.getClassLoader()
+ .getResourceAsStream(defaultIconPath);
+
+ byte[] result = null;
+
+ //if something happened and the resource isn't at the specified location
+ //(messed jar-s, wrong filename, etc.) just return now
+ if (is == null)
+ return result;
+ try
+ {
+ logger.trace("Icon is "+is.available() + " bytes long");
+ result = new byte[is.available()];
+ is.read(result);
+ }
+ catch (IOException ioex)
+ {
+ logger.error("Error loading default icon at" + defaultIconPath,
+ ioex);
+ }
+ return result;
+
}
/**
@@ -234,7 +356,7 @@ public void setPresenceStatus(PresenceStatus rssPresenceStatus)
/**
* Returns a reference to the protocol provider that created the contact.
*
- * @return a refererence to an instance of the ProtocolProviderService
+ * @return a reference to an instance of the ProtocolProviderService
*/
public ProtocolProviderService getProtocolProvider()
{
diff --git a/src/net/java/sip/communicator/impl/protocol/rss/OperationSetBasicInstantMessagingRssImpl.java b/src/net/java/sip/communicator/impl/protocol/rss/OperationSetBasicInstantMessagingRssImpl.java
index 33be96bcb..2ffa56882 100644
--- a/src/net/java/sip/communicator/impl/protocol/rss/OperationSetBasicInstantMessagingRssImpl.java
+++ b/src/net/java/sip/communicator/impl/protocol/rss/OperationSetBasicInstantMessagingRssImpl.java
@@ -16,6 +16,7 @@
* Instant messaging functionalites for the Rss protocol.
*
* @author Jean-Albert Vescovo
+ * @author Mihai Balan
*/
public class OperationSetBasicInstantMessagingRssImpl
implements OperationSetBasicInstantMessaging,
@@ -97,8 +98,10 @@ public void addMessageListener(MessageListener listener)
public Message createMessage(byte[] content, String contentType,
String contentEncoding, String subject)
{
- return new MessageRssImpl(new String(content), contentType
- , contentEncoding, subject);
+ return new MessageRssImpl(new String(content),
+ contentType,
+ contentEncoding,
+ subject);
}
/**
@@ -110,9 +113,10 @@ public Message createMessage(byte[] content, String contentType,
*/
public Message createMessage(String messageText)
{
-
- return new MessageRssImpl(messageText, DEFAULT_MIME_TYPE
- , DEFAULT_MIME_ENCODING, null);
+ return new MessageRssImpl(messageText,
+ "text/html",
+ DEFAULT_MIME_ENCODING,
+ null);
}
/**
@@ -356,9 +360,9 @@ public boolean isOfflineMessagingSupported()
{
return false;
}
-
+
/**
- * Determines wheter the protocol supports the supplied content type
+ * Determines whether the protocol supports the supplied content type
*
* @param contentType the type we want to check
* @return true if the protocol supports it and
@@ -368,6 +372,8 @@ public boolean isContentTypeSupported(String contentType)
{
if(contentType.equals(DEFAULT_MIME_TYPE))
return true;
+ else if(contentType.equals("text/html"))
+ return true;
else
return false;
}
diff --git a/src/net/java/sip/communicator/impl/protocol/rss/RssFeedReader.java b/src/net/java/sip/communicator/impl/protocol/rss/RssFeedReader.java
index ac9cab819..a684c1f62 100644
--- a/src/net/java/sip/communicator/impl/protocol/rss/RssFeedReader.java
+++ b/src/net/java/sip/communicator/impl/protocol/rss/RssFeedReader.java
@@ -18,6 +18,7 @@
* The class used for using the Informa Library into the RSS protocol
*
* @author Jean-Albert Vescovo
+ * @author Mihai Balan
*/
public class RssFeedReader
{
@@ -65,7 +66,7 @@ public RssFeedReader(URL contactRssURL)
{
this.rssURL = contactRssURL;
- /** @todo should retrieve this from a resource file.*/
+ /* TODO should retrieve this from a resource file.*/
this.title = "No feed avalaible !";
}
@@ -103,7 +104,8 @@ public void retrieveFlow()
//chronological order
items = (SyndEntry[]) (this.feed.getEntries()
.toArray(new SyndEntry[0]));
- sortItems();
+ //sort items
+ Arrays.sort(items, syndEntryComparator);
//if we don't understand the date format we don't want to handle
//this feed
@@ -145,10 +147,13 @@ public void retrieveFlow()
*/
public synchronized String feedToString(Date latestRetrievedItemDate)
{
+ String newsAbstract = null;
StringBuffer printedFeed = new StringBuffer();
+ /* TODO move this in a resources file.*/
if (items.length == 0)
- return "No items currently available for this feed !";
+ return "No items currently available for this feed !
";
+
//go through the items list in reverse order so that we could stop
//as soon as we reach items that we've already shown to the user.
@@ -157,37 +162,32 @@ public synchronized String feedToString(Date latestRetrievedItemDate)
if (items[i].getPublishedDate()
.compareTo(latestRetrievedItemDate) > 0)
{
- printedFeed.insert(
- 0
- , "\nAt " + items[i].getPublishedDate()
- + " - " + items[i].getTitle()
- + "\nLink: " + items[i].getLink() + "\n\n");
+ // Get the abstract of the news.
+ newsAbstract = items[i].getDescription().getValue();
+ // Forge the news to be displayed.
+ printedFeed.insert(0, "At "
+ + items[i].getPublishedDate()
+ + "
"+ items[i].getTitle() + ""
+ + " Link
");
}
else
{
if (i == items.length - 1)
{
printedFeed
- .append("\n\nNo new articles in your feed since"
- + " last update.");
+ .append("No new articles in your feed since"
+ + " last update.
");
+
}
break;
}
}
- printedFeed.append ("\n\nSend anything to refresh this feed...");
+ printedFeed
+ .append ("Send anything to refresh this feed...
\n");
return printedFeed.toString();
}
- /**
- * Sorts the items retrieved from the rss contact/feed associated with this
- * reader. The method uses a bubble sort algorithm.
- */
- private void sortItems()
- {
- Arrays.sort(items, syndEntryComparator);
- }
-
/**
* Returns a Date that can be used to know the most recent item in a
* retrieved feed.
diff --git a/src/net/java/sip/communicator/impl/protocol/rss/rss.provider.manifest.mf b/src/net/java/sip/communicator/impl/protocol/rss/rss.provider.manifest.mf
index 09b8d2ab0..f8d7ddd1e 100644
--- a/src/net/java/sip/communicator/impl/protocol/rss/rss.provider.manifest.mf
+++ b/src/net/java/sip/communicator/impl/protocol/rss/rss.provider.manifest.mf
@@ -12,5 +12,7 @@ Import-Package: org.osgi.framework,
net.java.sip.communicator.service.configuration.event,
net.java.sip.communicator.util,
net.java.sip.communicator.service.protocol,
- net.java.sip.communicator.service.protocol.event
+ net.java.sip.communicator.service.protocol.event,
+ org.apache.log4j,
+ javax.imageio