diff --git a/source/org/jivesoftware/smack/Roster.java b/source/org/jivesoftware/smack/Roster.java index e34490b1e..c7424a9ec 100644 --- a/source/org/jivesoftware/smack/Roster.java +++ b/source/org/jivesoftware/smack/Roster.java @@ -36,16 +36,16 @@ import java.util.concurrent.CopyOnWriteArrayList; /** * Represents a user's roster, which is the collection of users a person receives * presence updates for. Roster items are categorized into groups for easier management.

- * + *

* Others users may attempt to subscribe to this user using a subscription request. Three * modes are supported for handling these requests:

* - * @see XMPPConnection#getRoster() * @author Matt Tucker + * @see XMPPConnection#getRoster() */ public class Roster { @@ -99,7 +99,7 @@ public class Roster { */ Roster(final XMPPConnection connection) { this.connection = connection; - groups = new ConcurrentHashMap(); + groups = new ConcurrentHashMap(); unfiledEntries = new CopyOnWriteArrayList(); entries = new CopyOnWriteArrayList(); rosterListeners = new CopyOnWriteArrayList(); @@ -141,7 +141,7 @@ public class Roster { * Returns the subscription processing mode, which dictates what action * Smack will take when subscription requests from other users are made. * The default subscription mode is {@link SubscriptionMode#accept_all}.

- * + *

* If using the manual mode, a PacketListener should be registered that * listens for Presence packets that have a type of * {@link org.jivesoftware.smack.packet.Presence.Type#subscribe}. @@ -156,7 +156,7 @@ public class Roster { * Sets the subscription processing mode, which dictates what action * Smack will take when subscription requests from other users are made. * The default subscription mode is {@link SubscriptionMode#accept_all}.

- * + *

* If using the manual mode, a PacketListener should be registered that * listens for Presence packets that have a type of * {@link org.jivesoftware.smack.packet.Presence.Type#subscribe}. @@ -184,7 +184,7 @@ public class Roster { */ public void addRosterListener(RosterListener rosterListener) { if (!rosterListeners.contains(rosterListener)) { - rosterListeners.add(rosterListener); + rosterListeners.add(rosterListener); } } @@ -200,7 +200,7 @@ public class Roster { /** * Creates a new group.

- * + *

* Note: you must add at least one entry to the group for the group to be kept * after a logout/login. This is due to the way that XMPP stores group information. * @@ -220,13 +220,13 @@ public class Roster { * Creates a new roster entry and presence subscription. The server will asynchronously * update the roster with the subscription status. * - * @param user the user. (e.g. johndoe@jabber.org) - * @param name the nickname of the user. + * @param user the user. (e.g. johndoe@jabber.org) + * @param name the nickname of the user. * @param groups the list of group names the entry will belong to, or null if the - * the roster entry won't belong to a group. + * the roster entry won't belong to a group. * @throws XMPPException if an XMPP exception occurs. */ - public void createEntry(String user, String name, String [] groups) throws XMPPException { + public void createEntry(String user, String name, String[] groups) throws XMPPException { // Create and send roster entry creation packet. RosterPacket rosterPacket = new RosterPacket(); rosterPacket.setType(IQ.Type.SET); @@ -243,7 +243,7 @@ public class Roster { PacketCollector collector = connection.createPacketCollector( new PacketIDFilter(rosterPacket.getPacketID())); connection.sendPacket(rosterPacket); - IQ response = (IQ)collector.nextResult(SmackConfiguration.getPacketReplyTimeout()); + IQ response = (IQ) collector.nextResult(SmackConfiguration.getPacketReplyTimeout()); collector.cancel(); if (response == null) { throw new XMPPException("No response from the server."); @@ -281,9 +281,9 @@ public class Roster { item.setItemType(RosterPacket.ItemType.remove); packet.addRosterItem(item); PacketCollector collector = connection.createPacketCollector( - new PacketIDFilter(packet.getPacketID())); + new PacketIDFilter(packet.getPacketID())); connection.sendPacket(packet); - IQ response = (IQ)collector.nextResult(SmackConfiguration.getPacketReplyTimeout()); + IQ response = (IQ) collector.nextResult(SmackConfiguration.getPacketReplyTimeout()); collector.cancel(); if (response == null) { throw new XMPPException("No response from the server."); @@ -349,7 +349,7 @@ public class Roster { * null if the user is not an entry in the roster. * * @param user the XMPP address of the user (eg "jsmith@example.com"). The address could be - * in any valid format (e.g. "domain/resource", "user@domain" or "user@domain/resource"). + * in any valid format (e.g. "domain/resource", "user@domain" or "user@domain/resource"). * @return the roster entry or null if it does not exist. */ public RosterEntry getEntry(String user) { @@ -369,8 +369,8 @@ public class Roster { * Returns true if the specified XMPP address is an entry in the roster. * * @param user the XMPP address of the user (eg "jsmith@example.com"). The - * address could be in any valid format (e.g. "domain/resource", - * "user@domain" or "user@domain/resource"). + * address could be in any valid format (e.g. "domain/resource", + * "user@domain" or "user@domain/resource"). * @return true if the XMPP address is an entry in the roster. */ public boolean contains(String user) { @@ -385,7 +385,7 @@ public class Roster { * @return the roster group with the specified name. */ public RosterGroup getGroup(String name) { - return groups.get(name); + return groups.get(name); } /** @@ -410,14 +410,14 @@ public class Roster { * Returns the presence info for a particular user. If the user is offline, or * if no presence data is available (such as when you are not subscribed to the * user's presence updates), unavailable presence will be returned.

- * + *

* If the user has several presences (one for each resource), then the presence with * highest priority will be returned. If multiple presences have the same priority, * the one with the "most available" presence mode will be returned. In order, * that's {@link Presence.Mode#chat free to chat}, {@link Presence.Mode#available available}, * {@link Presence.Mode#away away}, {@link Presence.Mode#xa extended away}, and * {@link Presence.Mode#dnd do not disturb}.

- * + *

* Note that presence information is received asynchronously. So, just after logging * in to the server, presence values for users in the roster may be unavailable * even if they are actually online. In other words, the value returned by this @@ -427,16 +427,18 @@ public class Roster { * {@link RosterListener}. * * @param user an XMPP ID. The address could be in any valid format (e.g. - * "domain/resource", "user@domain" or "user@domain/resource"). Any resource - * information that's part of the ID will be discarded. + * "domain/resource", "user@domain" or "user@domain/resource"). Any resource + * information that's part of the ID will be discarded. * @return the user's current presence, or unavailable presence if the user is offline - * or if no presence information is available.. + * or if no presence information is available.. */ public Presence getPresence(String user) { String key = getPresenceMapKey(StringUtils.parseBareAddress(user)); Map userPresences = presenceMap.get(key); if (userPresences == null) { - return new Presence(Presence.Type.unavailable); + Presence presence = new Presence(Presence.Type.unavailable); + presence.setFrom(user); + return presence; } else { // Find the resource with the highest priority @@ -467,7 +469,9 @@ public class Roster { } } if (presence == null) { - return new Presence(Presence.Type.unavailable); + presence = new Presence(Presence.Type.unavailable); + presence.setFrom(user); + return presence; } else { return presence; @@ -482,19 +486,23 @@ public class Roster { * * @param userWithResource a fully qualified XMPP ID including a resource (user@domain/resource). * @return the user's current presence, or unavailable presence if the user is offline - * or if no presence information is available. + * or if no presence information is available. */ public Presence getPresenceResource(String userWithResource) { String key = getPresenceMapKey(userWithResource); String resource = StringUtils.parseResource(userWithResource); Map userPresences = presenceMap.get(key); if (userPresences == null) { - return new Presence(Presence.Type.unavailable); + Presence presence = new Presence(Presence.Type.unavailable); + presence.setFrom(userWithResource); + return presence; } else { Presence presence = userPresences.get(resource); if (presence == null) { - return new Presence(Presence.Type.unavailable); + presence = new Presence(Presence.Type.unavailable); + presence.setFrom(userWithResource); + return presence; } else { return presence; @@ -510,14 +518,16 @@ public class Roster { * * @param user a XMPP ID, e.g. jdoe@example.com. * @return an iterator (of Presence objects) for all the user's current presences, - * or an unavailable presence if the user is offline or if no presence information - * is available. + * or an unavailable presence if the user is offline or if no presence information + * is available. */ public Iterator getPresences(String user) { String key = getPresenceMapKey(user); Map userPresences = presenceMap.get(key); if (userPresences == null) { - return Arrays.asList(new Presence(Presence.Type.unavailable)).iterator(); + Presence presence = new Presence(Presence.Type.unavailable); + presence.setFrom(user); + return Arrays.asList(presence).iterator(); } else { return userPresences.values().iterator(); @@ -541,7 +551,7 @@ public class Roster { * since it will always contain one entry for the user. * * @param user the bare or fully qualified XMPP ID, e.g. jdoe@example.com or - * jdoe@example.com/Work. + * jdoe@example.com/Work. * @return the key to use in the presenceMap for the fully qualified XMPP ID. */ private String getPresenceMapKey(String user) { @@ -579,13 +589,12 @@ public class Roster { * specified collections of contacts have been added, updated or deleted * from the roster. * - * @param addedEntries the collection of address of the added contacts. + * @param addedEntries the collection of address of the added contacts. * @param updatedEntries the collection of address of the updated contacts. * @param deletedEntries the collection of address of the deleted contacts. */ private void fireRosterChangedEvent(Collection addedEntries, Collection updatedEntries, - Collection deletedEntries) - { + Collection deletedEntries) { for (RosterListener listener : rosterListeners) { if (!addedEntries.isEmpty()) { listener.entriesAdded(addedEntries); @@ -602,7 +611,7 @@ public class Roster { /** * Fires roster presence changed event to roster listeners. * - * @param presence the presence change. + * @param presence the presence change. */ private void fireRosterPresenceEvent(Presence presence) { for (RosterListener listener : rosterListeners) { @@ -619,7 +628,7 @@ public class Roster { * Automatically accept all subscription and unsubscription requests. This is * the default mode and is suitable for simple client. More complex client will * likely wish to handle subscription requests manually. - */ + */ accept_all, /** @@ -640,8 +649,9 @@ public class Roster { * Listens for all presence packets and processes them. */ private class PresencePacketListener implements PacketListener { + public void processPacket(Packet packet) { - Presence presence = (Presence)packet; + Presence presence = (Presence) packet; String from = presence.getFrom(); String key = getPresenceMapKey(from); diff --git a/source/org/jivesoftware/smackx/provider/VCardProvider.java b/source/org/jivesoftware/smackx/provider/VCardProvider.java index 2d6456a84..4602a7581 100644 --- a/source/org/jivesoftware/smackx/provider/VCardProvider.java +++ b/source/org/jivesoftware/smackx/provider/VCardProvider.java @@ -39,62 +39,69 @@ import java.util.List; * vCard provider. * * @author Gaston Dombiak + * @author Derek DeMoro */ public class VCardProvider implements IQProvider { - private final static String PREFERRED_ENCODING = "UTF-8"; + private static final String PREFERRED_ENCODING = "UTF-8"; - public IQ parseIQ(XmlPullParser parser) throws Exception { - StringBuilder sb = new StringBuilder(); - try { - int event = parser.getEventType(); - // get the content - while (true) { - switch (event) { - case XmlPullParser.TEXT: - // We must re-escape the xml so that the DOM won't throw an exception - sb.append(StringUtils.escapeForXML(parser.getText())); - break; - case XmlPullParser.START_TAG: - sb.append('<').append(parser.getName()).append('>'); - break; - case XmlPullParser.END_TAG: - sb.append("'); - break; - default: - } + public IQ parseIQ(XmlPullParser parser) throws Exception { + final StringBuilder sb = new StringBuilder(); + try { + int event = parser.getEventType(); + // get the content + while (true) { + switch (event) { + case XmlPullParser.TEXT: + // We must re-escape the xml so that the DOM won't throw an exception + sb.append(StringUtils.escapeForXML(parser.getText())); + break; + case XmlPullParser.START_TAG: + sb.append('<').append(parser.getName()).append('>'); + break; + case XmlPullParser.END_TAG: + sb.append("'); + break; + default: + } - if (event == XmlPullParser.END_TAG && "vCard".equals(parser.getName())) break; + if (event == XmlPullParser.END_TAG && "vCard".equals(parser.getName())) break; - event = parser.next(); - } - } catch (XmlPullParserException e) { - e.printStackTrace(); - } catch (IOException e) { - e.printStackTrace(); - } + event = parser.next(); + } + } + catch (XmlPullParserException e) { + e.printStackTrace(); + } + catch (IOException e) { + e.printStackTrace(); + } - String xmlText = sb.toString(); - return _createVCardFromXml(xmlText); - } + String xmlText = sb.toString(); + return createVCardFromXML(xmlText); + } - public static VCard _createVCardFromXml(String xmlText) { - VCard vCard = new VCard(); - try { - DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance(); - DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder(); - Document document = documentBuilder.parse( - new ByteArrayInputStream(xmlText.getBytes(PREFERRED_ENCODING))); + /** + * Builds a users vCard from xml file. + * + * @param xml the xml representing a users vCard. + * @return the VCard. + * @throws + */ + public static VCard createVCardFromXML(String xml) throws Exception { + VCard vCard = new VCard(); - new VCardReader(vCard, document).initializeFields(); + DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance(); + DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder(); + Document document = documentBuilder.parse( + new ByteArrayInputStream(xml.getBytes(PREFERRED_ENCODING))); - } catch (Exception e) { - e.printStackTrace(System.err); - } - return vCard; - } + new VCardReader(vCard, document).initializeFields(); + return vCard; + } private static class VCardReader { + private final VCard vCard; private final Document document; @@ -158,8 +165,8 @@ public class VCardProvider implements IQProvider { } if (code == null || value == null) continue; if ("HOME".equals(type)) { - vCard.setPhoneHome(code, value); - } + vCard.setPhoneHome(code, value); + } else { // By default, setup work phone vCard.setPhoneWork(code, value); } @@ -180,18 +187,18 @@ public class VCardProvider implements IQProvider { List code = new ArrayList(); List value = new ArrayList(); NodeList childNodes = addressNode.getChildNodes(); - for(int j = 0; j < childNodes.getLength(); j++) { + for (int j = 0; j < childNodes.getLength(); j++) { Node node = childNodes.item(j); if (node.getNodeType() != Node.ELEMENT_NODE) continue; String nodeName = node.getNodeName(); if (isWorkHome(nodeName)) { type = nodeName; - } - else { + } + else { code.add(nodeName); value.add(getTextContent(node)); - } - } + } + } for (int j = 0; j < value.size(); j++) { if ("HOME".equals(type)) { vCard.setAddressFieldHome((String) code.get(j), (String) value.get(j)); @@ -221,7 +228,8 @@ public class VCardProvider implements IQProvider { String field = element.getNodeName(); if (element.getChildNodes().getLength() == 0) { vCard.setField(field, ""); - } else if (element.getChildNodes().getLength() == 1 && + } + else if (element.getChildNodes().getLength() == 1 && element.getChildNodes().item(0) instanceof Text) { vCard.setField(field, getTextContent(element)); } diff --git a/test/org/jivesoftware/smackx/VCardTest.java b/test/org/jivesoftware/smackx/VCardTest.java index 0a5f27824..d3d011abe 100644 --- a/test/org/jivesoftware/smackx/VCardTest.java +++ b/test/org/jivesoftware/smackx/VCardTest.java @@ -62,23 +62,23 @@ public class VCardTest extends SmackTestCase { } public void testNoWorkHomeSpecifier_EMAIL() throws Throwable { - VCard card = VCardProvider._createVCardFromXml("foo@fee.www.bar"); + VCard card = VCardProvider.createVCardFromXML("foo@fee.www.bar"); assertEquals("foo@fee.www.bar", card.getEmailHome()); } public void testNoWorkHomeSpecifier_TEL() throws Throwable { - VCard card = VCardProvider._createVCardFromXml("3443233"); + VCard card = VCardProvider.createVCardFromXML("3443233"); assertEquals("3443233", card.getPhoneWork("FAX")); } public void testNoWorkHomeSpecifier_ADDR() throws Throwable { - VCard card = VCardProvider._createVCardFromXml("Some streetddss"); + VCard card = VCardProvider.createVCardFromXML("Some streetddss"); assertEquals("Some street", card.getAddressFieldWork("STREET")); assertEquals("ddss", card.getAddressFieldWork("FF")); } public void testFN() throws Throwable { - VCard card = VCardProvider._createVCardFromXml("kir max"); + VCard card = VCardProvider.createVCardFromXML("kir max"); assertEquals("kir max", card.getField("FN")); // assertEquals("kir max", card.getFullName()); }