RSS ProtocolProvider.

cusax-fix
Damian Minkov 19 years ago
parent 2dfda98983
commit 03262f0dd4

@ -852,6 +852,7 @@
bundle-growlnotification,bundle-audionotifier,bundle-plugin-splashscreen,
bundle-systray,bundle-browserlauncher,bundle-gibberish,
bundle-gibberish-slick,bundle-plugin-gibberishaccregwizz,
bundle-rss,bundle-plugin-rssaccregwizz,
bundle-pluginmanager"/>
<!--BUNDLE-HISTORY-->
@ -1535,7 +1536,7 @@ javax.swing.event, javax.swing.border"/>
</jar>
</target>
<!-- BUNDLE-PLUGIN MANAGER -->
<!-- BUNDLE-PLUGIN MANAGER -->
<target name="bundle-pluginmanager">
<!-- Creates a bundle for the plugin manager plugin.-->
<jar compress="false" destfile="${bundles.dest}/pluginmanager.jar"
@ -1544,4 +1545,34 @@ javax.swing.event, javax.swing.border"/>
prefix="net/java/sip/communicator/plugin/pluginmanager"/>
</jar>
</target>
<!-- BUNDLE-RSS -->
<target name="bundle-rss">
<!-- Creates a bundle containing the Rss impl of the protocol provider.-->
<jar compress="false" destfile="${bundles.dest}/protocol-rss.jar"
manifest="src/net/java/sip/communicator/impl/protocol/rss/rss.provider.manifest.mf">
<zipfileset dir="${dest}/net/java/sip/communicator/impl/protocol/rss"
prefix="net/java/sip/communicator/impl/protocol/rss"/>
<!-- LIBRARIES FOR RSS PROTOCOL, INCLUDING JDOM-1.0 AND ROME-0.9/-->
<zipfileset src="${lib.noinst}/jdom.jar" prefix=""/>
<zipfileset src="${lib.noinst}/rome-0.9.jar" prefix=""/>
<zipfileset dir="resources/images/rss"
prefix="resources/images/rss"/>
</jar>
</target>
<!-- BUNDLE-PLUGIN-RSSACCREGWIZZ -->
<target name="bundle-plugin-rssaccregwizz">
<!-- Creates a bundle for the plugin Rss Account Registration
Wizard.-->
<jar compress="false" destfile="${bundles.dest}/rssaccregwizz.jar"
manifest="src/net/java/sip/communicator/plugin/rssaccregwizz/rssaccregwizz.manifest.mf">
<zipfileset dir="${dest}/net/java/sip/communicator/plugin/rssaccregwizz"
prefix="net/java/sip/communicator/plugin/rssaccregwizz"/>
<zipfileset dir="resources/images/rss"
prefix="resources/images/rss"/>
</jar>
</target>
</project>

@ -34,7 +34,10 @@ org.osgi.framework.system.packages= org.osgi.framework; \
javax.sound.sampled; \
org.jdesktop.jdic.tray; \
org.jdesktop.jdic.desktop; \
com.apple.eio;
com.apple.eio; \
org.xml.sax.helpers; \
org.jdom; \
org.jdom.input;
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
@ -68,7 +71,8 @@ felix.auto.start.50= \
reference:file:sc-bundles/protocol-yahoo.jar \
reference:file:sc-bundles/protocol-gibberish.jar \
reference:file:sc-bundles/netaddr.jar \
reference:file:sc-bundles/meta-cl.jar
reference:file:sc-bundles/meta-cl.jar \
reference:file:sc-bundles/protocol-rss.jar
felix.auto.start.60= \
reference:file:sc-bundles/history.jar \
@ -90,7 +94,8 @@ felix.auto.start.60= \
reference:file:sc-bundles/msnaccregwizz.jar \
reference:file:sc-bundles/yahooaccregwizz.jar \
reference:file:sc-bundles/gibberishaccregwizz.jar \
reference:file:sc-bundles/shutdown.jar
reference:file:sc-bundles/shutdown.jar \
reference:file:sc-bundles/rssaccregwizz.jar
# Uncomment the following lines if you want to run the architect viewer
# bundle.

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 413 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 662 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

@ -0,0 +1,620 @@
/*
* 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.impl.protocol.rss;
import java.util.*;
import net.java.sip.communicator.service.protocol.*;
import net.java.sip.communicator.util.*;
/**
* A simple, straightforward implementation of a rss ContactGroup. Since
* the Rss protocol is not a real one, we simply store all group details
* in class fields. You should know that when implementing a real protocol,
* the contact group implementation would rather encapsulate group objects from
* the protocol stack and group property values should be returned by consulting
* the encapsulated object.
*
* @author Emil Ivov
*/
public class ContactGroupRssImpl
implements ContactGroup
{
private static final Logger logger
= Logger.getLogger(ContactGroupRssImpl.class);
/**
* The name of this Rss contact group.
*/
private String groupName = null;
/**
* The list of this group's members.
*/
private Vector contacts = new Vector();
/**
* The list of sub groups belonging to this group.
*/
private Vector subGroups = new Vector();
/**
* The group that this group belongs to (or null if this is the root group).
*/
private ContactGroupRssImpl parentGroup = null;
/**
* Determines whether this group is really in the contact list or whether
* it is here only temporarily and will be gone next time we restart.
*/
private boolean isPersistent = true;
/**
* The protocol provider that created us.
*/
private ProtocolProviderServiceRssImpl parentProvider = null;
/**
* Determines whether this group has been resolved on the server.
* Unresolved groups are groups that were available on previous runs and
* that the meta contact list has stored. During all next runs, when
* bootstrapping, the meta contact list would create these groups as
* unresolved. Once a protocol provider implementation confirms that the
* groups are still on the server, it would issue an event indicating that
* the groups are now resolved.
*/
private boolean isResolved = true;
/**
* An id uniquely identifying the group. For many protocols this could be
* the group name itself.
*/
private String uid = null;
private static final String UID_SUFFIX = ".uid";
/**
* Creates a ContactGroupRssImpl with the specified name.
*
* @param groupName the name of the group.
* @param parentProvider the protocol provider that created this group.
*/
public ContactGroupRssImpl(
String groupName,
ProtocolProviderServiceRssImpl parentProvider)
{
this.groupName = groupName;
this.uid = groupName + UID_SUFFIX;
this.parentProvider = parentProvider;
}
/**
* Determines whether the group may contain subgroups or not.
*
* @return always true in this implementation.
*/
public boolean canContainSubgroups()
{
return true;
}
/**
* Returns the protocol provider that this group belongs to.
* @return a regerence to the ProtocolProviderService instance that this
* ContactGroup belongs to.
*/
public ProtocolProviderService getProtocolProvider()
{
return parentProvider;
}
/**
* Returns an Iterator over all contacts, member of this
* <tt>ContactGroup</tt>.
*
* @return a java.util.Iterator over all contacts inside this
* <tt>ContactGroup</tt>
*/
public Iterator contacts()
{
return contacts.iterator();
}
/**
* Adds the specified contact to this group.
* @param contactToAdd the ContactRssImpl to add to this group.
*/
public void addContact(ContactRssImpl contactToAdd)
{
this.contacts.add(contactToAdd);
contactToAdd.setParentGroup(this);
}
/**
* Returns the number of <tt>Contact</tt> members of this
* <tt>ContactGroup</tt>
*
* @return an int indicating the number of <tt>Contact</tt>s, members of
* this <tt>ContactGroup</tt>.
*/
public int countContacts()
{
return contacts.size();
}
/**
* Returns the number of subgroups contained by this
* <tt>ContactGroup</tt>.
*
* @return the number of subGroups currently added to this group.
*/
public int countSubgroups()
{
return subGroups.size();
}
/**
* Adds the specified contact group to the contained by this group.
* @param subgroup the ContactGroupRssImpl to add as a subgroup to this group.
*/
public void addSubgroup(ContactGroupRssImpl subgroup)
{
this.subGroups.add(subgroup);
subgroup.setParentGroup(this);
}
/**
* Sets the group that is the new parent of this group
* @param parent ContactGroupRssImpl
*/
void setParentGroup(ContactGroupRssImpl parent)
{
this.parentGroup = parent;
}
/**
* Returns the contact group that currently contains this group or null if
* this is the root contact group.
* @return the contact group that currently contains this group or null if
* this is the root contact group.
*/
public ContactGroup getParentContactGroup()
{
return this.parentGroup;
}
/**
* Removes the specified contact group from the this group's subgroups.
* @param subgroup the ContactGroupRssImpl subgroup to remove.
*/
public void removeSubGroup(ContactGroupRssImpl subgroup)
{
this.subGroups.remove(subgroup);
subgroup.setParentGroup(null);
}
/**
* Returns the <tt>Contact</tt> with the specified index.
*
* @param index the index of the <tt>Contact</tt> to return.
* @return the <tt>Contact</tt> with the specified index.
*/
public Contact getContact(int index)
{
return (ContactRssImpl)contacts.get(index);
}
/**
* Returns the group that is parent of the specified rssGroup or null
* if no parent was found.
* @param rssGroup the group whose parent we're looking for.
* @return the ContactGroupRssImpl instance that rssGroup
* belongs to or null if no parent was found.
*/
public ContactGroupRssImpl findGroupParent(
ContactGroupRssImpl rssGroup)
{
if ( subGroups.contains(rssGroup) )
return this;
Iterator subGroupsIter = subgroups();
while (subGroupsIter.hasNext())
{
ContactGroupRssImpl subgroup
= (ContactGroupRssImpl) subGroupsIter.next();
ContactGroupRssImpl parent
= subgroup.findGroupParent(rssGroup);
if(parent != null)
return parent;
}
return null;
}
/**
* Returns the group that is parent of the specified rssContact or
* null if no parent was found.
*
* @param rssContact the contact whose parent we're looking for.
* @return the ContactGroupRssImpl instance that rssContact
* belongs to or <tt>null</tt> if no parent was found.
*/
public ContactGroupRssImpl findContactParent(
ContactRssImpl rssContact)
{
if ( contacts.contains(rssContact) )
return this;
Iterator subGroupsIter = subgroups();
while (subGroupsIter.hasNext())
{
ContactGroupRssImpl subgroup
= (ContactGroupRssImpl) subGroupsIter.next();
ContactGroupRssImpl parent
= subgroup.findContactParent(rssContact);
if(parent != null)
return parent;
}
return null;
}
/**
* Returns the <tt>Contact</tt> with the specified address or identifier.
*
* @param id the addres or identifier of the <tt>Contact</tt> we are
* looking for.
* @return the <tt>Contact</tt> with the specified id or address.
*/
public Contact getContact(String id)
{
Iterator contactsIter = contacts();
while (contactsIter.hasNext())
{
ContactRssImpl contact = (ContactRssImpl) contactsIter.next();
if (contact.getAddress().equals(id))
return contact;
}
return null;
}
/**
* Returns the subgroup with the specified index.
*
* @param index the index of the <tt>ContactGroup</tt> to retrieve.
* @return the <tt>ContactGroup</tt> with the specified index.
*/
public ContactGroup getGroup(int index)
{
return (ContactGroup)subGroups.get(index);
}
/**
* Returns the subgroup with the specified name.
*
* @param groupName the name of the <tt>ContactGroup</tt> to retrieve.
* @return the <tt>ContactGroup</tt> with the specified index.
*/
public ContactGroup getGroup(String groupName)
{
Iterator groupsIter = subgroups();
while (groupsIter.hasNext())
{
ContactGroupRssImpl contactGroup
= (ContactGroupRssImpl) groupsIter.next();
if (contactGroup.getGroupName().equals(groupName))
return contactGroup;
}
return null;
}
/**
* Returns the name of this group.
*
* @return a String containing the name of this group.
*/
public String getGroupName()
{
return this.groupName;
}
/**
* Sets this group a new name.
* @param newGrpName a String containing the new name of this group.
*/
public void setGroupName(String newGrpName)
{
this.groupName = newGrpName;
}
/**
* Returns an iterator over the sub groups that this
* <tt>ContactGroup</tt> contains.
*
* @return a java.util.Iterator over the <tt>ContactGroup</tt> children
* of this group (i.e. subgroups).
*/
public Iterator subgroups()
{
return subGroups.iterator();
}
/**
* Removes the specified contact from this group.
* @param contact the ContactRssImpl to remove from this group
*/
public void removeContact(ContactRssImpl contact)
{
this.contacts.remove(contact);
}
/**
* Returns the contact with the specified id or null if no such contact
* exists.
* @param id the id of the contact we're looking for.
* @return ContactRssImpl
*/
public ContactRssImpl findContactByID(String id)
{
//first go through the contacts that are direct children.
Iterator contactsIter = contacts();
while(contactsIter.hasNext())
{
ContactRssImpl mContact = (ContactRssImpl)contactsIter.next();
if( mContact.getAddress().equals(id) )
return mContact;
}
//if we didn't find it here, let's try in the subougroups
Iterator groupsIter = subgroups();
while( groupsIter.hasNext() )
{
ContactGroupRssImpl mGroup = (ContactGroupRssImpl)groupsIter.next();
ContactRssImpl mContact = mGroup.findContactByID(id);
if (mContact != null)
return mContact;
}
return null;
}
/**
* Returns a String representation of this group and the contacts it
* contains (may turn out to be a relatively long string).
* @return a String representing this group and its child contacts.
*/
public String toString()
{
StringBuffer buff = new StringBuffer(getGroupName());
buff.append(".subGroups=" + countSubgroups() + ":\n");
Iterator subGroups = subgroups();
while (subGroups.hasNext())
{
ContactGroupRssImpl group = (ContactGroupRssImpl)subGroups.next();
buff.append(group.toString());
if (subGroups.hasNext())
buff.append("\n");
}
buff.append("\nChildContacts="+countContacts()+":[");
Iterator contacts = contacts();
while (contacts.hasNext())
{
ContactRssImpl contact = (ContactRssImpl) contacts.next();
buff.append(contact.toString());
if(contacts.hasNext())
buff.append(", ");
}
return buff.append("]").toString();
}
public Vector getRssURLList(Vector rssURLList){
//private Vector rssURLList;
//StringBuffer buff = new StringBuffer(getGroupName());
//buff.append(".subGroups=" + countSubgroups() + ":\n");
Iterator subGroups = subgroups();
while (subGroups.hasNext())
{
ContactGroupRssImpl group = (ContactGroupRssImpl)subGroups.next();
//buff.append(
group.getRssURLList(rssURLList);
// if (subGroups.hasNext())
// buff.append("\n");
}
//buff.append("\nChildContacts="+countContacts()+":[");
Iterator contacts = contacts();
while (contacts.hasNext())
{
ContactRssImpl contact = (ContactRssImpl) contacts.next();
//buff.append(contact.getDisplayName());
rssURLList.addElement(contact);
//if(contacts.hasNext())
// buff.append(", ");
}
//return buff.append("]").toString();
return rssURLList;
}
/**
* Specifies whether or not this contact group is being stored by the server.
* Non persistent contact groups are common in the case of simple,
* non-persistent presence operation sets. They could however also be seen
* in persistent presence operation sets when for example we have received
* an event from someone not on our contact list and the contact that we
* associated with that user is placed in a non persistent group. Non
* persistent contact groups are volatile even when coming from a persistent
* presence op. set. They would only exist until the application is closed
* and will not be there next time it is loaded.
*
* @param isPersistent true if the contact group is to be persistent and
* false otherwise.
*/
public void setPersistent(boolean isPersistent)
{
this.isPersistent = isPersistent;
}
/**
* Determines whether or not this contact group is being stored by the
* server. Non persistent contact groups exist for the sole purpose of
* containing non persistent contacts.
* @return true if the contact group is persistent and false otherwise.
*/
public boolean isPersistent()
{
return isPersistent;
}
/**
* Returns null as no persistent data is required and the contact address is
* sufficient for restoring the contact.
* <p>
* @return null as no such data is needed.
*/
public String getPersistentData()
{
return null;
}
/**
* Determines whether or not this contact has been resolved against the
* server. Unresolved contacts are used when initially loading a contact
* list that has been stored in a local file until the presence operation
* set has managed to retrieve all the contact list from the server and has
* properly mapped contacts to their on-line buddies.
* @return true if the contact has been resolved (mapped against a buddy)
* and false otherwise.
*/
public boolean isResolved()
{
return isResolved;
}
/**
* Makes the group resolved or unresolved.
*
* @param resolved true to make the group resolved; false to
* make it unresolved
*/
public void setResolved(boolean resolved)
{
this.isResolved = resolved;
}
/**
* Returns a <tt>String</tt> that uniquely represnets the group inside
* the current protocol. The string MUST be persistent (it must not change
* across connections or runs of the application). In many cases (Jabber,
* ICQ) the string may match the name of the group as these protocols
* only allow a single level of contact groups and there is no danger of
* having the same name twice in the same contact list. Other protocols
* (no examples come to mind but that doesn't bother me ;) ) may be
* supporting mutilple levels of grooups so it might be possible for group
* A and group B to both contain groups named C. In such cases the
* implementation must find a way to return a unique identifier in this
* method and this UID should never change for a given group.
*
* @return a String representing this group in a unique and persistent
* way.
*/
public String getUID()
{
return uid;
}
/**
* Ugly but tricky conversion method.
* @param uid the uid we'd like to get a name from
* @return the name of the group with the specified <tt>uid</tt>.
*/
static String createNameFromUID(String uid)
{
return uid.substring(0, uid.length() - (UID_SUFFIX.length()));
}
/**
* Indicates whether some other object is "equal to" this one which in terms
* of contact groups translates to having the equal names and matching
* subgroups and child contacts. The resolved status of contactgroups and
* contacts is deliberately ignored so that groups and/or contacts would
* be assumed equal even if it differs.
* <p>
* @param obj the reference object with which to compare.
* @return <code>true</code> if this contact group has the equal child
* contacts and subgroups to those of the <code>obj</code> argument.
*/
public boolean equals(Object obj)
{
if(obj == null
|| !(obj instanceof ContactGroupRssImpl))
return false;
ContactGroupRssImpl rssGroup
= (ContactGroupRssImpl)obj;
if( ! rssGroup.getGroupName().equals(getGroupName())
|| ! rssGroup.getUID().equals(getUID())
|| rssGroup.countContacts() != countContacts()
|| rssGroup.countSubgroups() != countSubgroups())
return false;
//traverse child contacts
Iterator theirContacts = rssGroup.contacts();
while(theirContacts.hasNext())
{
ContactRssImpl theirContact
= (ContactRssImpl)theirContacts.next();
ContactRssImpl ourContact
= (ContactRssImpl)getContact(theirContact.getAddress());
if(ourContact == null
|| !ourContact.equals(theirContact))
return false;
}
//traverse subgroups
Iterator theirSubgroups = rssGroup.subgroups();
while(theirSubgroups.hasNext())
{
ContactGroupRssImpl theirSubgroup
= (ContactGroupRssImpl)theirSubgroups.next();
ContactGroupRssImpl ourSubgroup
= (ContactGroupRssImpl)getGroup(
theirSubgroup.getGroupName());
if(ourSubgroup == null
|| !ourSubgroup.equals(theirSubgroup))
return false;
}
return true;
}
}

@ -0,0 +1,428 @@
/*
* 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.impl.protocol.rss;
import java.util.*;
import java.text.*;
import net.java.sip.communicator.service.protocol.*;
import net.java.sip.communicator.util.*;
/**
* An implementation of a rss Contact.
*
* @author Jean-Albert Vescovo
*/
public class ContactRssImpl
implements Contact
{
private String lastDate = null;
private Date date = null;
private String nickName = null;
private static final Logger logger
= Logger.getLogger(ContactRssImpl.class);
private static SimpleDateFormat DATE_FORMATTER =
new SimpleDateFormat("yyyy.MM.dd-HH:mm:ss");
/**
* The id of the contact.
*/
private String contactID = null;
/**
* The provider that created us.
*/
private ProtocolProviderServiceRssImpl parentProvider = null;
/**
* The group that belong to.
*/
private ContactGroupRssImpl parentGroup = null;
/**
* The presence status of the contact.
*/
private PresenceStatus presenceStatus = RssStatusEnum.ONLINE;
/**
* Determines whether this contact is persistent, i.e. member of the contact
* list or whether it is here only temporarily.
*/
private boolean isPersistent = true;
/**
* Determines whether the contact has been resolved (i.e. we have a
* confirmation that it is still on the server contact list).
*/
private boolean isResolved = false;
/**
* Creates an instance of a meta contact with the specified string used
* as a name and identifier.
*
* @param id the identifier of this contact (also used as a name).
* @param parentProvider the provider that created us.
*/
public ContactRssImpl(
String id,
ProtocolProviderServiceRssImpl parentProvider)
{
this.contactID = id;
this.parentProvider = parentProvider;
}
/**
* This method is only called when the contact is added to a new
* <tt>ContactGroupRssImpl</tt> by the
* <tt>ContactGroupRssImpl</tt> itself.
*
* @param newParentGroup the <tt>ContactGroupRssImpl</tt> that is now
* parent of this <tt>ContactRssImpl</tt>
*/
void setParentGroup(ContactGroupRssImpl newParentGroup)
{
this.parentGroup = newParentGroup;
}
/**
* Returns a String that can be used for identifying the contact.
*
* @return a String id representing and uniquely identifying the contact.
*/
public String getAddress()
{
return contactID;
}
/**
* Returns a String that could be used by any user interacting modules
* for referring to this contact.
*
* @return a String that can be used for referring to this contact when
* interacting with the user.
*/
public String getDisplayName()
{
if(nickName == null) return contactID;
else return nickName;
}
public void setDisplayName(String nickName){
this.nickName = nickName;
}
/**
* Returns a Date corresponding to the date of the last query
* on this rss contact.
*
* @return a Date in order to compare with a new one obtained via
* a query on the feed.
*/
public Date getDate()
{
return this.date;
}
/**
* This method is only called when a new date is found after a query
* on the feed corresponding to this contact
*
* @param date the <tt>Date</tt> that is now
* the last update date of the <tt>ContactRssImpl</tt>
*/
public void setDate(Date date)
{
this.date = date;
this.lastDate = convertDateToString(this.date);
}
/**
* Updating the lastDate in String format of the contact
*
* @param lastDate the <tt>String</tt> that is now
* the last update date of the <tt>ContactRssImpl</tt>
*/
public void setLastDate(String lastDate)
{
this.lastDate = lastDate;
}
/**
* Returns a String corresponding to the date of the last query
* on this rss contact.
*
* @return a String representing a Date in order to compare with
* a new one obtained via a query on the feed.
*/
public String getLastDate()
{
return this.lastDate;
}
/**
* Returns a String corresponding to a date after a conversion
* from a Date
*
* @param date the date
* @return a String which is placed in the lastDate variable of the
* present contact
*/
private String convertDateToString(Date date)
{
return DATE_FORMATTER.format(date);
}
/**
* This method is called when a the contact is restored and a
* previous saved lastDate is found as persistent-data: this
* data is in a String format, and this method convert it into
* a Date usable by the protocol.
* @param lastDate date as String
*/
private void convertStringToDate(String lastDate)
{
try
{
this.date = DATE_FORMATTER.parse(lastDate);
}
catch(ParseException ex)
{
logger.error("Cannot parse Date", ex);
}
}
/**
* Returns an array of String corresponding to a date bursted in multiple
* fields as this:
* ddd mmm DD HH:mm:ss ZZZZ YYYY
*
* @return an Array of String
*/
private String[] getToken(String param1, String param2)
{
int i = 0;
String data[] = new String[8];
StringTokenizer tmp = new StringTokenizer(param1, param2);
while(tmp.hasMoreTokens())
{
data[i] = tmp.nextToken();
i++;
}
return data;
}
/**
* Returns a byte array containing an image (most often a photo or an
* avatar) that the contact uses as a representation.
*
* @return byte[] an image representing the contact.
*/
public byte[] getImage()
{
return null;
}
/**
* Returns the status of the contact.
*
* @return RssStatusEnum.STATUS.
*/
public PresenceStatus getPresenceStatus()
{
return this.presenceStatus;
}
/**
* Sets <tt>rssPresenceStatus</tt> as the PresenceStatus that this
* contact is currently in.
* @param rssPresenceStatus the <tt>RssPresenceStatus</tt>
* currently valid for this contact.
*/
public void setPresenceStatus(PresenceStatus rssPresenceStatus)
{
this.presenceStatus = rssPresenceStatus;
}
/**
* Returns a reference to the protocol provider that created the contact.
*
* @return a refererence to an instance of the ProtocolProviderService
*/
public ProtocolProviderService getProtocolProvider()
{
return parentProvider;
}
/**
* Determines whether or not this contact represents our own identity.
*
* @return true in case this is a contact that represents ourselves and
* false otherwise.
*/
public boolean isLocal()
{
return false;
}
/**
* Returns the group that contains this contact.
* @return a reference to the <tt>ContactGroupRssImpl</tt> that
* contains this contact.
*/
public ContactGroup getParentContactGroup()
{
return this.parentGroup;
}
/**
* Returns a string representation of this contact, containing most of its
* representative details.
*
* @return a string representation of this contact.
*/
public String toString()
{
StringBuffer buff
= new StringBuffer("ContactRssImpl[ DisplayName=")
.append(getDisplayName()).append("]");
return buff.toString();
}
/**
* Determines whether or not this contact is being stored by the server.
* Non persistent contacts are common in the case of simple, non-persistent
* presence operation sets. They could however also be seen in persistent
* presence operation sets when for example we have received an event
* from someone not on our contact list. Non persistent contacts are
* volatile even when coming from a persistent presence op. set. They would
* only exist until the application is closed and will not be there next
* time it is loaded.
*
* @return true if the contact is persistent and false otherwise.
*/
public boolean isPersistent()
{
return isPersistent;
}
/**
* Specifies whether or not this contact is being stored by the server.
* Non persistent contacts are common in the case of simple, non-persistent
* presence operation sets. They could however also be seen in persistent
* presence operation sets when for example we have received an event
* from someone not on our contact list. Non persistent contacts are
* volatile even when coming from a persistent presence op. set. They would
* only exist until the application is closed and will not be there next
* time it is loaded.
*
* @param isPersistent true if the contact is persistent and false
* otherwise.
*/
public void setPersistent(boolean isPersistent)
{
this.isPersistent = isPersistent;
}
/**
* Returns null as no persistent data is required and the contact address is
* sufficient for restoring the contact.
* <p>
* @return null as no such data is needed.
*/
public String getPersistentData()
{
// to store data only when lastDate is set
if(lastDate != null)
return "lastDate=" + lastDate + ";";
else
return null;
}
public void setPersistentData(String persistentData)
{
if(persistentData == null)
{
return;
}
StringTokenizer dataToks = new StringTokenizer(persistentData, ";");
while(dataToks.hasMoreTokens())
{
String data[] = dataToks.nextToken().split("=");
if(data[0].equals("lastDate") && data.length > 1)
{
this.lastDate = data[1];
convertStringToDate(this.lastDate);
}
}
}
/**
* Determines whether or not this contact has been resolved against the
* server. Unresolved contacts are used when initially loading a contact
* list that has been stored in a local file until the presence operation
* set has managed to retrieve all the contact list from the server and has
* properly mapped contacts to their on-line buddies.
*
* @return true if the contact has been resolved (mapped against a buddy)
* and false otherwise.
*/
public boolean isResolved()
{
return isResolved;
}
/**
* Makes the contact resolved or unresolved.
*
* @param resolved true to make the contact resolved; false to
* make it unresolved
*/
public void setResolved(boolean resolved)
{
this.isResolved = resolved;
}
/**
* Indicates whether some other object is "equal to" this one which in terms
* of contacts translates to having equal ids. The resolved status of the
* contacts deliberately ignored so that contacts would be declared equal
* even if it differs.
* <p>
* @param obj the reference object with which to compare.
* @return <code>true</code> if this contact has the same id as that of the
* <code>obj</code> argument.
*/
public boolean equals(Object obj)
{
if (obj == null
|| ! (obj instanceof ContactRssImpl))
return false;
ContactRssImpl rssContact = (ContactRssImpl) obj;
return this.getAddress().equals(rssContact.getAddress());
}
/**
* Returns the persistent presence operation set that this contact belongs
* to.
*
* @return the <tt>OperationSetPersistentPresenceRssImpl</tt> that
* this contact belongs to.
*/
public OperationSetPersistentPresenceRssImpl
getParentPresenceOperationSet()
{
return (OperationSetPersistentPresenceRssImpl)parentProvider
.getOperationSet(OperationSetPersistentPresence.class);
}
}

@ -0,0 +1,137 @@
/*
* 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.impl.protocol.rss;
import net.java.sip.communicator.service.protocol.*;
/**
* Very simple message implementation for the Rss protocol.
*
* @author Emil Ivov
*/
public class MessageRssImpl
implements Message
{
/**
* The actual message content.
*/
private String textContent = null;
/**
* The content type of the message. (text/plain if null)
*/
private String contentType = null;
/**
* The message encoding. (UTF8 if null).
*/
private String contentEncoding = null;
/**
* A String uniquely identifying the message
*/
private String messageUID = null;
/**
* The subject of the message. (most often is null)
*/
private String subject = null;
/**
* Creates a message instance according to the specified parameters.
*
* @param content the message body
* @param contentType message content type or null for text/plain
* @param contentEncoding message encoding or null for UTF8
* @param subject the subject of the message or null for no subject.
*/
public MessageRssImpl(String content,
String contentType,
String contentEncoding,
String subject)
{
this.textContent = content;
this.contentType = contentType;
this.contentEncoding = contentEncoding;
this.subject = subject;
//generate the uid
this.messageUID = String.valueOf(System.currentTimeMillis())
+ String.valueOf(hashCode());
}
/**
* Returns the message body.
*
* @return the message content.
*/
public String getContent()
{
return textContent;
}
/**
* Returns the type of the content of this message.
*
* @return the type of the content of this message.
*/
public String getContentType()
{
return contentType;
}
/**
* Returns the encoding used for the message content.
*
* @return the encoding of the message body.
*/
public String getEncoding()
{
return contentEncoding;
}
/**
* A string uniquely identifying the message.
*
* @return a <tt>String</tt> uniquely identifying the message.
*/
public String getMessageUID()
{
return messageUID;
}
/**
* Returns the message body in a binary form.
*
* @return a <tt>byte[]</tt> representation of the message body.
*/
public byte[] getRawData()
{
return getContent().getBytes();
}
/**
* Return the length of this message.
*
* @return the length of this message.
*/
public int getSize()
{
return getContent().length();
}
/**
* Returns the message subject.
*
* @return the message subject.
*/
public String getSubject()
{
return subject;
}
}

@ -0,0 +1,436 @@
/*
* 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.impl.protocol.rss;
import java.util.*;
import net.java.sip.communicator.service.protocol.*;
import net.java.sip.communicator.service.protocol.event.*;
import java.awt.*;
import java.awt.event.*;
/**
* Instant messaging functionalites for the Rss protocol.
*
* @author Jean-Albert Vescovo
*/
public class OperationSetBasicInstantMessagingRssImpl
implements OperationSetBasicInstantMessaging
{
/**
* Currently registered message listeners.
*/
private Vector messageListeners = new Vector();
/**
* The currently valid persistent presence operation set..
*/
private OperationSetPersistentPresenceRssImpl opSetPersPresence = null;
/**
* The protocol provider that created us.
*/
private ProtocolProviderServiceRssImpl parentProvider = null;
/**
* The timer used in order to refresh one or more rss feeds
*/
private Timer timer = null;
/**
* The value corresponding to the time in ms
* of the rss refreshing period (here 10min)
*/
final int PERIOD_REFRESH_RSS = 600000;
/**
* Creates an instance of this operation set keeping a reference to the
* parent protocol provider and presence operation set.
*
* @param provider The provider instance that creates us.
* @param opSetPersPresence the currently valid
* <tt>OperationSetPersistentPresenceRssImpl</tt> instance.
*/
public OperationSetBasicInstantMessagingRssImpl(
ProtocolProviderServiceRssImpl provider,
OperationSetPersistentPresenceRssImpl opSetPersPresence)
{
this.opSetPersPresence = opSetPersPresence;
this.parentProvider = provider;
}
/**
* Registers a MessageListener with this operation set so that it gets
* notifications of successful message delivery, failure or reception of
* incoming messages..
*
* @param listener the <tt>MessageListener</tt> to register.
*/
public void addMessageListener(MessageListener listener)
{
if(!messageListeners.contains(listener))
messageListeners.add(listener);
}
/**
* Create a Message instance for sending arbitrary MIME-encoding content.
*
* @param content content value
* @param contentType the MIME-type for <tt>content</tt>
* @param contentEncoding encoding used for <tt>content</tt>
* @param subject a <tt>String</tt> subject or <tt>null</tt> for now
* subject.
* @return the newly created message.
*/
public Message createMessage(byte[] content, String contentType,
String contentEncoding, String subject)
{
return new MessageRssImpl(new String(content), contentType
, contentEncoding, subject);
}
/**
* Create a Message instance for sending a simple text messages with
* default (text/plain) content type and encoding.
*
* @param messageText the string content of the message.
* @return Message the newly created message
*/
public Message createMessage(String messageText)
{
return new MessageRssImpl(messageText, DEFAULT_MIME_TYPE
, DEFAULT_MIME_ENCODING, null);
}
/**
* Unregisteres <tt>listener</tt> so that it won't receive any further
* notifications upon successful message delivery, failure or reception
* of incoming messages..
*
* @param listener the <tt>MessageListener</tt> to unregister.
*/
public void removeMessageListener(MessageListener listener)
{
messageListeners.remove(listener);
}
/**
* Looks for a RSS feed specified as contact
*
* @param rssContact the <tt>contact</tt> to send query
* @param newContact the <tt>boolean</tt> to now if it's a new feed/contact
* @param aloneUpdate the <tt>boolean</tt> to know if it's
* a query just for one feed/contact
*/
private void submitRssQuery(ContactRssImpl rssContact,
boolean newContact,
boolean aloneUpdate)
{
Message msg;
boolean newName = false;
boolean newDate = false;
boolean update = false;
Date lastQueryDate = null;
String newDisplayName = new String();
String oldDisplayName = new String();
//we instantiate a new RssFeedReader which will contain the feed retrieved
RssFeedReader rssFeed = new RssFeedReader(rssContact.getAddress());
//we parse the feed/contact
rssFeed.recupFlux();
if(rssFeed.getFeed() == null)
{
msg = createMessage("No RSS feed available at URL "+ rssContact.getAddress());
}else
{
//we recover the feed's old name
if(newContact)
oldDisplayName = rssContact.getDisplayName();
else
oldDisplayName = rssFeed.getTitle();
//we change the contact's displayName according to the feed's title
newDisplayName = rssFeed.getTitle();
if(!(newDisplayName.equals(oldDisplayName)))
{
newName = true;
}
rssContact.setDisplayName(newDisplayName);
//Looking for a date representing the last item retrieved on this feed
//we look after a date saving in the contact's parameters (i.e. in the
// file contactlist.xml)
if(rssContact.getDate() != null)
lastQueryDate = rssContact.getDate();
//we create the message containing the new items retrieved
msg = createMessage(rssFeed.getPrintedFeed(lastQueryDate));
//if a newer date is avalaible for the current feed/contact looking the
// date of each item of the feed retrieved, we update this date
if(rssFeed.getUltimateItemDate() != null)
{
if(lastQueryDate != null)
{
if(rssFeed.getUltimateItemDate().compareTo(lastQueryDate)>0)
{
rssContact.setDate(rssFeed.getUltimateItemDate());
newDate = true;
update = true;
}
}
else
{
rssContact.setDate(rssFeed.getUltimateItemDate());
newDate = true;
update = true;
}
}
else
update = true;
//if we have a new date or a new name on this feed/contact, we fire that
// the contact has his properties modified in order to save it
if(newName || newDate)
this.opSetPersPresence.fireContactPropertyChangeEvent(
ContactPropertyChangeEvent.
PROPERTY_DISPLAY_NAME, rssContact,
oldDisplayName, newDisplayName);
}
//if the feed has been updated or if the user made a request on a specific
//feed/contact, we fire a new message containing the new items to the user
if(update || aloneUpdate)
fireMessageReceived(msg, rssContact);
}
/**
* To refresh all rss feeds registered as contacts
*/
public void refreshRssFeed()
{
Vector rssContactList = new Vector();
rssContactList = opSetPersPresence.getContactListRoot().
getRssURLList(rssContactList);
Iterator rssContact = rssContactList.iterator();
while(rssContact.hasNext())
{
submitRssQuery((ContactRssImpl)rssContact.next(), false, false);
}
}
/**
* To refresh a specific rss feed specified as param
*
* @param rssURL the <tt>contact</tt> to be refreshed
* @param newContact
* @param aloneUpdate
*/
public void refreshRssFeed( ContactRssImpl rssURL,
boolean newContact,
boolean aloneUpdate)
{
submitRssQuery(rssURL, newContact, aloneUpdate);
}
/**
* Creating the timer permitting the refresh of rss feeds
*/
public void createTimer()
{
RssTimerRefreshFeed refresh = new RssTimerRefreshFeed(this);
this.timer = new Timer();
this.timer.scheduleAtFixedRate(refresh, 0, PERIOD_REFRESH_RSS);
}
/**
* Cancel the timer if the user switch to the OFFLINE status
*/
public void stopTimer(){
this.timer.cancel();
}
/**
* Retrieve the feeds for a new Rss Feed just added as persistent contact
*
* @param contact the <tt>Contact</tt> added
*/
public void newContact(ContactRssImpl contact)
{
RssThread rssThr = new RssThread(this,contact, true, true);
}
/**
* Sends the <tt>message</tt> to the destination indicated by the
* <tt>to</tt> contact.
*
* @param to the <tt>Contact</tt> to send <tt>message</tt> to
* @param message the <tt>Message</tt> to send.
* @throws IllegalStateException if the underlying ICQ stack is not
* registered and initialized.
* @throws IllegalArgumentException if <tt>to</tt> is not an instance
* belonging to the underlying implementation.
*/
public void sendInstantMessage(Contact to, Message message)
throws IllegalStateException,
IllegalArgumentException
{
if( !(to instanceof ContactRssImpl) )
throw new IllegalArgumentException(
"The specified contact is not a Rss contact."
+ to);
MessageDeliveredEvent msgDeliveredEvt
= new MessageDeliveredEvent(message, to, new Date());
//refresh the present rssFeed "to"
fireMessageDelivered(message,to);
RssThread rssThr = new RssThread(this, (ContactRssImpl)to, false, true);
}
/**
* In case the to the <tt>to</tt> Contact corresponds to another rss
* protocol provider registered with SIP Communicator, we deliver
* the message to them, in case the <tt>to</tt> Contact represents us, we
* fire a <tt>MessageReceivedEvent</tt>, and if <tt>to</tt> is simply
* a contact in our contact list, then we simply echo the message.
*
* @param message the <tt>Message</tt> the message to deliver.
* @param to the <tt>Contact</tt> that we should deliver the message to.
*/
private void deliverMessage(Message message, ContactRssImpl to)
{
String userID = to.getAddress();
//if the user id is owr own id, then this message is being routed to us
//from another instance of the rss provider.
if (userID.equals(this.parentProvider.getAccountID().getUserID()))
{
//check who is the provider sending the message
String sourceUserID
= to.getProtocolProvider().getAccountID().getUserID();
//check whether they are in our contact list
Contact from = opSetPersPresence.findContactByID(sourceUserID);
//and if not - add them there as volatile.
if(from == null)
{
from = opSetPersPresence.createVolatileContact(sourceUserID);
}
//and now fire the message received event.
fireMessageReceived(message, from);
}
else
{
//if userID is not our own, try an check whether another provider
//has that id and if yes - deliver the message to them.
ProtocolProviderServiceRssImpl rssProvider
= this.opSetPersPresence.findProviderForRssUserID(userID);
if(rssProvider != null)
{
OperationSetBasicInstantMessagingRssImpl opSetIM
= (OperationSetBasicInstantMessagingRssImpl)
rssProvider.getOperationSet(
OperationSetBasicInstantMessaging.class);
opSetIM.deliverMessage(message, to);
}
else
{
//if we got here then "to" is simply someone in our contact
//list so let's just echo the message.
fireMessageReceived(message, to);
}
}
}
/**
* Notifies all registered message listeners that a message has been
* delivered successfully to its addressee..
*
* @param message the <tt>Message</tt> that has been delivered.
* @param to the <tt>Contact</tt> that <tt>message</tt> was delivered to.
*/
private void fireMessageDelivered(Message message, Contact to)
{
MessageDeliveredEvent evt
= new MessageDeliveredEvent(message, to, new Date());
Iterator listeners = null;
synchronized (messageListeners)
{
listeners = new ArrayList(messageListeners).iterator();
}
while (listeners.hasNext())
{
MessageListener listener
= (MessageListener) listeners.next();
listener.messageDelivered(evt);
}
}
/**
* Notifies all registered message listeners that a message has been
* received.
*
* @param message the <tt>Message</tt> that has been received.
* @param from the <tt>Contact</tt> that <tt>message</tt> was received from.
*/
private void fireMessageReceived(Message message, Contact from)
{
MessageReceivedEvent evt
= new MessageReceivedEvent(message, from, new Date());
Iterator listeners = null;
synchronized (messageListeners)
{
listeners = new ArrayList(messageListeners).iterator();
}
while (listeners.hasNext())
{
MessageListener listener
= (MessageListener) listeners.next();
listener.messageReceived(evt);
}
}
/**
* Determines wheter the protocol provider (or the protocol itself) support
* sending and receiving offline messages. Most often this method would
* return true for protocols that support offline messages and false for
* those that don't. It is however possible for a protocol to support these
* messages and yet have a particular account that does not (i.e. feature
* not enabled on the protocol server). In cases like this it is possible
* for this method to return true even when offline messaging is not
* supported, and then have the sendMessage method throw an
* OperationFailedException with code - OFFLINE_MESSAGES_NOT_SUPPORTED.
*
* @return <tt>true</tt> if the protocol supports offline messages and
* <tt>false</tt> otherwise.
*/
public boolean isOfflineMessagingSupported()
{
return true;
}
public ProtocolProviderServiceRssImpl getParentProvider(){
return this.parentProvider;
}
public OperationSetPersistentPresenceRssImpl getOpSetPersPresence(){
return this.opSetPersPresence;
}
}

@ -0,0 +1,193 @@
/*
* 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.impl.protocol.rss;
import java.util.*;
import net.java.sip.communicator.service.protocol.*;
import net.java.sip.communicator.service.protocol.event.*;
import net.java.sip.communicator.util.*;
/**
* Implements typing notifications for the Rss protocol. The operation
* set would simply mirror all outgoing typing notifications and make them
* appear as incoming events generated by the contact that we are currently
* writing a message to.
*
* @author Emil Ivov
*/
public class OperationSetTypingNotificationsRssImpl
implements OperationSetTypingNotifications
{
private static final Logger logger =
Logger.getLogger(OperationSetTypingNotificationsRssImpl.class);
/**
* All currently registered TN listeners.
*/
private List typingNotificationsListeners = new ArrayList();
/**
* The provider that created us.
*/
private ProtocolProviderServiceRssImpl parentProvider = null;
/**
* The currently valid persistent presence operation set..
*/
private OperationSetPersistentPresenceRssImpl opSetPersPresence = null;
/**
* Creates a new instance of this operation set and keeps the parent
* provider as a reference.
*
* @param provider a ref to the <tt>ProtocolProviderServiceImpl</tt>
* that created us and that we'll use for retrieving the underlying aim
* connection.
* @param opSetPersPresence the currently valid
* <tt>OperationSetPersistentPresenceRssImpl</tt> instance.
*/
OperationSetTypingNotificationsRssImpl(
ProtocolProviderServiceRssImpl provider,
OperationSetPersistentPresenceRssImpl opSetPersPresence)
{
this.parentProvider = provider;
this.opSetPersPresence = opSetPersPresence;
}
/**
* Adds <tt>listener</tt> to the list of listeners registered for receiving
* <tt>TypingNotificationEvent</tt>s
*
* @param listener the <tt>TypingNotificationsListener</tt> listener that
* we'd like to add to the list of listeneres registered for receiving
* typing notificaions.
*/
public void addTypingNotificationsListener(
TypingNotificationsListener listener)
{
synchronized(typingNotificationsListeners)
{
typingNotificationsListeners.add(listener);
}
}
/**
* Removes <tt>listener</tt> from the list of listeners registered for
* receiving <tt>TypingNotificationEvent</tt>s
*
* @param listener the <tt>TypingNotificationsListener</tt> listener that
* we'd like to remove
*/
public void removeTypingNotificationsListener(
TypingNotificationsListener listener)
{
synchronized(typingNotificationsListeners)
{
typingNotificationsListeners.remove(listener);
}
}
/**
* Delivers a <tt>TypingNotificationEvent</tt> to all registered listeners.
* @param sourceContact the contact who has sent the notification.
* @param evtCode the code of the event to deliver.
*/
private void fireTypingNotificationsEvent(Contact sourceContact
,int evtCode)
{
logger.debug("Dispatching a TypingNotif. event to "
+ typingNotificationsListeners.size()+" listeners. Contact "
+ sourceContact.getAddress() + " has now a typing status of "
+ evtCode);
TypingNotificationEvent evt = new TypingNotificationEvent(
sourceContact, evtCode);
Iterator listeners = null;
synchronized (typingNotificationsListeners)
{
listeners = new ArrayList(typingNotificationsListeners).iterator();
}
while (listeners.hasNext())
{
TypingNotificationsListener listener
= (TypingNotificationsListener) listeners.next();
listener.typingNotificationReceifed(evt);
}
}
/**
* Sends a notification to <tt>notifiedContatct</tt> that we have entered
* <tt>typingState</tt>.
*
* @param notifiedContact the <tt>Contact</tt> to notify
* @param typingState the typing state that we have entered.
*
* @throws java.lang.IllegalStateException if the underlying stack is
* not registered and initialized.
* @throws java.lang.IllegalArgumentException if <tt>notifiedContact</tt> is
* not an instance belonging to the underlying implementation.
*/
public void sendTypingNotification(Contact notifiedContact, int typingState)
throws IllegalStateException, IllegalArgumentException
{
if( !(notifiedContact instanceof ContactRssImpl) )
throw new IllegalArgumentException(
"The specified contact is not a Rss contact."
+ notifiedContact);
String userID = notifiedContact.getAddress();
//if the user id is owr own id, then this message is being routed to us
//from another instance of the rss provider.
if (userID.equals(this.parentProvider.getAccountID().getUserID()))
{
//check who is the provider sending the message
String sourceUserID = notifiedContact.getProtocolProvider()
.getAccountID().getUserID();
//check whether they are in our contact list
Contact from = opSetPersPresence.findContactByID(sourceUserID);
//and if not - add them there as volatile.
if (from == null)
{
from = opSetPersPresence.createVolatileContact(sourceUserID);
}
//and now fire the message received event.
fireTypingNotificationsEvent(from, typingState);
}
else
{
//if userID is not our own, try a check whether another provider
//has that id and if yes - deliver the message to them.
ProtocolProviderServiceRssImpl rssProvider
= this.opSetPersPresence.findProviderForRssUserID(userID);
if (rssProvider != null)
{
OperationSetTypingNotificationsRssImpl opSetTN
= (OperationSetTypingNotificationsRssImpl)
rssProvider.getOperationSet(
OperationSetTypingNotifications.class);
opSetTN.sendTypingNotification(notifiedContact, typingState);
}
else
{
//if we got here then "to" is simply someone in our contact
//list so let's just echo the message.
fireTypingNotificationsEvent(notifiedContact, typingState);
}
}
}
}

@ -0,0 +1,102 @@
/*
* 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.impl.protocol.rss;
import java.awt.image.*;
import java.io.*;
import java.net.*;
import java.util.*;
import javax.imageio.*;
import javax.imageio.stream.*;
import net.java.sip.communicator.impl.gui.utils.*;
import net.java.sip.communicator.impl.gui.utils.ImageLoader.*;
import net.java.sip.communicator.service.protocol.*;
import net.java.sip.communicator.util.*;
/**
* Reperesents the Rss protocol icon. Implements the <tt>ProtocolIcon</tt>
* interface in order to provide a rss logo image in two different sizes.
*
* @author Yana Stamcheva
*/
public class ProtocolIconRssImpl
implements ProtocolIcon
{
private static Logger logger
= Logger.getLogger(ProtocolIconRssImpl.class);
/**
* A hash table containing the protocol icon in different sizes.
*/
private static Hashtable iconsTable = new Hashtable();
static
{
iconsTable.put(ProtocolIcon.ICON_SIZE_16x16,
loadIcon("resources/images/rss/rss-online.png"));
iconsTable.put(ProtocolIcon.ICON_SIZE_64x64,
loadIcon("resources/images/rss/rss64x64.png"));
}
/**
* Implements the <tt>ProtocolIcon.getSupportedSizes()</tt> method. Returns
* an iterator to a set containing the supported icon sizes.
* @return an iterator to a set containing the supported icon sizes
*/
public Iterator getSupportedSizes()
{
return iconsTable.keySet().iterator();
}
/**
* Returne TRUE if a icon with the given size is supported, FALSE-otherwise.
*/
public boolean isSizeSupported(String iconSize)
{
return iconsTable.containsKey(iconSize);
}
/**
* Returns the icon image in the given size.
* @param iconSize the icon size; one of ICON_SIZE_XXX constants
*/
public byte[] getIcon(String iconSize)
{
return (byte[])iconsTable.get(iconSize);
}
/**
* Returns the icon image used to represent the protocol connecting state.
* @return the icon image used to represent the protocol connecting state
*/
public byte[] getConnectingIcon()
{
return loadIcon("resources/images/rss/rss-online.png");
}
/**
* Loads an image from a given image path.
* @param imagePath The identifier of the image.
* @return The image for the given identifier.
*/
public static byte[] loadIcon(String imagePath)
{
InputStream is = ProtocolIconRssImpl.class
.getClassLoader().getResourceAsStream(imagePath);
byte[] icon = null;
try {
icon = new byte[is.available()];
is.read(icon);
} catch (IOException e) {
logger.error("Failed to load icon: " + imagePath, e);
}
return icon;
}
}

@ -0,0 +1,272 @@
/*
* 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.impl.protocol.rss;
import java.util.*;
import org.osgi.framework.*;
import net.java.sip.communicator.service.protocol.*;
import net.java.sip.communicator.util.*;
/**
* The Rss protocol provider factory creates instances of the Rss
* protocol provider service. One Service instance corresponds to one account.
*
* @author Emil Ivov
*/
public class ProtocolProviderFactoryRssImpl
extends ProtocolProviderFactory
{
private static final Logger logger
= Logger.getLogger(ProtocolProviderFactoryRssImpl.class);
/**
* The table that we store our accounts in.
*/
private Hashtable registeredAccounts = new Hashtable();
/**
* Creates an instance of the ProtocolProviderFactoryRssImpl.
*/
public ProtocolProviderFactoryRssImpl()
{
super();
}
/**
* Returns the ServiceReference for the protocol provider corresponding
* to the specified accountID or null if the accountID is unknown.
*
* @param accountID the accountID of the protocol provider we'd like to
* get
* @return a ServiceReference object to the protocol provider with the
* specified account id and null if the account id is unknwon to the
* provider factory.
*/
public ServiceReference getProviderForAccount(AccountID accountID)
{
ServiceRegistration registration
= (ServiceRegistration)registeredAccounts.get(accountID);
return (registration == null )
? null
: registration.getReference();
}
/**
* Returns a copy of the list containing the <tt>AccoudID</tt>s of all
* accounts currently registered in this protocol provider.
*
* @return a copy of the list containing the <tt>AccoudID</tt>s of all
* accounts currently registered in this protocol provider.
*/
public ArrayList getRegisteredAccounts()
{
return new ArrayList(registeredAccounts.keySet());
}
/**
* Loads (and hence installs) all accounts previously stored in the
* configuration service.
*/
public void loadStoredAccounts()
{
super.loadStoredAccounts( RssActivator.getBundleContext());
}
/**
* Initializaed and creates an account corresponding to the specified
* accountProperties and registers the resulting ProtocolProvider in the
* <tt>context</tt> BundleContext parameter.
*
* @param userIDStr tha/a user identifier uniquely representing the newly
* created account within the protocol namespace.
* @param accountProperties a set of protocol (or implementation)
* specific properties defining the new account.
* @return the AccountID of the newly created account.
*/
public AccountID installAccount( String userIDStr,
Map accountProperties)
{
BundleContext context
= RssActivator.getBundleContext();
if (context == null)
throw new NullPointerException("The specified BundleContext was null");
if (userIDStr == null)
throw new NullPointerException("The specified AccountID was null");
if (accountProperties == null)
throw new NullPointerException("The specified property map was null");
accountProperties.put(USER_ID, userIDStr);
AccountID accountID = new RssAccountID(userIDStr, accountProperties);
//make sure we haven't seen this account id before.
if (registeredAccounts.containsKey(accountID))
throw new IllegalStateException(
"An account for id " + userIDStr + " was already installed!");
//first store the account and only then load it as the load generates
//an osgi event, the osgi event triggers (through the UI) a call to the
//ProtocolProviderService.register() method and it needs to acces
//the configuration service and check for a stored password.
this.storeAccount(
RssActivator.getBundleContext()
, accountID);
accountID = loadAccount(accountProperties);
return accountID;
}
/**
* Initializes and creates an account corresponding to the specified
* accountProperties and registers the resulting ProtocolProvider in the
* <tt>context</tt> BundleContext parameter.
*
* @param accountProperties a set of protocol (or implementation)
* specific properties defining the new account.
* @return the AccountID of the newly loaded account
*/
public AccountID loadAccount( Map accountProperties)
{
BundleContext context
= RssActivator.getBundleContext();
if(context == null)
throw new NullPointerException("The specified BundleContext was null");
String userIDStr = (String)accountProperties.get(USER_ID);
AccountID accountID = new RssAccountID(userIDStr, accountProperties);
//get a reference to the configuration service and register whatever
//properties we have in it.
Hashtable properties = new Hashtable();
properties.put(PROTOCOL, "Rss");
properties.put(USER_ID, userIDStr);
ProtocolProviderServiceRssImpl rssProtocolProvider
= new ProtocolProviderServiceRssImpl();
rssProtocolProvider.initialize(userIDStr, accountID);
ServiceRegistration registration
= context.registerService( ProtocolProviderService.class.getName(),
rssProtocolProvider,
properties);
registeredAccounts.put(accountID, registration);
return accountID;
}
/**
* Removes the specified account from the list of accounts that this
* provider factory is handling.
*
* @param accountID the ID of the account to remove.
* @return true if an account with the specified ID existed and was
* removed and false otherwise.
*/
public boolean uninstallAccount(AccountID accountID)
{
//unregister the protocol provider
ServiceReference serRef = getProviderForAccount(accountID);
ProtocolProviderService protocolProvider
= (ProtocolProviderService) RssActivator.getBundleContext()
.getService(serRef);
try
{
protocolProvider.unregister();
}
catch (OperationFailedException exc)
{
logger.error("Failed to unregister protocol provider for account : "
+ accountID + " caused by : " + exc);
}
ServiceRegistration registration
= (ServiceRegistration)registeredAccounts.remove(accountID);
if(registration == null)
return false;
//kill the service
registration.unregister();
registeredAccounts.remove(accountID);
return removeStoredAccount(RssActivator.getBundleContext(), accountID);
}
/**
* Saves the password for the specified account after scrambling it a bit
* so that it is not visible from first sight (Method remains highly
* insecure).
*
* @param accountID the AccountID for the account whose password we're
* storing.
* @param passwd the password itself.
*
* @throws java.lang.IllegalArgumentException if no account corresponding
* to <tt>accountID</tt> has been previously stored.
*/
public void storePassword(AccountID accountID, String passwd)
throws IllegalArgumentException
{
super.storePassword(RssActivator.getBundleContext(),
accountID,
passwd);
}
/**
* Returns the password last saved for the specified account.
*
* @param accountID the AccountID for the account whose password we're
* looking for..
*
* @return a String containing the password for the specified accountID.
*
* @throws java.lang.IllegalArgumentException if no account corresponding
* to <tt>accountID</tt> has been previously stored.
*/
public String loadPassword(AccountID accountID)
throws IllegalArgumentException
{
return super.loadPassword(RssActivator.getBundleContext(), accountID );
}
/**
* Prepares the factory for bundle shutdown.
*/
public void stop()
{
Enumeration registrations = this.registeredAccounts.elements();
while(registrations.hasMoreElements())
{
ServiceRegistration reg
= ((ServiceRegistration)registrations.nextElement());
reg.unregister();
}
Enumeration idEnum = registeredAccounts.keys();
while(idEnum.hasMoreElements())
{
registeredAccounts.remove(idEnum.nextElement());
}
}
}

@ -0,0 +1,447 @@
/*
* 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.impl.protocol.rss;
import java.util.*;
import net.java.sip.communicator.service.protocol.*;
import net.java.sip.communicator.service.protocol.event.*;
import net.java.sip.communicator.util.*;
/**
* A Rss implementation of the ProtocolProviderService.
*
* @author Emil Ivov/Jean-Albert Vescovo
*/
public class ProtocolProviderServiceRssImpl
implements ProtocolProviderService
{
private static final Logger logger
= Logger.getLogger(ProtocolProviderServiceRssImpl.class);
/**
* The name of this protocol.
*/
public static final String RSS_PROTOCOL_NAME = "Rss";
/**
* The id of the account that this protocol provider represents.
*/
private AccountID accountID = null;
/**
* We use this to lock access to initialization.
*/
private Object initializationLock = new Object();
/**
* The hashtable with the operation sets that we support locally.
*/
private Hashtable supportedOperationSets = new Hashtable();
/**
* A list of listeners interested in changes in our registration state.
*/
private Vector registrationStateListeners = new Vector();
/**
* Indicates whether or not the provider is initialized and ready for use.
*/
private boolean isInitialized = false;
/**
* The logo corresponding to the rss protocol.
*/
private ProtocolIconRssImpl rssIcon
= new ProtocolIconRssImpl();
/**
* A reference to the IM operation set
*/
private OperationSetBasicInstantMessagingRssImpl basicInstantMessaging;
private boolean start = false;
/**
* The registration state that we are currently in. Note that in a real
* world protocol implementation this field won't exist and the registration
* state would be retrieved from the protocol stack.
*/
private RegistrationState currentRegistrationState
= RegistrationState.UNREGISTERED;
/**
* The default constructor for the Rss protocol provider.
*/
public ProtocolProviderServiceRssImpl()
{
logger.trace("Creating a rss provider.");
}
/**
* Initializes the service implementation, and puts it in a state where it
* could interoperate with other services. It is strongly recomended that
* properties in this Map be mapped to property names as specified by
* <tt>AccountProperties</tt>.
*
* @param userID the user id of the rss account we're currently
* initializing
* @param accountID the identifier of the account that this protocol
* provider represents.
*
* @see net.java.sip.communicator.service.protocol.AccountID
*/
protected void initialize(String userID,
AccountID accountID)
{
synchronized(initializationLock)
{
this.accountID = accountID;
//initialize the presence operationset
OperationSetPersistentPresenceRssImpl persistentPresence =
new OperationSetPersistentPresenceRssImpl(this);
supportedOperationSets.put(
OperationSetPersistentPresence.class.getName(),
persistentPresence);
//register it once again for those that simply need presence and
//won't be smart enough to check for a persistent presence
//alternative
supportedOperationSets.put( OperationSetPresence.class.getName(),
persistentPresence);
//initialize the IM operation set
//OperationSetBasicInstantMessagingRssImpl
basicInstantMessaging
= new OperationSetBasicInstantMessagingRssImpl(
this
, (OperationSetPersistentPresenceRssImpl)
persistentPresence);
supportedOperationSets.put(
OperationSetBasicInstantMessaging.class.getName(),
basicInstantMessaging);
//initialize the typing notifications operation set
OperationSetTypingNotifications typingNotifications =
new OperationSetTypingNotificationsRssImpl(
this, persistentPresence);
supportedOperationSets.put(
OperationSetTypingNotifications.class.getName(),
typingNotifications);
isInitialized = true;
}
}
/**
* Registers the specified listener with this provider so that it would
* receive notifications on changes of its state or other properties such
* as its local address and display name.
*
* @param listener the listener to register.
*/
public void addRegistrationStateChangeListener(
RegistrationStateChangeListener listener)
{
synchronized(registrationStateListeners)
{
if (!registrationStateListeners.contains(listener))
registrationStateListeners.add(listener);
}
}
/**
* Removes the specified registration listener so that it won't receive
* further notifications when our registration state changes.
*
* @param listener the listener to remove.
*/
public void removeRegistrationStateChangeListener(
RegistrationStateChangeListener listener)
{
synchronized(registrationStateListeners)
{
registrationStateListeners.remove(listener);
}
}
/**
* Creates a <tt>RegistrationStateChangeEvent</tt> corresponding to the
* specified old and new states and notifies all currently registered
* listeners.
*
* @param oldState the state that the provider had before the change
* occurred
* @param newState the state that the provider is currently in.
* @param reasonCode a value corresponding to one of the REASON_XXX fields
* of the RegistrationStateChangeEvent class, indicating the reason for
* this state transition.
* @param reason a String further explaining the reason code or null if
* no such explanation is necessary.
*/
private void fireRegistrationStateChanged( RegistrationState oldState,
RegistrationState newState,
int reasonCode,
String reason)
{
RegistrationStateChangeEvent event =
new RegistrationStateChangeEvent(
this, oldState, newState, reasonCode, reason);
logger.debug("Dispatching " + event + " to "
+ registrationStateListeners.size()+ " listeners.");
Iterator listeners = null;
synchronized (registrationStateListeners)
{
listeners = new ArrayList(registrationStateListeners).iterator();
}
while (listeners.hasNext())
{
RegistrationStateChangeListener listener
= (RegistrationStateChangeListener) listeners.next();
listener.registrationStateChanged(event);
}
/* If Timer isn't started, we launch a new timer for sending periodic
* rss feeds' refresh taks.
* If yes, we stop it.
*/
if(!start){
this.basicInstantMessaging.createTimer();
start = true;
}
else{
this.basicInstantMessaging.stopTimer();
start = false;
}
logger.trace("Done.");
}
/**
* Returns the AccountID that uniquely identifies the account represented
* by this instance of the ProtocolProviderService.
*
* @return the id of the account represented by this provider.
*/
public AccountID getAccountID()
{
return accountID;
}
/**
* Returns the operation set corresponding to the specified class or null
* if this operation set is not supported by the provider implementation.
*
* @param opsetClass the <tt>Class</tt> of the operation set that we're
* looking for.
* @return returns an OperationSet of the specified <tt>Class</tt> if
* the undelying implementation supports it or null otherwise.
*/
public OperationSet getOperationSet(Class opsetClass)
{
return (OperationSet) getSupportedOperationSets()
.get(opsetClass.getName());
}
/**
* Returns the short name of the protocol that the implementation of this
* provider is based upon (like SIP, Jabber, ICQ/AIM, or others for
* example).
*
* @return a String containing the short name of the protocol this
* service is implementing (most often that would be a name in
* ProtocolNames).
*/
public String getProtocolName()
{
return RSS_PROTOCOL_NAME;
}
/**
* Returns the state of the registration of this protocol provider with
* the corresponding registration service.
*
* @return ProviderRegistrationState
*/
public RegistrationState getRegistrationState()
{
return currentRegistrationState;
}
/**
* Returns an array containing all operation sets supported by the
* current implementation.
*
* @return a java.util.Map containing instance of all supported
* operation sets mapped against their class names (e.g.
* OperationSetPresence.class.getName()) .
*/
public Map getSupportedOperationSets()
{
//Copy the map so that the caller is not able to modify it.
return (Map)supportedOperationSets.clone();
}
/**
* Indicates whether or not this provider is registered
*
* @return true if the provider is currently registered and false
* otherwise.
*/
public boolean isRegistered()
{
return currentRegistrationState.equals(RegistrationState.REGISTERED);
}
/**
* Starts the registration process.
*
* @param authority the security authority that will be used for
* resolving any security challenges that may be returned during the
* registration or at any moment while wer're registered.
* @throws OperationFailedException with the corresponding code it the
* registration fails for some reason (e.g. a networking error or an
* implementation problem).
*/
public void register(SecurityAuthority authority)
throws OperationFailedException
{
//we don't really need a password here since there's no server in
//Rss but nevertheless we'll behave as if we did.
//verify whether a password has already been stored for this account
String password = RssActivator.
getProtocolProviderFactory().loadPassword(getAccountID());
//if we don't - retrieve it from the user through the security authority
if (password == null)
{
//create a default credentials object
UserCredentials credentials = new UserCredentials();
credentials.setUserName(getAccountID().getUserID());
//request a password from the user
credentials = authority.obtainCredentials("Rss"
, credentials);
//extract the password the user passed us.
char[] pass = credentials.getPassword();
// the user didn't provide us a password (canceled the operation)
if (pass == null)
{
fireRegistrationStateChanged(
getRegistrationState(),
RegistrationState.UNREGISTERED,
RegistrationStateChangeEvent.REASON_USER_REQUEST, "");
return;
}
password = new String(pass);
//if the user indicated that the password should be saved, we'll ask
//the proto provider factory to store it for us.
if (credentials.isPasswordPersistent())
{
RssActivator.getProtocolProviderFactory()
.storePassword(getAccountID(), password);
}
}
RegistrationState oldState = currentRegistrationState;
currentRegistrationState = RegistrationState.REGISTERED;
fireRegistrationStateChanged(
oldState
, currentRegistrationState
, RegistrationStateChangeEvent.REASON_USER_REQUEST
, null);
}
/**
* Makes the service implementation close all open sockets and release
* any resources that it might have taken and prepare for
* shutdown/garbage collection.
*/
public void shutdown()
{
if(!isInitialized)
{
return;
}
logger.trace("Killing the Rss Protocol Provider.");
if(isRegistered())
{
try
{
//do the unregistration
unregister();
}
catch (OperationFailedException ex)
{
//we're shutting down so we need to silence the exception here
logger.error(
"Failed to properly unregister before shutting down. "
+ getAccountID()
, ex);
}
}
isInitialized = false;
}
/**
* Ends the registration of this protocol provider with the current
* registration service.
*
* @throws OperationFailedException with the corresponding code it the
* registration fails for some reason (e.g. a networking error or an
* implementation problem).
*/
public void unregister()
throws OperationFailedException
{
RegistrationState oldState = currentRegistrationState;
currentRegistrationState = RegistrationState.UNREGISTERED;
fireRegistrationStateChanged(
oldState
, currentRegistrationState
, RegistrationStateChangeEvent.REASON_USER_REQUEST
, null);
}
/**
* Returns the rss protocol icon.
* @return the rss protocol icon
*/
public ProtocolIcon getProtocolIcon()
{
return rssIcon;
}
/**
* Returns the IM set
* @return the IM set
*/
public OperationSetBasicInstantMessagingRssImpl getBasicInstantMessaging()
{
return this.basicInstantMessaging;
}
}

@ -0,0 +1,32 @@
/*
* 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.impl.protocol.rss;
import net.java.sip.communicator.service.protocol.*;
import java.util.Map;
/**
* The Rss implementation of a sip-communicator account id.
* @author Emil Ivov
*/
public class RssAccountID
extends AccountID
{
/**
* Creates an account id from the specified id and account properties.
*
* @param userID the user identifier correspnding to the account
* @param accountProperties any other properties necessary for the account.
*/
RssAccountID(String userID, Map accountProperties)
{
super( userID,
accountProperties,
"Rss",
"rss.org");
}
}

@ -0,0 +1,116 @@
/*
* 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.impl.protocol.rss;
import org.osgi.framework.*;
import net.java.sip.communicator.util.*;
import java.util.*;
import net.java.sip.communicator.service.protocol.*;
import net.java.sip.communicator.impl.gui.*;
/**
* Loads the Rss provider factory and registers its services in the OSGI
* bundle context.
*
* @author Emil Ivov
*/
public class RssActivator
implements BundleActivator
{
private static final Logger logger
= Logger.getLogger(RssActivator.class);
/**
* A reference to the registration of our Rss protocol provider
* factory.
*/
private ServiceRegistration rssPpFactoryServReg = null;
/**
* A reference to the Rss protocol provider factory.
*/
private static ProtocolProviderFactoryRssImpl
rssProviderFactory = null;
/**
* The currently valid bundle context.
*/
private static BundleContext bundleContext = null;
/**
* Called when this bundle is started. In here we'll export the
* rss ProtocolProviderFactory implementation so that it could be
* possible to register accounts with it in SIP Communicator.
*
* @param context The execution context of the bundle being started.
* @throws Exception If this method throws an exception, this bundle is
* marked as stopped and the Framework will remove this bundle's
* listeners, unregister all services registered by this bundle, and
* release all services used by this bundle.
*/
public void start(BundleContext context)
throws Exception
{
this.bundleContext = context;
Hashtable hashtable = new Hashtable();
hashtable.put(ProtocolProviderFactory.PROTOCOL, "Rss");
rssProviderFactory = new ProtocolProviderFactoryRssImpl();
//load all stored Rss accounts.
rssProviderFactory.loadStoredAccounts();
//reg the rss provider factory.
rssPpFactoryServReg = context.registerService(
ProtocolProviderFactory.class.getName(),
rssProviderFactory,
hashtable);
logger.info("Rss protocol implementation [STARTED].");
}
/**
* Returns a reference to the bundle context that we were started with.
* @return a reference to the BundleContext instance that we were started
* witn.
*/
public static BundleContext getBundleContext()
{
return bundleContext;
}
/**
* Retrurns a reference to the protocol provider factory that we have
* registered.
* @return a reference to the <tt>ProtocolProviderFactoryJabberImpl</tt>
* instance that we have registered from this package.
*/
public static ProtocolProviderFactoryRssImpl getProtocolProviderFactory()
{
return rssProviderFactory;
}
/**
* Called when this bundle is stopped so the Framework can perform the
* bundle-specific activities necessary to stop the bundle.
*
* @param context The execution context of the bundle being stopped.
* @throws Exception If this method throws an exception, the bundle is
* still marked as stopped, and the Framework will remove the bundle's
* listeners, unregister all services registered by the bundle, and
* release all services used by the bundle.
*/
public void stop(BundleContext context)
throws Exception
{
this.rssProviderFactory.stop();
rssPpFactoryServReg.unregister();
logger.info("Rss protocol implementation [STOPPED].");
}
}

@ -0,0 +1,256 @@
/*
* 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.impl.protocol.rss;
import java.io.*;
import java.net.*;
import java.util.*;
import com.sun.syndication.feed.synd.*;
import com.sun.syndication.io.*;
import net.java.sip.communicator.service.protocol.*;
import net.java.sip.communicator.service.protocol.event.*;
/**
* The class used for using the Informa Library into the RSS protocol
*
* @author Jean-Albert Vescovo
*/
public class RssFeedReader
{
/**
* The id of the contact/feed, used to make a tcp query toward
* the .xml file containing the items of the feed.
*/
private String address;
/**
* The title of the feed, which will be used as the displayname
* of the contact/feed.
*/
private String title;
/**
* The object charged to retrieve the feed incoming from the relavant server.
*/
private SyndFeed feed;
/**
* The last update date of this feed.
*/
private Date ultimateItemDate = null;
/**
* An array of SyndEntry which will contain all the items retrieved from the feed.
*/
private SyndEntry[] items;
/**
* Creates an instance of a rss feed with the specified string used
* as an url to contact the relevant server.
*
* @param address the url of this feed.
*/
public RssFeedReader(String address)
{
this.address = address;
this.feed = null;
this.title = "No feed avalaible !";
}
/**
* To refresh this rss contact/feed registered as contact
* Moreover, we sort the items by reverse chronological order after
* insert them into an Array
*/
public void recupFlux()
{
try
{
URL rssURL = new URL(this.address);
//the most important thing in this protocol: we parse the rss feed
//using the Rome library
SyndFeedInput input = new SyndFeedInput();
this.feed = input.build(new XmlReader(rssURL));
this.title = this.feed.getTitle();
//we retrieve the items and sort them by reverse chronological order
items = (SyndEntry[])(this.feed.getEntries().toArray(new SyndEntry[0]));
sortItems();
//we retrieve the date of the most recent item
this.ultimateItemDate = findUltimateItemDate();
}
catch(Exception ex)
{
ex.printStackTrace();
System.out.println("ERROR: "+ex.getMessage());
}
}
/**
* Returns a String containing the message to send to the user after
* a successful query on a rss server:
*
* - if we have no items, we return "No items found on this feed !"
* - if we can't read a date in these items, we return the last 10 items of the feed
* - if we can read a date, we just return the items which have a date earlier than
* the lastQueryDate, and "No new articles in your feed since last update." if it isn't
* new item since lastQueryDate.
*
* We signal to the user ("Send anything to refresh this feed...") that he can send anything
* to refresh the present contact/feed.
*
* @param lastQueryDate the date to compare with that of the items retrieved.
* @return String string
*/
public String getPrintedFeed(Date lastQueryDate)
{
boolean more = true;
int i=0,nbNewItem = 0;
String printedFeed = new String();
if(items.length > 0)
{
while((i<items.length)&&more)
{
if((items[i].getPublishedDate() != null) && (lastQueryDate != null))
{
if(items[i].getPublishedDate().compareTo(lastQueryDate)>0)
{
printedFeed += "\nAt " + items[i].getPublishedDate()+" - " +
items[i].getTitle() +
"\nLink: " + items[i].getLink() + "\n\n";
nbNewItem++;
}
else{
more = false;
if(nbNewItem == 0) printedFeed +=
"\n\nNo new articles in your feed since last update.";
}
}
else{
if(items[i].getPublishedDate() != null)
printedFeed += "\nAt " + items[i].getPublishedDate();
printedFeed += "\n" + items[i].getTitle() +
"\nLink: "+items[i].getLink()+"\n\n";
if(i == 10) more = false;
}
i++;
}
printedFeed += ("\n\nSend anything to refresh this feed...");
}
else
{
printedFeed += "No items found on this feed !";
}
return printedFeed;
}
/**
* To sort the items retrieved from the rss contact/feed registered as contact
* We use for that a bubble sort algorithm
*/
public void sortItems()
{
int i;
int size = items.length;
SyndEntry temp;
boolean inversion;
do
{
inversion=false;
for(i = 0; i < size - 1; i++)
{
if((items[i].getPublishedDate() != null) && (items[i+1].getPublishedDate()!=null))
if(items[i].getPublishedDate().compareTo(items[i+1].getPublishedDate())<0)
{
temp = items[i];
items[i] = items[i+1];
items[i+1] = temp;
inversion=true;
}
}
size--;
}while(inversion);
}
/**
* Returns a Date that can be used to know the most recent item in a retrieved feed.
*
* @return the feed's Date representing the nearest item's date never retrieved on this feed.
*/
public Date getUltimateItemDate()
{
return this.ultimateItemDate;
}
/**
* Returns a Date that can be used to know the most recent item in a retrieved feed.
*
* This method just gives the date of the first element of the array of ItemIF previously
* sorted.
*
* @return a Date representing the nearest item's date.
*/
private Date findUltimateItemDate()
{
if(items[0].getPublishedDate() != null)
this.ultimateItemDate = items[0].getPublishedDate();
return this.ultimateItemDate;
}
/**
* Returns a ChannelIF that can be used to know if a feed exists indeed.
*
* @return a ChannelIF containing the result of a query on a rss server.
*/
public SyndFeed getFeed()
{
return this.feed;
}
/**
* Returns a Date giving the publication date of the feed on the relevant server.
*
* In most case, this date doesn't exist on the server. Not used at this time in this
* implementation.
*
* @return a Date representing the publication date of the feed.
*/
public Date getPubDate()
{
return this.feed.getPublishedDate();
}
/**
* Returns a String used as a displayname.
*
* @return a String title representing the feed/contact.
*/
public String getTitle()
{
return this.title;
}
/**
* Returns a String that can be used for identifying the contact.
*
* We'll prefer to use the title of the feed as displayname.
*
* @return a String id representing and uniquely identifying the contact.
*/
public String getAddress()
{
return this.address;
}
}

@ -0,0 +1,104 @@
/*
* 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.impl.protocol.rss;
import java.util.*;
import net.java.sip.communicator.service.protocol.*;
import net.java.sip.communicator.util.*;
import java.io.*;
/**
* An implementation of <tt>PresenceStatus</tt> that enumerates all states that
* a Rss contact can fall into.
*
* @author Jean-Albert Vescovo
*/
public class RssStatusEnum
extends PresenceStatus
{
private static final Logger logger
= Logger.getLogger(RssStatusEnum.class);
/**
* Indicates an Offline status or status with 0 connectivity.
*/
public static final RssStatusEnum OFFLINE
= new RssStatusEnum(
0
, "Offline"
, loadIcon("resources/images/rss/rss-offline.png"));
/**
* The Online status. Indicate that the user is able and willing to
* communicate.
*/
public static final RssStatusEnum ONLINE
= new RssStatusEnum(
65
, "Online"
, loadIcon("resources/images/rss/rss-online.png"));
/**
* Initialize the list of supported status states.
*/
private static List supportedStatusSet = new LinkedList();
static
{
supportedStatusSet.add(OFFLINE);
supportedStatusSet.add(ONLINE);
}
/**
* Creates an instance of <tt>RssPresneceStatus</tt> with the
* specified parameters.
* @param status the connectivity level of the new presence status instance
* @param statusName the name of the presence status.
* @param statusIcon the icon associated with this status
*/
private RssStatusEnum(int status,
String statusName,
byte[] statusIcon)
{
super(status, statusName, statusIcon);
}
/**
* Returns an iterator over all status instances supproted by the rss
* provider.
* @return an <tt>Iterator</tt> over all status instances supported by the
* rss provider.
*/
static Iterator supportedStatusSet()
{
return supportedStatusSet.iterator();
}
/**
* Loads an image from a given image path.
* @param imagePath The path to the image resource.
* @return The image extracted from the resource at the specified path.
*/
public static byte[] loadIcon(String imagePath)
{
InputStream is = RssStatusEnum.class.getClassLoader()
.getResourceAsStream(imagePath);
byte[] icon = null;
try
{
icon = new byte[is.available()];
is.read(icon);
}
catch (IOException exc)
{
logger.error("Failed to load icon: " + imagePath, exc);
}
return icon;
}
}

@ -0,0 +1,73 @@
/*
* 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.impl.protocol.rss;
import java.util.*;
import net.java.sip.communicator.service.protocol.*;
import net.java.sip.communicator.service.protocol.event.*;
/**
* Instant messaging functionalites for the Rss protocol.
*
* @author Jean-Albert Vescovo
*/
public class RssThread
extends Thread
{
private OperationSetBasicInstantMessagingRssImpl opSet;
private ContactRssImpl rssFeed = null;
private boolean newContact = false;
private boolean aloneUpdate = false;
/** Creates a new instance of RssThread
* @param opSet the OperationSetBasicInstantMessagingRssImpl instance that
* is managing the rss protocol.
*/
public RssThread(OperationSetBasicInstantMessagingRssImpl opSet)
{
this.opSet = opSet;
this.start();
}
/** Creates a new instance of RssThread
* @param opSet the OperationSetBasicInstantMessagingRssImpl instance that
* is managing the rss protocol.
* @param rssFeed the contact that the thread is going to do a query
* @param newContact newContact
* @param aloneUpdate aloneUpdate
*/
public RssThread(OperationSetBasicInstantMessagingRssImpl opSet,
ContactRssImpl rssFeed,
boolean newContact,
boolean aloneUpdate)
{
this.opSet = opSet;
this.rssFeed = rssFeed;
this.newContact = newContact;
this.aloneUpdate = aloneUpdate;
this.start();
}
/**
* The task executed by the thread
* If no rss contact given as parameter, the query is launched for all contacts
*/
public void run()
{
try
{
if(this.rssFeed == null)
this.opSet.refreshRssFeed();
else
this.opSet.refreshRssFeed(this.rssFeed,this.newContact,this.aloneUpdate);
}
catch(Exception exc)
{
exc.printStackTrace();
}
}
}

@ -0,0 +1,41 @@
/*
* 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.impl.protocol.rss;
import java.util.TimerTask;
/**
* Instant messaging functionalites for the Rss protocol.
*
* @author Jean-Albert Vescovo
*/
public class RssTimerRefreshFeed
extends TimerTask
{
private OperationSetBasicInstantMessagingRssImpl opSet;
/**
* Creates an instance of timer used to seeking periodically the rss feeds registered
* as contacts.
* @param opSet the OperationSetBasicInstantMessagingRssImpl instance that
* is managing the rss protocol.
*/
public RssTimerRefreshFeed(OperationSetBasicInstantMessagingRssImpl opSet)
{
this.opSet = opSet;
}
/**
* What the timer is supposed to do each time the PERIOD_REFRESH_RSS expire.
* In facts, it launch a new thread responsible for starting one or more rss queries
*/
public void run()
{
RssThread rssThr = new RssThread(this.opSet);
}
}

@ -0,0 +1,15 @@
Bundle-Activator: net.java.sip.communicator.impl.protocol.rss.RssActivator
Bundle-Name: Rss Protocol Provider
Bundle-Description: A bundle providing support for the Rss protocol.
Bundle-Vendor: sip-communicator.org
Bundle-Version: 0.0.1
Import-Package: org.osgi.framework,
org.xml.sax,
org.xml.sax.helpers,
org.jdom,
org.jdom.input,
net.java.sip.communicator.service.configuration,
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

@ -0,0 +1,265 @@
/*
* 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.plugin.rssaccregwizz;
import java.util.*;
import java.awt.*;
import javax.swing.*;
import javax.swing.event.*;
import net.java.sip.communicator.service.gui.*;
import net.java.sip.communicator.service.protocol.*;
/**
* The <tt>FirstWizardPage</tt> is the page, where user could enter the user ID
* and the password of the account.
*
* @author Emil Ivov/Jean-Albert Vescovo
*/
public class FirstWizardPage
extends JPanel implements WizardPage, DocumentListener
{
public static final String FIRST_PAGE_IDENTIFIER = "FirstPageIdentifier";
private JPanel userPassPanel = new JPanel(new BorderLayout(10, 10));
private JPanel labelsPanel = new JPanel();
private JLabel existingAccountLabel =
new JLabel("RSS account already exists !");
private JLabel creatingAccountLabel =
new JLabel("Press next to creat your RSS account...");
private JTextField userIDField = new JTextField();
private JPanel mainPanel = new JPanel();
private Object nextPageIdentifier = WizardPage.SUMMARY_PAGE_IDENTIFIER;
private RssAccountRegistration registration = null;
private WizardContainer wizardContainer;
/**
* Creates an instance of <tt>FirstWizardPage</tt>.
* @param registration the <tt>RssAccountRegistration</tt>, where
* all data through the wizard are stored
* @param wizardContainer the wizardContainer, where this page will
* be added
*/
public FirstWizardPage(RssAccountRegistration registration,
WizardContainer wizardContainer)
{
super(new BorderLayout());
this.wizardContainer = wizardContainer;
this.registration = registration;
this.setPreferredSize(new Dimension(300, 150));
mainPanel.setLayout(new BoxLayout(mainPanel, BoxLayout.Y_AXIS));
this.init();
this.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
this.labelsPanel.setLayout(new BoxLayout(labelsPanel, BoxLayout.Y_AXIS));
}
/**
* Initializes all panels, buttons, etc.
*/
private void init()
{
this.userIDField.getDocument().addDocumentListener(this);
this.existingAccountLabel.setForeground(Color.RED);
this.creatingAccountLabel.setForeground(Color.BLUE);
labelsPanel.add(creatingAccountLabel);
if(!isExistingAccount("rss")){
labelsPanel.remove(existingAccountLabel);
labelsPanel.add(creatingAccountLabel);
setNextButtonAccordingToUserID(true);
}
else{
labelsPanel.remove(creatingAccountLabel);
labelsPanel.add(existingAccountLabel);
setNextButtonAccordingToUserID(false);
}
userPassPanel.add(labelsPanel, BorderLayout.CENTER);
userPassPanel.setBorder(BorderFactory
.createTitledBorder("RSS account creation..."));
this.add(userPassPanel, BorderLayout.CENTER);
}
/**
* Implements the <code>WizardPage.getIdentifier</code> to return
* this page identifier.
*
* @return the Identifier of the first page in this wizard.
*/
public Object getIdentifier()
{
return FIRST_PAGE_IDENTIFIER;
}
/**
* Implements the <code>WizardPage.getNextPageIdentifier</code> to return
* the next page identifier - the summary page.
*
* @return the identifier of the page following this one.
*/
public Object getNextPageIdentifier()
{
return nextPageIdentifier;
}
/**
* Implements the <code>WizardPage.getBackPageIdentifier</code> to return
* the next back identifier - the default page.
*
* @return the identifier of the default wizard page.
*/
public Object getBackPageIdentifier()
{
return WizardPage.DEFAULT_PAGE_IDENTIFIER;
}
/**
* Implements the <code>WizardPage.getWizardForm</code> to return
* this panel.
*
* @return the component to be displayed in this wizard page.
*/
public Object getWizardForm()
{
return this;
}
/**
* Before this page is displayed enables or disables the "Next" wizard
* button according to whether the UserID field is empty.
*/
public void pageShowing()
{
if(isExistingAccount("Rss")) setNextButtonAccordingToUserID(false);
else setNextButtonAccordingToUserID(true);
}
/**
* Saves the user input when the "Next" wizard buttons is clicked.
*/
public void pageNext()
{
nextPageIdentifier = SUMMARY_PAGE_IDENTIFIER;
userPassPanel.remove(existingAccountLabel);
registration.setUserID("Rss");
registration.setPassword("rss");
}
/**
* Enables or disables the "Next" wizard button according to whether the
* User ID field is empty.
*/
private void setNextButtonAccordingToUserID(boolean newOne)
{
if(!newOne)
{
wizardContainer.setNextFinishButtonEnabled(false);
}
else
{
wizardContainer.setNextFinishButtonEnabled(true);
}
}
/**
* Handles the <tt>DocumentEvent</tt> triggered when user types in the
* User ID field. Enables or disables the "Next" wizard button according to
* whether the User ID field is empty.
*
* @param event the event containing the update.
*/
public void insertUpdate(DocumentEvent event)
{
}
/**
* Handles the <tt>DocumentEvent</tt> triggered when user deletes letters
* from the UserID field. Enables or disables the "Next" wizard button
* according to whether the UserID field is empty.
*
* @param event the event containing the update.
*/
public void removeUpdate(DocumentEvent event)
{
}
public void changedUpdate(DocumentEvent event)
{
}
public void pageHiding()
{
}
public void pageShown()
{
}
public void pageBack()
{
}
/**
* Fills the UserID and Password fields in this panel with the data comming
* from the given protocolProvider.
* @param protocolProvider The <tt>ProtocolProviderService</tt> to load the
* data from.
*/
public void loadAccount(ProtocolProviderService protocolProvider)
{
}
/**
* Verifies whether there is already an account installed with the same
* details as the one that the user has just entered.
*
* @param userID the name of the user that the account is registered for
* @return true if there is already an account for this userID and false
* otherwise.
*/
private boolean isExistingAccount(String userID)
{
ProtocolProviderFactory factory
= RssAccRegWizzActivator.getRssProtocolProviderFactory();
ArrayList registeredAccounts = factory.getRegisteredAccounts();
for (int i = 0; i < registeredAccounts.size(); i++)
{
AccountID accountID = (AccountID) registeredAccounts.get(i);
if (userID.equalsIgnoreCase(accountID.getUserID()))
{
return true;
}
}
return false;
}
}

@ -0,0 +1,95 @@
/*
* 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.plugin.rssaccregwizz;
import java.io.*;
import java.util.*;
import net.java.sip.communicator.util.*;
/**
* The Messages class manages the access to the internationalization
* properties files.
*
* @author Emil Ivov
*/
public class Resources
{
private static Logger log = Logger.getLogger(Resources.class);
private static final String BUNDLE_NAME
= "net.java.sip.communicator.plugin.rssaccregwizz.resources";
private static final ResourceBundle RESOURCE_BUNDLE = ResourceBundle
.getBundle(BUNDLE_NAME);
public static ImageID GIBBERISH_LOGO = new ImageID("protocolIcon");
public static ImageID PAGE_IMAGE = new ImageID("pageImage");
/**
* Returns an internationalized string corresponding to the given key.
* @param key The key of the string.
* @return An internationalized string corresponding to the given key.
*/
public static String getString(String key)
{
try
{
return RESOURCE_BUNDLE.getString(key);
}
catch (MissingResourceException exc)
{
return '!' + key + '!';
}
}
/**
* Loads an image from a given image identifier.
* @param imageID The identifier of the image.
* @return The image for the given identifier.
*/
public static byte[] getImage(ImageID imageID)
{
byte[] image = new byte[100000];
String path = Resources.getString(imageID.getId());
try
{
Resources.class.getClassLoader()
.getResourceAsStream(path).read(image);
}
catch (IOException exc)
{
log.error("Failed to load image:" + path, exc);
}
return image;
}
/**
* Represents the Image Identifier.
*/
public static class ImageID
{
private String id;
private ImageID(String id)
{
this.id = id;
}
public String getId()
{
return id;
}
}
}

@ -0,0 +1,109 @@
/*
* 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.plugin.rssaccregwizz;
import org.osgi.framework.*;
import net.java.sip.communicator.service.configuration.*;
import net.java.sip.communicator.service.gui.*;
import net.java.sip.communicator.service.protocol.*;
import net.java.sip.communicator.util.*;
/**
* Registers the <tt>RssAccountRegistrationWizard</tt> in the UI Service.
*
* @author Emil Ivov
*/
public class RssAccRegWizzActivator
implements BundleActivator
{
private static Logger logger = Logger.getLogger(
RssAccRegWizzActivator.class.getName());
/**
* A currently valid bundle context.
*/
public static BundleContext bundleContext;
/**
* A currently valid reference to the configuration service.
*/
private static ConfigurationService configService;
/**
* Starts this bundle.
* @param bc the currently valid <tt>BundleContext</tt>.
*/
public void start(BundleContext bc)
{
logger.info("Loading rss account wizard.");
bundleContext = bc;
ServiceReference uiServiceRef = bundleContext
.getServiceReference(UIService.class.getName());
UIService uiService
= (UIService) bundleContext.getService(uiServiceRef);
AccountRegistrationWizardContainer wizardContainer
= uiService.getAccountRegWizardContainer();
RssAccountRegistrationWizard rssWizard
= new RssAccountRegistrationWizard(wizardContainer);
wizardContainer.addAccountRegistrationWizard(rssWizard);
logger.info("Rss account registration wizard [STARTED].");
}
/**
* Called when this bundle is stopped so the Framework can perform the
* bundle-specific activities necessary to stop the bundle.
*
* @param context The execution context of the bundle being stopped.
*/
public void stop(BundleContext context)
{
}
/**
* Returns the <tt>ProtocolProviderFactory</tt> for the Rss protocol.
* @return the <tt>ProtocolProviderFactory</tt> for the Rss protocol
*/
public static ProtocolProviderFactory getRssProtocolProviderFactory()
{
ServiceReference[] serRefs = null;
String osgiFilter = "("
+ ProtocolProviderFactory.PROTOCOL
+ "=" + "Rss" + ")";
try
{
serRefs = bundleContext.getServiceReferences(
ProtocolProviderFactory.class.getName(), osgiFilter);
}
catch (InvalidSyntaxException ex)
{
logger.error(ex);
}
return (ProtocolProviderFactory) bundleContext.getService(serRefs[0]);
}
/**
* Returns the bundleContext that we received when we were started.
*
* @return a currently valid instance of a bundleContext.
*/
public BundleContext getBundleContext()
{
return bundleContext;
}
}

@ -0,0 +1,82 @@
/*
* SIP Communicator, the OpenSource Java VoIP and Instant Messaging client.
*
* Distributable under LGPL license.
* See terms of license at gnu.org.
*/
/**
* The <tt>RssAccountRegistration</tt> is used to store all user input data
* through the <tt>RssAccountRegistrationWizard</tt>.
*
* @author Emil Ivov/Jean-Albert Vescovo
*/
package net.java.sip.communicator.plugin.rssaccregwizz;
public class RssAccountRegistration
{
private String userID;
private String password;
private boolean rememberPassword;
/**
* Returns the User ID of the rss registration account.
* @return the User ID of the rss registration account.
*/
public String getUserID()
{
return userID;
}
/**
* Sets the user ID of the rss registration account.
* @param userID the userID of the rss registration account.
*/
public void setUserID(String userID)
{
this.userID = userID;
}
/**
* Returns the password of the Rss registration account.
*
* @return the password of the Rss registration account.
*/
public String getPassword()
{
return password;
}
/**
* Sets the password of the Rss registration account.
*
* @param password the password of the Rss registration account.
*/
public void setPassword(String password)
{
this.password = password;
}
/**
* Returns <tt>true</tt> if password has to remembered, <tt>false</tt>
* otherwise.
*
* @return <tt>true</tt> if password has to remembered, <tt>false</tt>
* otherwise.
*/
public boolean isRememberPassword()
{
return true;
}
/**
* Sets the rememberPassword value of this Rss account registration.
*
* @param rememberPassword <tt>true</tt> if password has to remembered,
* <tt>false</tt> otherwise.
*/
public void setRememberPassword(boolean rememberPassword)
{
this.rememberPassword = true;
}
}

@ -0,0 +1,198 @@
/*
* 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.plugin.rssaccregwizz;
import java.util.*;
import org.osgi.framework.*;
import net.java.sip.communicator.impl.gui.customcontrols.*;
import net.java.sip.communicator.service.gui.*;
import net.java.sip.communicator.service.protocol.*;
/**
* The <tt>RssAccountRegistrationWizard</tt> is an implementation of the
* <tt>AccountRegistrationWizard</tt> for the Rss protocol. It allows
* the user to create and configure a new Rss account.
*
* @author Emil Ivov
*/
public class RssAccountRegistrationWizard
implements AccountRegistrationWizard
{
/**
* The first page of the rss account registration wizard.
*/
private FirstWizardPage firstWizardPage;
/**
* The object that we use to store details on an account that we will be
* creating.
*/
private RssAccountRegistration registration
= new RssAccountRegistration();
private WizardContainer wizardContainer;
private ProtocolProviderService protocolProvider;
private String propertiesPackage
= "net.java.sip.communicator.plugin.rssaccregwizz";
private boolean isModification;
/**
* Creates an instance of <tt>RssAccountRegistrationWizard</tt>.
* @param wizardContainer the wizard container, where this wizard
* is added
*/
public RssAccountRegistrationWizard(WizardContainer wizardContainer)
{
this.wizardContainer = wizardContainer;
}
/**
* Implements the <code>AccountRegistrationWizard.getIcon</code> method.
* Returns the icon to be used for this wizard.
* @return byte[]
*/
public byte[] getIcon()
{
return Resources.getImage(Resources.GIBBERISH_LOGO);
}
/**
* Implements the <code>AccountRegistrationWizard.getPageImage</code> method.
* Returns the image used to decorate the wizard page
*
* @return byte[] the image used to decorate the wizard page
*/
public byte[] getPageImage()
{
return Resources.getImage(Resources.PAGE_IMAGE);
}
/**
* Implements the <code>AccountRegistrationWizard.getProtocolName</code>
* method. Returns the protocol name for this wizard.
* @return String
*/
public String getProtocolName()
{
return Resources.getString("protocolName");
}
/**
* Implements the <code>AccountRegistrationWizard.getProtocolDescription
* </code> method. Returns the description of the protocol for this wizard.
* @return String
*/
public String getProtocolDescription()
{
return Resources.getString("protocolDescription");
}
/**
* Returns the set of pages contained in this wizard.
* @return Iterator
*/
public Iterator getPages()
{
ArrayList pages = new ArrayList();
firstWizardPage = new FirstWizardPage(registration, wizardContainer);
pages.add(firstWizardPage);
return pages.iterator();
}
/**
* Returns the set of data that user has entered through this wizard.
* @return Iterator
*/
public Iterator getSummary()
{
Hashtable summaryTable = new Hashtable();
summaryTable.put("User ID", registration.getUserID());
return summaryTable.entrySet().iterator();
}
/**
* Installs the account created through this wizard.
* @return ProtocolProviderService
*/
public ProtocolProviderService finish()
{
firstWizardPage = null;
ProtocolProviderFactory factory
= RssAccRegWizzActivator.getRssProtocolProviderFactory();
return this.installAccount(factory,
registration.getUserID());
}
/**
* Creates an account for the given user and password.
* @param providerFactory the ProtocolProviderFactory which will create
* the account
* @param user the user identifier
* @return the <tt>ProtocolProviderService</tt> for the new account.
*/
public ProtocolProviderService installAccount(
ProtocolProviderFactory providerFactory,
String user)
{
Hashtable accountProperties = new Hashtable();
if (registration.isRememberPassword())
{
accountProperties.put(ProtocolProviderFactory.PASSWORD
, registration.getPassword());
}
try
{
AccountID accountID = providerFactory.installAccount(
user, accountProperties);
ServiceReference serRef = providerFactory
.getProviderForAccount(accountID);
protocolProvider = (ProtocolProviderService)
RssAccRegWizzActivator.bundleContext
.getService(serRef);
}
catch (IllegalArgumentException exc)
{
new ErrorDialog(null, exc.getMessage(), exc).showDialog();
}
catch (IllegalStateException exc)
{
new ErrorDialog(null, exc.getMessage(), exc).showDialog();
}
return protocolProvider;
}
/**
* Fills the UserID and Password fields in this panel with the data comming
* from the given protocolProvider.
* @param protocolProvider The <tt>ProtocolProviderService</tt> to load the
* data from.
*/
public void loadAccount(ProtocolProviderService protocolProvider)
{
this.protocolProvider = protocolProvider;
isModification = true;
}
}

@ -0,0 +1,10 @@
protocolName=Rss
protocolDescription=Add your preferred RSS feeds into SIP Communicator !
userID=User ID:
password=Password:
rememberPassword=Remember password
userAndPassword=Identification
existingAccount=* The account you entered is already installed.
protocolIcon=resources/images/rss/rss-online.png
pageImage=resources/images/rss/rss64x64.png

@ -0,0 +1,30 @@
Bundle-Activator: net.java.sip.communicator.plugin.rssaccregwizz.RssAccRegWizzActivator
Bundle-Name: Rss account registration wizard
Bundle-Description: Rss account registration wizard.
Bundle-Vendor: sip-communicator.org
Bundle-Version: 0.0.1
Import-Package: org.osgi.framework,
net.java.sip.communicator.util,
net.java.sip.communicator.service.configuration,
net.java.sip.communicator.service.configuration.event,
net.java.sip.communicator.service.protocol,
net.java.sip.communicator.service.protocol.event,
net.java.sip.communicator.service.contactlist,
net.java.sip.communicator.service.contactlist.event,
net.java.sip.communicator.service.gui,
net.java.sip.communicator.service.gui.event,
net.java.sip.communicator.service.browserlauncher,
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.filechooser,
javax.swing.tree,
javax.swing.undo,
javax.swing.border
Loading…
Cancel
Save