/** * $RCSfile$ * $Revision$ * $Date$ * * Copyright (C) 2004 Jive Software. All rights reserved. * * This software is published under the terms of the GNU Public License (GPL), * a copy of which is included in this distribution. */ package org.jivesoftware.messenger.user.spi; import org.jivesoftware.util.LocaleUtils; import org.jivesoftware.util.Log; import org.jivesoftware.util.XPPReader; import org.jivesoftware.messenger.XMPPAddress; import org.jivesoftware.messenger.XMPPDOMFragment; import org.jivesoftware.messenger.XMPPFragment; import org.jivesoftware.messenger.auth.UnauthorizedException; import org.jivesoftware.messenger.spi.IQImpl; import org.jivesoftware.messenger.user.*; import java.util.Iterator; import java.util.List; import javax.xml.stream.XMLStreamConstants; import javax.xml.stream.XMLStreamException; import javax.xml.stream.XMLStreamReader; import javax.xml.stream.XMLStreamWriter; import org.dom4j.Document; import org.dom4j.DocumentException; import org.dom4j.Element; /** * A roster implemented against a JDBC database * * @author Iain Shigeoka */ public class IQRosterImpl extends IQImpl implements IQRoster { private BasicIQRoster basicRoster = new BasicIQRoster(); /** * <p>Create an empty iq roster packet.</p> */ public IQRosterImpl() { } public String getChildNamespace() { return "jabber:iq:roster"; } public String getChildName() { return "query"; } public void send(XMLStreamWriter xmlSerializer, int version) throws XMLStreamException { try { super.sendRoot(xmlSerializer, version, "iq", null); xmlSerializer.setPrefix("", "jabber:iq:roster"); xmlSerializer.writeStartElement("query"); xmlSerializer.writeDefaultNamespace("jabber:iq:roster"); Iterator items = basicRoster.getRosterItems(); while (items.hasNext()) { Object item = items.next(); if (item instanceof IQRosterItem) { ((IQRosterItem)item).send(xmlSerializer, version); } else { new IQRosterItemImpl((RosterItem)item).send(xmlSerializer, version); } } xmlSerializer.writeEndElement(); xmlSerializer.writeEndElement(); } catch (UnauthorizedException e) { Log.error(LocaleUtils.getLocalizedString("admin.error"), e); } } public void parse(Document doc) { Element root = doc.getRootElement(); setRecipient(XMPPAddress.parseJID(root.attributeValue("to"))); setType(typeFromString(root.attributeValue("type"))); setID(root.attributeValue("id")); Iterator elements = root.elements().iterator(); while (elements.hasNext()) { Element element = (Element)elements.next(); if ("query".equals(element.getName())) { Iterator items = element.elementIterator("item"); while (items.hasNext()) { try { Element item = (Element)items.next(); RosterItem rosterItem = basicRoster.createRosterItem(XMPPAddress.parseJID(item.attributeValue("jid")), item.attributeValue("name"), null); rosterItem.setSubStatus("remove".equals(item.attributeValue("subscription")) ? RosterItem.SUB_REMOVE : RosterItem.SUB_NONE); Iterator groupElements = item.elementIterator("group"); while (groupElements.hasNext()) { rosterItem.getGroups().add(((Element)groupElements.next()).getTextTrim()); } } catch (UnauthorizedException e) { Log.error(LocaleUtils.getLocalizedString("admin.error"), e); } catch (UserAlreadyExistsException e) { Log.error(LocaleUtils.getLocalizedString("admin.error"), e); } } } } } public void parse(XMLStreamReader xpp) throws XMLStreamException { // We're one past the root iq-element int event = xpp.getEventType(); Document doc = null; // The one query element or the error element if (event == XMLStreamConstants.START_ELEMENT) { if ("query".equals(xpp.getLocalName())) { } else { // error, we'll punt and implement later throw new XMLStreamException("Error packets not supported yet"); } try { doc = XPPReader.parseDocument(xpp); setChildNamespace(doc.getRootElement().getNamespaceURI()); setChildName(doc.getRootElement().getName()); XMPPFragment fragment = new XMPPDOMFragment(doc.getRootElement()); addFragment(fragment); setChildFragment(fragment); } catch (DocumentException e) { throw new XMLStreamException(); } } while (event != XMLStreamConstants.END_ELEMENT) { event = xpp.next(); } } // ################################################################################## // Basic Roster usage - the downside of single inheritance // ################################################################################## private class BasicIQRoster extends BasicRoster { protected RosterItem provideRosterItem(RosterItem item) throws UserAlreadyExistsException, UnauthorizedException { return new IQRosterItemImpl(item); } protected RosterItem provideRosterItem(XMPPAddress user, String nickname, List groups) throws UserAlreadyExistsException, UnauthorizedException { return new IQRosterItemImpl(user, nickname, groups); } } public boolean isRosterItem(XMPPAddress user) { return basicRoster.isRosterItem(user); } public Iterator getRosterItems() throws UnauthorizedException { return basicRoster.getRosterItems(); } public int getTotalRosterItemCount() throws UnauthorizedException { return basicRoster.getTotalRosterItemCount(); } public RosterItem getRosterItem(XMPPAddress user) throws UnauthorizedException, UserNotFoundException { return basicRoster.getRosterItem(user); } public RosterItem createRosterItem(XMPPAddress user) throws UnauthorizedException, UserAlreadyExistsException { return basicRoster.createRosterItem(user); } public RosterItem createRosterItem(XMPPAddress user, String nickname, List groups) throws UnauthorizedException, UserAlreadyExistsException { return basicRoster.createRosterItem(user, nickname, groups); } public RosterItem createRosterItem(RosterItem item) throws UnauthorizedException, UserAlreadyExistsException { return basicRoster.createRosterItem(item); } public void updateRosterItem(RosterItem item) throws UnauthorizedException, UserNotFoundException { basicRoster.updateRosterItem(item); } public RosterItem deleteRosterItem(XMPPAddress user) throws UnauthorizedException { return basicRoster.deleteRosterItem(user); } }