1
0
Fork 0
mirror of https://codeberg.org/Mercury-IM/Smack synced 2025-12-10 15:11:08 +01:00

smack_1_5_1

git-svn-id: http://svn.igniterealtime.org/svn/repos/smack/trunk@2639 b35dd754-fafc-0310-a699-88a17e54d16e
This commit is contained in:
Gaston Dombiak 2005-08-12 21:09:32 +00:00 committed by gato
parent aa32e12164
commit 7ae75258be
276 changed files with 40430 additions and 0 deletions

View file

@ -0,0 +1,296 @@
/**
* $RCSfile$
* $Revision$
* $Date$
*
* Copyright 2003-2004 Jive Software.
*
* All rights reserved. Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jivesoftware.smackx.packet;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import org.jivesoftware.smack.packet.PacketExtension;
import org.jivesoftware.smackx.FormField;
/**
* Represents a form that could be use for gathering data as well as for reporting data
* returned from a search.
*
* @author Gaston Dombiak
*/
public class DataForm implements PacketExtension {
private String type;
private String title;
private List instructions = new ArrayList();
private ReportedData reportedData;
private List items = new ArrayList();
private List fields = new ArrayList();
public DataForm(String type) {
this.type = type;
}
/**
* Returns the meaning of the data within the context. The data could be part of a form
* to fill out, a form submission or data results.<p>
*
* Possible form types are:
* <ul>
* <li>form -> This packet contains a form to fill out. Display it to the user (if your
* program can).</li>
* <li>submit -> The form is filled out, and this is the data that is being returned from
* the form.</li>
* <li>cancel -> The form was cancelled. Tell the asker that piece of information.</li>
* <li>result -> Data results being returned from a search, or some other query.</li>
* </ul>
*
* @return the form's type.
*/
public String getType() {
return type;
}
/**
* Returns the description of the data. It is similar to the title on a web page or an X
* window. You can put a <title/> on either a form to fill out, or a set of data results.
*
* @return description of the data.
*/
public String getTitle() {
return title;
}
/**
* Returns an Iterator for the list of instructions that explain how to fill out the form and
* what the form is about. The dataform could include multiple instructions since each
* instruction could not contain newlines characters. Join the instructions together in order
* to show them to the user.
*
* @return an Iterator for the list of instructions that explain how to fill out the form.
*/
public Iterator getInstructions() {
synchronized (instructions) {
return Collections.unmodifiableList(new ArrayList(instructions)).iterator();
}
}
/**
* Returns the fields that will be returned from a search.
*
* @return fields that will be returned from a search.
*/
public ReportedData getReportedData() {
return reportedData;
}
/**
* Returns an Iterator for the items returned from a search.
*
* @return an Iterator for the items returned from a search.
*/
public Iterator getItems() {
synchronized (items) {
return Collections.unmodifiableList(new ArrayList(items)).iterator();
}
}
/**
* Returns an Iterator for the fields that are part of the form.
*
* @return an Iterator for the fields that are part of the form.
*/
public Iterator getFields() {
synchronized (fields) {
return Collections.unmodifiableList(new ArrayList(fields)).iterator();
}
}
public String getElementName() {
return "x";
}
public String getNamespace() {
return "jabber:x:data";
}
/**
* Sets the description of the data. It is similar to the title on a web page or an X window.
* You can put a <title/> on either a form to fill out, or a set of data results.
*
* @param title description of the data.
*/
public void setTitle(String title) {
this.title = title;
}
/**
* Sets the list of instructions that explain how to fill out the form and what the form is
* about. The dataform could include multiple instructions since each instruction could not
* contain newlines characters.
*
* @param instructions list of instructions that explain how to fill out the form.
*/
public void setInstructions(List instructions) {
this.instructions = instructions;
}
/**
* Sets the fields that will be returned from a search.
*
* @param reportedData the fields that will be returned from a search.
*/
public void setReportedData(ReportedData reportedData) {
this.reportedData = reportedData;
}
/**
* Adds a new field as part of the form.
*
* @param field the field to add to the form.
*/
public void addField(FormField field) {
synchronized (fields) {
fields.add(field);
}
}
/**
* Adds a new instruction to the list of instructions that explain how to fill out the form
* and what the form is about. The dataform could include multiple instructions since each
* instruction could not contain newlines characters.
*
* @param instruction the new instruction that explain how to fill out the form.
*/
public void addInstruction(String instruction) {
synchronized (instructions) {
instructions.add(instruction);
}
}
/**
* Adds a new item returned from a search.
*
* @param item the item returned from a search.
*/
public void addItem(Item item) {
synchronized (items) {
items.add(item);
}
}
public String toXML() {
StringBuffer buf = new StringBuffer();
buf.append("<").append(getElementName()).append(" xmlns=\"").append(getNamespace()).append(
"\" type=\"" + getType() +"\">");
if (getTitle() != null) {
buf.append("<title>").append(getTitle()).append("</title>");
}
for (Iterator it=getInstructions(); it.hasNext();) {
buf.append("<instructions>").append(it.next()).append("</instructions>");
}
// Append the list of fields returned from a search
if (getReportedData() != null) {
buf.append(getReportedData().toXML());
}
// Loop through all the items returned from a search and append them to the string buffer
for (Iterator i = getItems(); i.hasNext();) {
Item item = (Item) i.next();
buf.append(item.toXML());
}
// Loop through all the form fields and append them to the string buffer
for (Iterator i = getFields(); i.hasNext();) {
FormField field = (FormField) i.next();
buf.append(field.toXML());
}
buf.append("</").append(getElementName()).append(">");
return buf.toString();
}
/**
*
* Represents the fields that will be returned from a search. This information is useful when
* you try to use the jabber:iq:search namespace to return dynamic form information.
*
* @author Gaston Dombiak
*/
public static class ReportedData {
private List fields = new ArrayList();
public ReportedData(List fields) {
this.fields = fields;
}
/**
* Returns the fields returned from a search.
*
* @return the fields returned from a search.
*/
public Iterator getFields() {
return Collections.unmodifiableList(new ArrayList(fields)).iterator();
}
public String toXML() {
StringBuffer buf = new StringBuffer();
buf.append("<reported>");
// Loop through all the form items and append them to the string buffer
for (Iterator i = getFields(); i.hasNext();) {
FormField field = (FormField) i.next();
buf.append(field.toXML());
}
buf.append("</reported>");
return buf.toString();
}
}
/**
*
* Represents items of reported data.
*
* @author Gaston Dombiak
*/
public static class Item {
private List fields = new ArrayList();
public Item(List fields) {
this.fields = fields;
}
/**
* Returns the fields that define the data that goes with the item.
*
* @return the fields that define the data that goes with the item.
*/
public Iterator getFields() {
return Collections.unmodifiableList(new ArrayList(fields)).iterator();
}
public String toXML() {
StringBuffer buf = new StringBuffer();
buf.append("<item>");
// Loop through all the form items and append them to the string buffer
for (Iterator i = getFields(); i.hasNext();) {
FormField field = (FormField) i.next();
buf.append(field.toXML());
}
buf.append("</item>");
return buf.toString();
}
}
}

View file

@ -0,0 +1,137 @@
/**
* $RCSfile$
* $Revision$
* $Date$
*
* Copyright 2003-2004 Jive Software.
*
* All rights reserved. Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jivesoftware.smackx.packet;
import java.util.Map;
import java.util.Iterator;
import java.util.Collections;
import java.util.HashMap;
/**
* Default implementation of the PrivateData interface. Unless a PrivateDataProvider
* is registered with the PrivateDataManager class, instances of this class will be
* returned when getting private data.<p>
*
* This class provides a very simple representation of an XML sub-document. Each element
* is a key in a Map with its CDATA being the value. For example, given the following
* XML sub-document:
*
* <pre>
* &lt;foo xmlns="http://bar.com"&gt;
* &lt;color&gt;blue&lt;/color&gt;
* &lt;food&gt;pizza&lt;/food&gt;
* &lt;/foo&gt;</pre>
*
* In this case, getValue("color") would return "blue", and getValue("food") would
* return "pizza". This parsing mechanism mechanism is very simplistic and will not work
* as desired in all cases (for example, if some of the elements have attributes. In those
* cases, a custom {@link org.jivesoftware.smackx.provider.PrivateDataProvider} should be used.
*
* @author Matt Tucker
*/
public class DefaultPrivateData implements PrivateData {
private String elementName;
private String namespace;
private Map map;
/**
* Creates a new generic private data object.
*
* @param elementName the name of the element of the XML sub-document.
* @param namespace the namespace of the element.
*/
public DefaultPrivateData(String elementName, String namespace) {
this.elementName = elementName;
this.namespace = namespace;
}
/**
* Returns the XML element name of the private data sub-packet root element.
*
* @return the XML element name of the packet extension.
*/
public String getElementName() {
return elementName;
}
/**
* Returns the XML namespace of the private data sub-packet root element.
*
* @return the XML namespace of the packet extension.
*/
public String getNamespace() {
return namespace;
}
public String toXML() {
StringBuffer buf = new StringBuffer();
buf.append("<").append(elementName).append(" xmlns=\"").append(namespace).append("\">");
for (Iterator i=getNames(); i.hasNext(); ) {
String name = (String)i.next();
String value = getValue(name);
buf.append("<").append(name).append(">");
buf.append(value);
buf.append("</").append(name).append(">");
}
buf.append("</").append(elementName).append(">");
return buf.toString();
}
/**
* Returns an Iterator for the names that can be used to get
* values of the private data.
*
* @return an Iterator for the names.
*/
public synchronized Iterator getNames() {
if (map == null) {
return Collections.EMPTY_LIST.iterator();
}
return Collections.unmodifiableMap(new HashMap(map)).keySet().iterator();
}
/**
* Returns a value given a name.
*
* @param name the name.
* @return the value.
*/
public synchronized String getValue(String name) {
if (map == null) {
return null;
}
return (String)map.get(name);
}
/**
* Sets a value given the name.
*
* @param name the name.
* @param value the value.
*/
public synchronized void setValue(String name, String value) {
if (map == null) {
map = new HashMap();
}
map.put(name, value);
}
}

View file

@ -0,0 +1,142 @@
/**
* $RCSfile$
* $Revision$
* $Date$
*
* Copyright 2003-2004 Jive Software.
*
* All rights reserved. Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jivesoftware.smackx.packet;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.TimeZone;
import org.jivesoftware.smack.packet.PacketExtension;
/**
* Represents timestamp information about data stored for later delivery. A DelayInformation will
* always includes the timestamp when the packet was originally sent and may include more
* information such as the JID of the entity that originally sent the packet as well as the reason
* for the dealy.<p>
*
* For more information see <a href="http://www.jabber.org/jeps/jep-0091.html">JEP-91</a>.
*
* @author Gaston Dombiak
*/
public class DelayInformation implements PacketExtension {
public static SimpleDateFormat UTC_FORMAT = new SimpleDateFormat("yyyyMMdd'T'HH:mm:ss");
/**
* New date format based on JEP-82 that some clients may use when sending delayed dates.
* JEP-91 is using a SHOULD other servers or clients may be using this format instead of the
* old UTC format.
*/
public static SimpleDateFormat NEW_UTC_FORMAT =
new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
static {
UTC_FORMAT.setTimeZone(TimeZone.getTimeZone("GMT+0"));
NEW_UTC_FORMAT.setTimeZone(TimeZone.getTimeZone("UTC"));
}
private Date stamp;
private String from;
private String reason;
/**
* Creates a new instance with the specified timestamp.
*/
public DelayInformation(Date stamp) {
super();
this.stamp = stamp;
}
/**
* Returns the JID of the entity that originally sent the packet or that delayed the
* delivery of the packet or <tt>null</tt> if this information is not available.
*
* @return the JID of the entity that originally sent the packet or that delayed the
* delivery of the packet.
*/
public String getFrom() {
return from;
}
/**
* Sets the JID of the entity that originally sent the packet or that delayed the
* delivery of the packet or <tt>null</tt> if this information is not available.
*
* @param from the JID of the entity that originally sent the packet.
*/
public void setFrom(String from) {
this.from = from;
}
/**
* Returns the timstamp when the packet was originally sent. The returned Date is
* be understood as UTC.
*
* @return the timstamp when the packet was originally sent.
*/
public Date getStamp() {
return stamp;
}
/**
* Returns a natural-language description of the reason for the delay or <tt>null</tt> if
* this information is not available.
*
* @return a natural-language description of the reason for the delay or <tt>null</tt>.
*/
public String getReason() {
return reason;
}
/**
* Sets a natural-language description of the reason for the delay or <tt>null</tt> if
* this information is not available.
*
* @param reason a natural-language description of the reason for the delay or <tt>null</tt>.
*/
public void setReason(String reason) {
this.reason = reason;
}
public String getElementName() {
return "x";
}
public String getNamespace() {
return "jabber:x:delay";
}
public String toXML() {
StringBuffer buf = new StringBuffer();
buf.append("<").append(getElementName()).append(" xmlns=\"").append(getNamespace()).append(
"\"");
buf.append(" stamp=\"").append(UTC_FORMAT.format(stamp)).append("\"");
if (from != null && from.length() > 0) {
buf.append(" from=\"").append(from).append("\"");
}
buf.append(">");
if (reason != null && reason.length() > 0) {
buf.append(reason);
}
buf.append("</").append(getElementName()).append(">");
return buf.toString();
}
}

View file

@ -0,0 +1,268 @@
/**
* $RCSfile$
* $Revision$
* $Date$
*
* Copyright 2003-2004 Jive Software.
*
* All rights reserved. Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jivesoftware.smackx.packet;
import java.util.*;
import org.jivesoftware.smack.packet.IQ;
/**
* A DiscoverInfo IQ packet, which is used by XMPP clients to request and receive information
* to/from other XMPP entities.<p>
*
* The received information may contain one or more identities of the requested XMPP entity, and
* a list of supported features by the requested XMPP entity.
*
* @author Gaston Dombiak
*/
public class DiscoverInfo extends IQ {
private List features = new ArrayList();
private List identities = new ArrayList();
private String node;
/**
* Adds a new feature to the discovered information.
*
* @param feature the discovered feature
*/
public void addFeature(String feature) {
addFeature(new DiscoverInfo.Feature(feature));
}
private void addFeature(Feature feature) {
synchronized (features) {
features.add(feature);
}
}
/**
* Returns the discovered features of an XMPP entity.
*
* @return an Iterator on the discovered features of an XMPP entity
*/
Iterator getFeatures() {
synchronized (features) {
return Collections.unmodifiableList(new ArrayList(features)).iterator();
}
}
/**
* Adds a new identity of the requested entity to the discovered information.
*
* @param identity the discovered entity's identity
*/
public void addIdentity(Identity identity) {
synchronized (identities) {
identities.add(identity);
}
}
/**
* Returns the discovered identities of an XMPP entity.
*
* @return an Iterator on the discoveted identities
*/
public Iterator getIdentities() {
synchronized (identities) {
return Collections.unmodifiableList(new ArrayList(identities)).iterator();
}
}
/**
* Returns the node attribute that supplements the 'jid' attribute. A node is merely
* something that is associated with a JID and for which the JID can provide information.<p>
*
* Node attributes SHOULD be used only when trying to provide or query information which
* is not directly addressable.
*
* @return the node attribute that supplements the 'jid' attribute
*/
public String getNode() {
return node;
}
/**
* Sets the node attribute that supplements the 'jid' attribute. A node is merely
* something that is associated with a JID and for which the JID can provide information.<p>
*
* Node attributes SHOULD be used only when trying to provide or query information which
* is not directly addressable.
*
* @param node the node attribute that supplements the 'jid' attribute
*/
public void setNode(String node) {
this.node = node;
}
/**
* Returns true if the specified feature is part of the discovered information.
*
* @param feature the feature to check
* @return true if the requestes feature has been discovered
*/
public boolean containsFeature(String feature) {
for (Iterator it = getFeatures(); it.hasNext();) {
if (feature.equals(((DiscoverInfo.Feature) it.next()).getVar()))
return true;
}
return false;
}
public String getChildElementXML() {
StringBuffer buf = new StringBuffer();
buf.append("<query xmlns=\"http://jabber.org/protocol/disco#info\"");
if (getNode() != null) {
buf.append(" node=\"");
buf.append(getNode());
buf.append("\"");
}
buf.append(">");
synchronized (identities) {
for (int i = 0; i < identities.size(); i++) {
Identity identity = (Identity) identities.get(i);
buf.append(identity.toXML());
}
}
synchronized (features) {
for (int i = 0; i < features.size(); i++) {
Feature feature = (Feature) features.get(i);
buf.append(feature.toXML());
}
}
// Add packet extensions, if any are defined.
buf.append(getExtensionsXML());
buf.append("</query>");
return buf.toString();
}
/**
* Represents the identity of a given XMPP entity. An entity may have many identities but all
* the identities SHOULD have the same name.<p>
*
* Refer to <a href="http://www.jabber.org/registrar/disco-categories.html">Jabber::Registrar</a>
* in order to get the official registry of values for the <i>category</i> and <i>type</i>
* attributes.
*
*/
public static class Identity {
private String category;
private String name;
private String type;
/**
* Creates a new identity for an XMPP entity.
*
* @param category the entity's category.
* @param name the entity's name.
*/
public Identity(String category, String name) {
this.category = category;
this.name = name;
}
/**
* Returns the entity's category. To get the official registry of values for the
* 'category' attribute refer to <a href="http://www.jabber.org/registrar/disco-categories.html">Jabber::Registrar</a>
*
* @return the entity's category.
*/
public String getCategory() {
return category;
}
/**
* Returns the identity's name.
*
* @return the identity's name.
*/
public String getName() {
return name;
}
/**
* Returns the entity's type. To get the official registry of values for the
* 'type' attribute refer to <a href="http://www.jabber.org/registrar/disco-categories.html">Jabber::Registrar</a>
*
* @return the entity's type.
*/
public String getType() {
return type;
}
/**
* Sets the entity's type. To get the official registry of values for the
* 'type' attribute refer to <a href="http://www.jabber.org/registrar/disco-categories.html">Jabber::Registrar</a>
*
* @param type the identity's type.
*/
public void setType(String type) {
this.type = type;
}
public String toXML() {
StringBuffer buf = new StringBuffer();
buf.append("<identity category=\"").append(category).append("\"");
buf.append(" name=\"").append(name).append("\"");
if (type != null) {
buf.append(" type=\"").append(type).append("\"");
}
buf.append("/>");
return buf.toString();
}
}
/**
* Represents the features offered by the item. This information helps requestors determine
* what actions are possible with regard to this item (registration, search, join, etc.)
* as well as specific feature types of interest, if any (e.g., for the purpose of feature
* negotiation).
*/
public static class Feature {
private String variable;
/**
* Creates a new feature offered by an XMPP entity or item.
*
* @param variable the feature's variable.
*/
public Feature(String variable) {
this.variable = variable;
}
/**
* Returns the feature's variable.
*
* @return the feature's variable.
*/
public String getVar() {
return variable;
}
public String toXML() {
StringBuffer buf = new StringBuffer();
buf.append("<feature var=\"").append(variable).append("\"/>");
return buf.toString();
}
}
}

View file

@ -0,0 +1,235 @@
/**
* $RCSfile$
* $Revision$
* $Date$
*
* Copyright 2003-2004 Jive Software.
*
* All rights reserved. Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jivesoftware.smackx.packet;
import java.util.*;
import org.jivesoftware.smack.packet.IQ;
/**
* A DiscoverItems IQ packet, which is used by XMPP clients to request and receive items
* associated with XMPP entities.<p>
*
* The items could also be queried in order to discover if they contain items inside. Some items
* may be addressable by its JID and others may require to be addressed by a JID and a node name.
*
* @author Gaston Dombiak
*/
public class DiscoverItems extends IQ {
private List items = new ArrayList();
private String node;
/**
* Adds a new item to the discovered information.
*
* @param item the discovered entity's item
*/
public void addItem(Item item) {
synchronized (items) {
items.add(item);
}
}
/**
* Returns the discovered items of the queried XMPP entity.
*
* @return an Iterator on the discovered entity's items
*/
public Iterator getItems() {
synchronized (items) {
return Collections.unmodifiableList(new ArrayList(items)).iterator();
}
}
/**
* Returns the node attribute that supplements the 'jid' attribute. A node is merely
* something that is associated with a JID and for which the JID can provide information.<p>
*
* Node attributes SHOULD be used only when trying to provide or query information which
* is not directly addressable.
*
* @return the node attribute that supplements the 'jid' attribute
*/
public String getNode() {
return node;
}
/**
* Sets the node attribute that supplements the 'jid' attribute. A node is merely
* something that is associated with a JID and for which the JID can provide information.<p>
*
* Node attributes SHOULD be used only when trying to provide or query information which
* is not directly addressable.
*
* @param node the node attribute that supplements the 'jid' attribute
*/
public void setNode(String node) {
this.node = node;
}
public String getChildElementXML() {
StringBuffer buf = new StringBuffer();
buf.append("<query xmlns=\"http://jabber.org/protocol/disco#items\"");
if (getNode() != null) {
buf.append(" node=\"");
buf.append(getNode());
buf.append("\"");
}
buf.append(">");
synchronized (items) {
for (int i = 0; i < items.size(); i++) {
Item item = (Item) items.get(i);
buf.append(item.toXML());
}
}
buf.append("</query>");
return buf.toString();
}
/**
* An item is associated with an XMPP Entity, usually thought of a children of the parent
* entity and normally are addressable as a JID.<p>
*
* An item associated with an entity may not be addressable as a JID. In order to handle
* such items, Service Discovery uses an optional 'node' attribute that supplements the
* 'jid' attribute.
*/
public static class Item {
/**
* Request to create or update the item.
*/
public static final String UPDATE_ACTION = "update";
/**
* Request to remove the item.
*/
public static final String REMOVE_ACTION = "remove";
private String entityID;
private String name;
private String node;
private String action;
/**
* Create a new Item associated with a given entity.
*
* @param entityID the id of the entity that contains the item
*/
public Item(String entityID) {
this.entityID = entityID;
}
/**
* Returns the entity's ID.
*
* @return the entity's ID.
*/
public String getEntityID() {
return entityID;
}
/**
* Returns the entity's name.
*
* @return the entity's name.
*/
public String getName() {
return name;
}
/**
* Sets the entity's name.
*
* @param name the entity's name.
*/
public void setName(String name) {
this.name = name;
}
/**
* Returns the node attribute that supplements the 'jid' attribute. A node is merely
* something that is associated with a JID and for which the JID can provide information.<p>
*
* Node attributes SHOULD be used only when trying to provide or query information which
* is not directly addressable.
*
* @return the node attribute that supplements the 'jid' attribute
*/
public String getNode() {
return node;
}
/**
* Sets the node attribute that supplements the 'jid' attribute. A node is merely
* something that is associated with a JID and for which the JID can provide information.<p>
*
* Node attributes SHOULD be used only when trying to provide or query information which
* is not directly addressable.
*
* @param node the node attribute that supplements the 'jid' attribute
*/
public void setNode(String node) {
this.node = node;
}
/**
* Returns the action that specifies the action being taken for this item. Possible action
* values are: "update" and "remove". Update should either create a new entry if the node
* and jid combination does not already exist, or simply update an existing entry. If
* "remove" is used as the action, the item should be removed from persistent storage.
*
* @return the action being taken for this item
*/
public String getAction() {
return action;
}
/**
* Sets the action that specifies the action being taken for this item. Possible action
* values are: "update" and "remove". Update should either create a new entry if the node
* and jid combination does not already exist, or simply update an existing entry. If
* "remove" is used as the action, the item should be removed from persistent storage.
*
* @param action the action being taken for this item
*/
public void setAction(String action) {
this.action = action;
}
public String toXML() {
StringBuffer buf = new StringBuffer();
buf.append("<item jid=\"").append(entityID).append("\"");
if (name != null) {
buf.append(" name=\"").append(name).append("\"");
}
if (node != null) {
buf.append(" node=\"").append(node).append("\"");
}
if (action != null) {
buf.append(" action=\"").append(action).append("\"");
}
buf.append("/>");
return buf.toString();
}
}
}

View file

@ -0,0 +1,234 @@
/**
* $RCSfile$
* $Revision$
* $Date$
*
* Copyright 2003-2004 Jive Software.
*
* All rights reserved. Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jivesoftware.smackx.packet;
import java.util.*;
import org.jivesoftware.smack.packet.IQ;
/**
* IQ packet that serves for kicking users, granting and revoking voice, banning users,
* modifying the ban list, granting and revoking membership and granting and revoking
* moderator privileges. All these operations are scoped by the
* 'http://jabber.org/protocol/muc#admin' namespace.
*
* @author Gaston Dombiak
*/
public class MUCAdmin extends IQ {
private List items = new ArrayList();
/**
* Returns an Iterator for item childs that holds information about roles, affiliation,
* jids and nicks.
*
* @return an Iterator for item childs that holds information about roles, affiliation,
* jids and nicks.
*/
public Iterator getItems() {
synchronized (items) {
return Collections.unmodifiableList(new ArrayList(items)).iterator();
}
}
/**
* Adds an item child that holds information about roles, affiliation, jids and nicks.
*
* @param item the item child that holds information about roles, affiliation, jids and nicks.
*/
public void addItem(Item item) {
synchronized (items) {
items.add(item);
}
}
public String getChildElementXML() {
StringBuffer buf = new StringBuffer();
buf.append("<query xmlns=\"http://jabber.org/protocol/muc#admin\">");
synchronized (items) {
for (int i = 0; i < items.size(); i++) {
Item item = (Item) items.get(i);
buf.append(item.toXML());
}
}
// Add packet extensions, if any are defined.
buf.append(getExtensionsXML());
buf.append("</query>");
return buf.toString();
}
/**
* Item child that holds information about roles, affiliation, jids and nicks.
*
* @author Gaston Dombiak
*/
public static class Item {
private String actor;
private String reason;
private String affiliation;
private String jid;
private String nick;
private String role;
/**
* Creates a new item child.
*
* @param affiliation the actor's affiliation to the room
* @param role the privilege level of an occupant within a room.
*/
public Item(String affiliation, String role) {
this.affiliation = affiliation;
this.role = role;
}
/**
* Returns the actor (JID of an occupant in the room) that was kicked or banned.
*
* @return the JID of an occupant in the room that was kicked or banned.
*/
public String getActor() {
return actor;
}
/**
* Returns the reason for the item child. The reason is optional and could be used to
* explain the reason why a user (occupant) was kicked or banned.
*
* @return the reason for the item child.
*/
public String getReason() {
return reason;
}
/**
* Returns the occupant's affiliation to the room. The affiliation is a semi-permanent
* association or connection with a room. The possible affiliations are "owner", "admin",
* "member", and "outcast" (naturally it is also possible to have no affiliation). An
* affiliation lasts across a user's visits to a room.
*
* @return the actor's affiliation to the room
*/
public String getAffiliation() {
return affiliation;
}
/**
* Returns the <room@service/nick> by which an occupant is identified within the context
* of a room. If the room is non-anonymous, the JID will be included in the item.
*
* @return the room JID by which an occupant is identified within the room.
*/
public String getJid() {
return jid;
}
/**
* Returns the new nickname of an occupant that is changing his/her nickname. The new
* nickname is sent as part of the unavailable presence.
*
* @return the new nickname of an occupant that is changing his/her nickname.
*/
public String getNick() {
return nick;
}
/**
* Returns the temporary position or privilege level of an occupant within a room. The
* possible roles are "moderator", "participant", and "visitor" (it is also possible to
* have no defined role). A role lasts only for the duration of an occupant's visit to
* a room.
*
* @return the privilege level of an occupant within a room.
*/
public String getRole() {
return role;
}
/**
* Sets the actor (JID of an occupant in the room) that was kicked or banned.
*
* @param actor the actor (JID of an occupant in the room) that was kicked or banned.
*/
public void setActor(String actor) {
this.actor = actor;
}
/**
* Sets the reason for the item child. The reason is optional and could be used to
* explain the reason why a user (occupant) was kicked or banned.
*
* @param reason the reason why a user (occupant) was kicked or banned.
*/
public void setReason(String reason) {
this.reason = reason;
}
/**
* Sets the <room@service/nick> by which an occupant is identified within the context
* of a room. If the room is non-anonymous, the JID will be included in the item.
*
* @param jid the JID by which an occupant is identified within a room.
*/
public void setJid(String jid) {
this.jid = jid;
}
/**
* Sets the new nickname of an occupant that is changing his/her nickname. The new
* nickname is sent as part of the unavailable presence.
*
* @param nick the new nickname of an occupant that is changing his/her nickname.
*/
public void setNick(String nick) {
this.nick = nick;
}
public String toXML() {
StringBuffer buf = new StringBuffer();
buf.append("<item");
if (getAffiliation() != null) {
buf.append(" affiliation=\"").append(getAffiliation()).append("\"");
}
if (getJid() != null) {
buf.append(" jid=\"").append(getJid()).append("\"");
}
if (getNick() != null) {
buf.append(" nick=\"").append(getNick()).append("\"");
}
if (getRole() != null) {
buf.append(" role=\"").append(getRole()).append("\"");
}
if (getReason() == null && getActor() == null) {
buf.append("/>");
}
else {
buf.append(">");
if (getReason() != null) {
buf.append("<reason>").append(getReason()).append("</reason>");
}
if (getActor() != null) {
buf.append("<actor jid=\"").append(getActor()).append("\"/>");
}
buf.append("</item>");
}
return buf.toString();
}
};
}

View file

@ -0,0 +1,223 @@
/**
* $RCSfile$
* $Revision$
* $Date$
*
* Copyright 2003-2004 Jive Software.
*
* All rights reserved. Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jivesoftware.smackx.packet;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.TimeZone;
import org.jivesoftware.smack.packet.PacketExtension;
/**
* Represents extended presence information whose sole purpose is to signal the ability of
* the occupant to speak the MUC protocol when joining a room. If the room requires a password
* then the MUCInitialPresence should include one.<p>
*
* The amount of discussion history provided on entering a room (perhaps because the
* user is on a low-bandwidth connection or is using a small-footprint client) could be managed by
* setting a configured History instance to the MUCInitialPresence instance.
* @see MUCInitialPresence#setHistory(MUCInitialPresence.History).
*
* @author Gaston Dombiak
*/
public class MUCInitialPresence implements PacketExtension {
private String password;
private History history;
public String getElementName() {
return "x";
}
public String getNamespace() {
return "http://jabber.org/protocol/muc";
}
public String toXML() {
StringBuffer buf = new StringBuffer();
buf.append("<").append(getElementName()).append(" xmlns=\"").append(getNamespace()).append(
"\">");
if (getPassword() != null) {
buf.append("<password>").append(getPassword()).append("</password>");
}
if (getHistory() != null) {
buf.append(getHistory().toXML());
}
buf.append("</").append(getElementName()).append(">");
return buf.toString();
}
/**
* Returns the history that manages the amount of discussion history provided on
* entering a room.
*
* @return the history that manages the amount of discussion history provided on
* entering a room.
*/
public History getHistory() {
return history;
}
/**
* Returns the password to use when the room requires a password.
*
* @return the password to use when the room requires a password.
*/
public String getPassword() {
return password;
}
/**
* Sets the History that manages the amount of discussion history provided on
* entering a room.
*
* @param history that manages the amount of discussion history provided on
* entering a room.
*/
public void setHistory(History history) {
this.history = history;
}
/**
* Sets the password to use when the room requires a password.
*
* @param password the password to use when the room requires a password.
*/
public void setPassword(String password) {
this.password = password;
}
/**
* The History class controls the number of characters or messages to receive
* when entering a room.
*
* @author Gaston Dombiak
*/
public static class History {
private int maxChars = -1;
private int maxStanzas = -1;
private int seconds = -1;
private Date since;
/**
* Returns the total number of characters to receive in the history.
*
* @return total number of characters to receive in the history.
*/
public int getMaxChars() {
return maxChars;
}
/**
* Returns the total number of messages to receive in the history.
*
* @return the total number of messages to receive in the history.
*/
public int getMaxStanzas() {
return maxStanzas;
}
/**
* Returns the number of seconds to use to filter the messages received during that time.
* In other words, only the messages received in the last "X" seconds will be included in
* the history.
*
* @return the number of seconds to use to filter the messages received during that time.
*/
public int getSeconds() {
return seconds;
}
/**
* Returns the since date to use to filter the messages received during that time.
* In other words, only the messages received since the datetime specified will be
* included in the history.
*
* @return the since date to use to filter the messages received during that time.
*/
public Date getSince() {
return since;
}
/**
* Sets the total number of characters to receive in the history.
*
* @param maxChars the total number of characters to receive in the history.
*/
public void setMaxChars(int maxChars) {
this.maxChars = maxChars;
}
/**
* Sets the total number of messages to receive in the history.
*
* @param maxStanzas the total number of messages to receive in the history.
*/
public void setMaxStanzas(int maxStanzas) {
this.maxStanzas = maxStanzas;
}
/**
* Sets the number of seconds to use to filter the messages received during that time.
* In other words, only the messages received in the last "X" seconds will be included in
* the history.
*
* @param seconds the number of seconds to use to filter the messages received during
* that time.
*/
public void setSeconds(int seconds) {
this.seconds = seconds;
}
/**
* Sets the since date to use to filter the messages received during that time.
* In other words, only the messages received since the datetime specified will be
* included in the history.
*
* @param since the since date to use to filter the messages received during that time.
*/
public void setSince(Date since) {
this.since = since;
}
public String toXML() {
StringBuffer buf = new StringBuffer();
buf.append("<history");
if (getMaxChars() != -1) {
buf.append(" maxchars=\"").append(getMaxChars()).append("\"");
}
if (getMaxStanzas() != -1) {
buf.append(" maxstanzas=\"").append(getMaxStanzas()).append("\"");
}
if (getSeconds() != -1) {
buf.append(" seconds=\"").append(getSeconds()).append("\"");
}
if (getSince() != null) {
SimpleDateFormat utcFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
utcFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
buf.append(" since=\"").append(utcFormat.format(getSince())).append("\"");
}
buf.append("/>");
return buf.toString();
}
}
}

View file

@ -0,0 +1,339 @@
/**
* $RCSfile$
* $Revision$
* $Date$
*
* Copyright 2003-2004 Jive Software.
*
* All rights reserved. Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jivesoftware.smackx.packet;
import java.util.*;
import org.jivesoftware.smack.packet.IQ;
/**
* IQ packet that serves for granting and revoking ownership privileges, granting
* and revoking administrative privileges and destroying a room. All these operations
* are scoped by the 'http://jabber.org/protocol/muc#owner' namespace.
*
* @author Gaston Dombiak
*/
public class MUCOwner extends IQ {
private List items = new ArrayList();
private Destroy destroy;
/**
* Returns an Iterator for item childs that holds information about affiliation,
* jids and nicks.
*
* @return an Iterator for item childs that holds information about affiliation,
* jids and nicks.
*/
public Iterator getItems() {
synchronized (items) {
return Collections.unmodifiableList(new ArrayList(items)).iterator();
}
}
/**
* Returns a request to the server to destroy a room. The sender of the request
* should be the room's owner. If the sender of the destroy request is not the room's owner
* then the server will answer a "Forbidden" error.
*
* @return a request to the server to destroy a room.
*/
public Destroy getDestroy() {
return destroy;
}
/**
* Sets a request to the server to destroy a room. The sender of the request
* should be the room's owner. If the sender of the destroy request is not the room's owner
* then the server will answer a "Forbidden" error.
*
* @param destroy the request to the server to destroy a room.
*/
public void setDestroy(Destroy destroy) {
this.destroy = destroy;
}
/**
* Adds an item child that holds information about affiliation, jids and nicks.
*
* @param item the item child that holds information about affiliation, jids and nicks.
*/
public void addItem(Item item) {
synchronized (items) {
items.add(item);
}
}
public String getChildElementXML() {
StringBuffer buf = new StringBuffer();
buf.append("<query xmlns=\"http://jabber.org/protocol/muc#owner\">");
synchronized (items) {
for (int i = 0; i < items.size(); i++) {
Item item = (Item) items.get(i);
buf.append(item.toXML());
}
}
if (getDestroy() != null) {
buf.append(getDestroy().toXML());
}
// Add packet extensions, if any are defined.
buf.append(getExtensionsXML());
buf.append("</query>");
return buf.toString();
}
/**
* Item child that holds information about affiliation, jids and nicks.
*
* @author Gaston Dombiak
*/
public static class Item {
private String actor;
private String reason;
private String affiliation;
private String jid;
private String nick;
private String role;
/**
* Creates a new item child.
*
* @param affiliation the actor's affiliation to the room
*/
public Item(String affiliation) {
this.affiliation = affiliation;
}
/**
* Returns the actor (JID of an occupant in the room) that was kicked or banned.
*
* @return the JID of an occupant in the room that was kicked or banned.
*/
public String getActor() {
return actor;
}
/**
* Returns the reason for the item child. The reason is optional and could be used to
* explain the reason why a user (occupant) was kicked or banned.
*
* @return the reason for the item child.
*/
public String getReason() {
return reason;
}
/**
* Returns the occupant's affiliation to the room. The affiliation is a semi-permanent
* association or connection with a room. The possible affiliations are "owner", "admin",
* "member", and "outcast" (naturally it is also possible to have no affiliation). An
* affiliation lasts across a user's visits to a room.
*
* @return the actor's affiliation to the room
*/
public String getAffiliation() {
return affiliation;
}
/**
* Returns the <room@service/nick> by which an occupant is identified within the context
* of a room. If the room is non-anonymous, the JID will be included in the item.
*
* @return the room JID by which an occupant is identified within the room.
*/
public String getJid() {
return jid;
}
/**
* Returns the new nickname of an occupant that is changing his/her nickname. The new
* nickname is sent as part of the unavailable presence.
*
* @return the new nickname of an occupant that is changing his/her nickname.
*/
public String getNick() {
return nick;
}
/**
* Returns the temporary position or privilege level of an occupant within a room. The
* possible roles are "moderator", "participant", and "visitor" (it is also possible to
* have no defined role). A role lasts only for the duration of an occupant's visit to
* a room.
*
* @return the privilege level of an occupant within a room.
*/
public String getRole() {
return role;
}
/**
* Sets the actor (JID of an occupant in the room) that was kicked or banned.
*
* @param actor the actor (JID of an occupant in the room) that was kicked or banned.
*/
public void setActor(String actor) {
this.actor = actor;
}
/**
* Sets the reason for the item child. The reason is optional and could be used to
* explain the reason why a user (occupant) was kicked or banned.
*
* @param reason the reason why a user (occupant) was kicked or banned.
*/
public void setReason(String reason) {
this.reason = reason;
}
/**
* Sets the <room@service/nick> by which an occupant is identified within the context
* of a room. If the room is non-anonymous, the JID will be included in the item.
*
* @param jid the JID by which an occupant is identified within a room.
*/
public void setJid(String jid) {
this.jid = jid;
}
/**
* Sets the new nickname of an occupant that is changing his/her nickname. The new
* nickname is sent as part of the unavailable presence.
*
* @param nick the new nickname of an occupant that is changing his/her nickname.
*/
public void setNick(String nick) {
this.nick = nick;
}
/**
* Sets the temporary position or privilege level of an occupant within a room. The
* possible roles are "moderator", "participant", and "visitor" (it is also possible to
* have no defined role). A role lasts only for the duration of an occupant's visit to
* a room.
*
* @param role the new privilege level of an occupant within a room.
*/
public void setRole(String role) {
this.role = role;
}
public String toXML() {
StringBuffer buf = new StringBuffer();
buf.append("<item");
if (getAffiliation() != null) {
buf.append(" affiliation=\"").append(getAffiliation()).append("\"");
}
if (getJid() != null) {
buf.append(" jid=\"").append(getJid()).append("\"");
}
if (getNick() != null) {
buf.append(" nick=\"").append(getNick()).append("\"");
}
if (getRole() != null) {
buf.append(" role=\"").append(getRole()).append("\"");
}
if (getReason() == null && getActor() == null) {
buf.append("/>");
}
else {
buf.append(">");
if (getReason() != null) {
buf.append("<reason>").append(getReason()).append("</reason>");
}
if (getActor() != null) {
buf.append("<actor jid=\"").append(getActor()).append("\"/>");
}
buf.append("</item>");
}
return buf.toString();
}
};
/**
* Represents a request to the server to destroy a room. The sender of the request
* should be the room's owner. If the sender of the destroy request is not the room's owner
* then the server will answer a "Forbidden" error.
*
* @author Gaston Dombiak
*/
public static class Destroy {
private String reason;
private String jid;
/**
* Returns the JID of an alternate location since the current room is being destroyed.
*
* @return the JID of an alternate location.
*/
public String getJid() {
return jid;
}
/**
* Returns the reason for the room destruction.
*
* @return the reason for the room destruction.
*/
public String getReason() {
return reason;
}
/**
* Sets the JID of an alternate location since the current room is being destroyed.
*
* @param jid the JID of an alternate location.
*/
public void setJid(String jid) {
this.jid = jid;
}
/**
* Sets the reason for the room destruction.
*
* @param reason the reason for the room destruction.
*/
public void setReason(String reason) {
this.reason = reason;
}
public String toXML() {
StringBuffer buf = new StringBuffer();
buf.append("<destroy");
if (getJid() != null) {
buf.append(" jid=\"").append(getJid()).append("\"");
}
if (getReason() == null) {
buf.append("/>");
}
else {
buf.append(">");
if (getReason() != null) {
buf.append("<reason>").append(getReason()).append("</reason>");
}
buf.append("</destroy>");
}
return buf.toString();
}
}
}

View file

@ -0,0 +1,627 @@
/**
* $RCSfile$
* $Revision$
* $Date$
*
* Copyright 2003-2004 Jive Software.
*
* All rights reserved. Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jivesoftware.smackx.packet;
import org.jivesoftware.smack.packet.PacketExtension;
/**
* Represents extended presence information about roles, affiliations, full JIDs,
* or status codes scoped by the 'http://jabber.org/protocol/muc#user' namespace.
*
* @author Gaston Dombiak
*/
public class MUCUser implements PacketExtension {
private Invite invite;
private Decline decline;
private Item item;
private String password;
private Status status;
private Destroy destroy;
public String getElementName() {
return "x";
}
public String getNamespace() {
return "http://jabber.org/protocol/muc#user";
}
public String toXML() {
StringBuffer buf = new StringBuffer();
buf.append("<").append(getElementName()).append(" xmlns=\"").append(getNamespace()).append(
"\">");
if (getInvite() != null) {
buf.append(getInvite().toXML());
}
if (getDecline() != null) {
buf.append(getDecline().toXML());
}
if (getItem() != null) {
buf.append(getItem().toXML());
}
if (getPassword() != null) {
buf.append("<password>").append(getPassword()).append("</password>");
}
if (getStatus() != null) {
buf.append(getStatus().toXML());
}
if (getDestroy() != null) {
buf.append(getDestroy().toXML());
}
buf.append("</").append(getElementName()).append(">");
return buf.toString();
}
/**
* Returns the invitation for another user to a room. The sender of the invitation
* must be an occupant of the room. The invitation will be sent to the room which in turn
* will forward the invitation to the invitee.
*
* @return an invitation for another user to a room.
*/
public Invite getInvite() {
return invite;
}
/**
* Returns the rejection to an invitation from another user to a room. The rejection will be
* sent to the room which in turn will forward the refusal to the inviter.
*
* @return a rejection to an invitation from another user to a room.
*/
public Decline getDecline() {
return decline;
}
/**
* Returns the item child that holds information about roles, affiliation, jids and nicks.
*
* @return an item child that holds information about roles, affiliation, jids and nicks.
*/
public Item getItem() {
return item;
}
/**
* Returns the password to use to enter Password-Protected Room. A Password-Protected Room is
* a room that a user cannot enter without first providing the correct password.
*
* @return the password to use to enter Password-Protected Room.
*/
public String getPassword() {
return password;
}
/**
* Returns the status which holds a code that assists in presenting notification messages.
*
* @return the status which holds a code that assists in presenting notification messages.
*/
public Status getStatus() {
return status;
}
/**
* Returns the notification that the room has been destroyed. After a room has been destroyed,
* the room occupants will receive a Presence packet of type 'unavailable' with the reason for
* the room destruction if provided by the room owner.
*
* @return a notification that the room has been destroyed.
*/
public Destroy getDestroy() {
return destroy;
}
/**
* Sets the invitation for another user to a room. The sender of the invitation
* must be an occupant of the room. The invitation will be sent to the room which in turn
* will forward the invitation to the invitee.
*
* @param invite the invitation for another user to a room.
*/
public void setInvite(Invite invite) {
this.invite = invite;
}
/**
* Sets the rejection to an invitation from another user to a room. The rejection will be
* sent to the room which in turn will forward the refusal to the inviter.
*
* @param decline the rejection to an invitation from another user to a room.
*/
public void setDecline(Decline decline) {
this.decline = decline;
}
/**
* Sets the item child that holds information about roles, affiliation, jids and nicks.
*
* @param item the item child that holds information about roles, affiliation, jids and nicks.
*/
public void setItem(Item item) {
this.item = item;
}
/**
* Sets the password to use to enter Password-Protected Room. A Password-Protected Room is
* a room that a user cannot enter without first providing the correct password.
*
* @param string the password to use to enter Password-Protected Room.
*/
public void setPassword(String string) {
password = string;
}
/**
* Sets the status which holds a code that assists in presenting notification messages.
*
* @param status the status which holds a code that assists in presenting notification
* messages.
*/
public void setStatus(Status status) {
this.status = status;
}
/**
* Sets the notification that the room has been destroyed. After a room has been destroyed,
* the room occupants will receive a Presence packet of type 'unavailable' with the reason for
* the room destruction if provided by the room owner.
*
* @param destroy the notification that the room has been destroyed.
*/
public void setDestroy(Destroy destroy) {
this.destroy = destroy;
}
/**
* Represents an invitation for another user to a room. The sender of the invitation
* must be an occupant of the room. The invitation will be sent to the room which in turn
* will forward the invitation to the invitee.
*
* @author Gaston Dombiak
*/
public static class Invite {
private String reason;
private String from;
private String to;
/**
* Returns the bare JID of the inviter or, optionally, the room JID. (e.g.
* 'crone1@shakespeare.lit/desktop').
*
* @return the room's occupant that sent the invitation.
*/
public String getFrom() {
return from;
}
/**
* Returns the message explaining the invitation.
*
* @return the message explaining the invitation.
*/
public String getReason() {
return reason;
}
/**
* Returns the bare JID of the invitee. (e.g. 'hecate@shakespeare.lit')
*
* @return the bare JID of the invitee.
*/
public String getTo() {
return to;
}
/**
* Sets the bare JID of the inviter or, optionally, the room JID. (e.g.
* 'crone1@shakespeare.lit/desktop')
*
* @param from the bare JID of the inviter or, optionally, the room JID.
*/
public void setFrom(String from) {
this.from = from;
}
/**
* Sets the message explaining the invitation.
*
* @param reason the message explaining the invitation.
*/
public void setReason(String reason) {
this.reason = reason;
}
/**
* Sets the bare JID of the invitee. (e.g. 'hecate@shakespeare.lit')
*
* @param to the bare JID of the invitee.
*/
public void setTo(String to) {
this.to = to;
}
public String toXML() {
StringBuffer buf = new StringBuffer();
buf.append("<invite ");
if (getTo() != null) {
buf.append(" to=\"").append(getTo()).append("\"");
}
if (getFrom() != null) {
buf.append(" from=\"").append(getFrom()).append("\"");
}
buf.append(">");
if (getReason() != null) {
buf.append("<reason>").append(getReason()).append("</reason>");
}
buf.append("</invite>");
return buf.toString();
}
};
/**
* Represents a rejection to an invitation from another user to a room. The rejection will be
* sent to the room which in turn will forward the refusal to the inviter.
*
* @author Gaston Dombiak
*/
public static class Decline {
private String reason;
private String from;
private String to;
/**
* Returns the bare JID of the invitee that rejected the invitation. (e.g.
* 'crone1@shakespeare.lit/desktop').
*
* @return the bare JID of the invitee that rejected the invitation.
*/
public String getFrom() {
return from;
}
/**
* Returns the message explaining why the invitation was rejected.
*
* @return the message explaining the reason for the rejection.
*/
public String getReason() {
return reason;
}
/**
* Returns the bare JID of the inviter. (e.g. 'hecate@shakespeare.lit')
*
* @return the bare JID of the inviter.
*/
public String getTo() {
return to;
}
/**
* Sets the bare JID of the invitee that rejected the invitation. (e.g.
* 'crone1@shakespeare.lit/desktop').
*
* @param from the bare JID of the invitee that rejected the invitation.
*/
public void setFrom(String from) {
this.from = from;
}
/**
* Sets the message explaining why the invitation was rejected.
*
* @param reason the message explaining the reason for the rejection.
*/
public void setReason(String reason) {
this.reason = reason;
}
/**
* Sets the bare JID of the inviter. (e.g. 'hecate@shakespeare.lit')
*
* @param to the bare JID of the inviter.
*/
public void setTo(String to) {
this.to = to;
}
public String toXML() {
StringBuffer buf = new StringBuffer();
buf.append("<decline ");
if (getTo() != null) {
buf.append(" to=\"").append(getTo()).append("\"");
}
if (getFrom() != null) {
buf.append(" from=\"").append(getFrom()).append("\"");
}
buf.append(">");
if (getReason() != null) {
buf.append("<reason>").append(getReason()).append("</reason>");
}
buf.append("</decline>");
return buf.toString();
}
};
/**
* Item child that holds information about roles, affiliation, jids and nicks.
*
* @author Gaston Dombiak
*/
public static class Item {
private String actor;
private String reason;
private String affiliation;
private String jid;
private String nick;
private String role;
/**
* Creates a new item child.
*
* @param affiliation the actor's affiliation to the room
* @param role the privilege level of an occupant within a room.
*/
public Item(String affiliation, String role) {
this.affiliation = affiliation;
this.role = role;
}
/**
* Returns the actor (JID of an occupant in the room) that was kicked or banned.
*
* @return the JID of an occupant in the room that was kicked or banned.
*/
public String getActor() {
return actor == null ? "" : actor;
}
/**
* Returns the reason for the item child. The reason is optional and could be used to
* explain the reason why a user (occupant) was kicked or banned.
*
* @return the reason for the item child.
*/
public String getReason() {
return reason == null ? "" : reason;
}
/**
* Returns the occupant's affiliation to the room. The affiliation is a semi-permanent
* association or connection with a room. The possible affiliations are "owner", "admin",
* "member", and "outcast" (naturally it is also possible to have no affiliation). An
* affiliation lasts across a user's visits to a room.
*
* @return the actor's affiliation to the room
*/
public String getAffiliation() {
return affiliation;
}
/**
* Returns the <room@service/nick> by which an occupant is identified within the context
* of a room. If the room is non-anonymous, the JID will be included in the item.
*
* @return the room JID by which an occupant is identified within the room.
*/
public String getJid() {
return jid;
}
/**
* Returns the new nickname of an occupant that is changing his/her nickname. The new
* nickname is sent as part of the unavailable presence.
*
* @return the new nickname of an occupant that is changing his/her nickname.
*/
public String getNick() {
return nick;
}
/**
* Returns the temporary position or privilege level of an occupant within a room. The
* possible roles are "moderator", "participant", and "visitor" (it is also possible to
* have no defined role). A role lasts only for the duration of an occupant's visit to
* a room.
*
* @return the privilege level of an occupant within a room.
*/
public String getRole() {
return role;
}
/**
* Sets the actor (JID of an occupant in the room) that was kicked or banned.
*
* @param actor the actor (JID of an occupant in the room) that was kicked or banned.
*/
public void setActor(String actor) {
this.actor = actor;
}
/**
* Sets the reason for the item child. The reason is optional and could be used to
* explain the reason why a user (occupant) was kicked or banned.
*
* @param reason the reason why a user (occupant) was kicked or banned.
*/
public void setReason(String reason) {
this.reason = reason;
}
/**
* Sets the <room@service/nick> by which an occupant is identified within the context
* of a room. If the room is non-anonymous, the JID will be included in the item.
*
* @param jid the JID by which an occupant is identified within a room.
*/
public void setJid(String jid) {
this.jid = jid;
}
/**
* Sets the new nickname of an occupant that is changing his/her nickname. The new
* nickname is sent as part of the unavailable presence.
*
* @param nick the new nickname of an occupant that is changing his/her nickname.
*/
public void setNick(String nick) {
this.nick = nick;
}
public String toXML() {
StringBuffer buf = new StringBuffer();
buf.append("<item");
if (getAffiliation() != null) {
buf.append(" affiliation=\"").append(getAffiliation()).append("\"");
}
if (getJid() != null) {
buf.append(" jid=\"").append(getJid()).append("\"");
}
if (getNick() != null) {
buf.append(" nick=\"").append(getNick()).append("\"");
}
if (getRole() != null) {
buf.append(" role=\"").append(getRole()).append("\"");
}
if (getReason() == null && getActor() == null) {
buf.append("/>");
}
else {
buf.append(">");
if (getReason() != null) {
buf.append("<reason>").append(getReason()).append("</reason>");
}
if (getActor() != null) {
buf.append("<actor jid=\"").append(getActor()).append("\"/>");
}
buf.append("</item>");
}
return buf.toString();
}
};
/**
* Status code assists in presenting notification messages. The following link provides the
* list of existing error codes (@link http://www.jabber.org/jeps/jep-0045.html#errorstatus).
*
* @author Gaston Dombiak
*/
public static class Status {
private String code;
/**
* Creates a new instance of Status with the specified code.
*
* @param code the code that uniquely identifies the reason of the error.
*/
public Status(String code) {
this.code = code;
}
/**
* Returns the code that uniquely identifies the reason of the error. The code
* assists in presenting notification messages.
*
* @return the code that uniquely identifies the reason of the error.
*/
public String getCode() {
return code;
}
public String toXML() {
StringBuffer buf = new StringBuffer();
buf.append("<status code=\"").append(getCode()).append("\"/>");
return buf.toString();
}
};
/**
* Represents a notification that the room has been destroyed. After a room has been destroyed,
* the room occupants will receive a Presence packet of type 'unavailable' with the reason for
* the room destruction if provided by the room owner.
*
* @author Gaston Dombiak
*/
public static class Destroy {
private String reason;
private String jid;
/**
* Returns the JID of an alternate location since the current room is being destroyed.
*
* @return the JID of an alternate location.
*/
public String getJid() {
return jid;
}
/**
* Returns the reason for the room destruction.
*
* @return the reason for the room destruction.
*/
public String getReason() {
return reason;
}
/**
* Sets the JID of an alternate location since the current room is being destroyed.
*
* @param jid the JID of an alternate location.
*/
public void setJid(String jid) {
this.jid = jid;
}
/**
* Sets the reason for the room destruction.
*
* @param reason the reason for the room destruction.
*/
public void setReason(String reason) {
this.reason = reason;
}
public String toXML() {
StringBuffer buf = new StringBuffer();
buf.append("<destroy");
if (getJid() != null) {
buf.append(" jid=\"").append(getJid()).append("\"");
}
if (getReason() == null) {
buf.append("/>");
}
else {
buf.append(">");
if (getReason() != null) {
buf.append("<reason>").append(getReason()).append("</reason>");
}
buf.append("</destroy>");
}
return buf.toString();
}
}
}

View file

@ -0,0 +1,334 @@
/**
* $RCSfile$
* $Revision$
* $Date$
*
* Copyright 2003-2004 Jive Software.
*
* All rights reserved. Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jivesoftware.smackx.packet;
import java.util.*;
import org.jivesoftware.smack.packet.PacketExtension;
/**
* Represents message events relating to the delivery, display, composition and cancellation of
* messages.<p>
*
* There are four message events currently defined in this namespace:
* <ol>
* <li>Offline<br>
* Indicates that the message has been stored offline by the intended recipient's server. This
* event is triggered only if the intended recipient's server supports offline storage, has that
* support enabled, and the recipient is offline when the server receives the message for delivery.</li>
*
* <li>Delivered<br>
* Indicates that the message has been delivered to the recipient. This signifies that the message
* has reached the recipient's XMPP client, but does not necessarily mean that the message has
* been displayed. This event is to be raised by the XMPP client.</li>
*
* <li>Displayed<br>
* Once the message has been received by the recipient's XMPP client, it may be displayed to the
* user. This event indicates that the message has been displayed, and is to be raised by the
* XMPP client. Even if a message is displayed multiple times, this event should be raised only
* once.</li>
*
* <li>Composing<br>
* In threaded chat conversations, this indicates that the recipient is composing a reply to a
* message. The event is to be raised by the recipient's XMPP client. A XMPP client is allowed
* to raise this event multiple times in response to the same request, providing the original
* event is cancelled first.</li>
* </ol>
*
* @author Gaston Dombiak
*/
public class MessageEvent implements PacketExtension {
public static final String OFFLINE = "offline";
public static final String COMPOSING = "composing";
public static final String DISPLAYED = "displayed";
public static final String DELIVERED = "delivered";
public static final String CANCELLED = "cancelled";
private boolean offline = false;
private boolean delivered = false;
private boolean displayed = false;
private boolean composing = false;
private boolean cancelled = true;
private String packetID = null;
/**
* Returns the XML element name of the extension sub-packet root element.
* Always returns "x"
*
* @return the XML element name of the packet extension.
*/
public String getElementName() {
return "x";
}
/**
* Returns the XML namespace of the extension sub-packet root element.
* According the specification the namespace is always "jabber:x:event"
*
* @return the XML namespace of the packet extension.
*/
public String getNamespace() {
return "jabber:x:event";
}
/**
* When the message is a request returns if the sender of the message requests to be notified
* when the receiver is composing a reply.
* When the message is a notification returns if the receiver of the message is composing a
* reply.
*
* @return true if the sender is requesting to be notified when composing or when notifying
* that the receiver of the message is composing a reply
*/
public boolean isComposing() {
return composing;
}
/**
* When the message is a request returns if the sender of the message requests to be notified
* when the message is delivered.
* When the message is a notification returns if the message was delivered or not.
*
* @return true if the sender is requesting to be notified when delivered or when notifying
* that the message was delivered
*/
public boolean isDelivered() {
return delivered;
}
/**
* When the message is a request returns if the sender of the message requests to be notified
* when the message is displayed.
* When the message is a notification returns if the message was displayed or not.
*
* @return true if the sender is requesting to be notified when displayed or when notifying
* that the message was displayed
*/
public boolean isDisplayed() {
return displayed;
}
/**
* When the message is a request returns if the sender of the message requests to be notified
* when the receiver of the message is offline.
* When the message is a notification returns if the receiver of the message was offline.
*
* @return true if the sender is requesting to be notified when offline or when notifying
* that the receiver of the message is offline
*/
public boolean isOffline() {
return offline;
}
/**
* When the message is a notification returns if the receiver of the message cancelled
* composing a reply.
*
* @return true if the receiver of the message cancelled composing a reply
*/
public boolean isCancelled() {
return cancelled;
}
/**
* Returns the unique ID of the message that requested to be notified of the event.
* The packet id is not used when the message is a request for notifications
*
* @return the message id that requested to be notified of the event.
*/
public String getPacketID() {
return packetID;
}
/**
* Returns the types of events. The type of event could be:
* "offline", "composing","delivered","displayed", "offline"
*
* @return an iterator over all the types of events of the MessageEvent.
*/
public Iterator getEventTypes() {
ArrayList allEvents = new ArrayList();
if (isDelivered()) {
allEvents.add(MessageEvent.DELIVERED);
}
if (isCancelled()) {
allEvents.add(MessageEvent.CANCELLED);
}
if (isComposing()) {
allEvents.add(MessageEvent.COMPOSING);
}
if (isDisplayed()) {
allEvents.add(MessageEvent.DISPLAYED);
}
if (isOffline()) {
allEvents.add(MessageEvent.OFFLINE);
}
return allEvents.iterator();
}
/**
* When the message is a request sets if the sender of the message requests to be notified
* when the receiver is composing a reply.
* When the message is a notification sets if the receiver of the message is composing a
* reply.
*
* @param composing sets if the sender is requesting to be notified when composing or when
* notifying that the receiver of the message is composing a reply
*/
public void setComposing(boolean composing) {
this.composing = composing;
setCancelled(false);
}
/**
* When the message is a request sets if the sender of the message requests to be notified
* when the message is delivered.
* When the message is a notification sets if the message was delivered or not.
*
* @param delivered sets if the sender is requesting to be notified when delivered or when
* notifying that the message was delivered
*/
public void setDelivered(boolean delivered) {
this.delivered = delivered;
setCancelled(false);
}
/**
* When the message is a request sets if the sender of the message requests to be notified
* when the message is displayed.
* When the message is a notification sets if the message was displayed or not.
*
* @param displayed sets if the sender is requesting to be notified when displayed or when
* notifying that the message was displayed
*/
public void setDisplayed(boolean displayed) {
this.displayed = displayed;
setCancelled(false);
}
/**
* When the message is a request sets if the sender of the message requests to be notified
* when the receiver of the message is offline.
* When the message is a notification sets if the receiver of the message was offline.
*
* @param offline sets if the sender is requesting to be notified when offline or when
* notifying that the receiver of the message is offline
*/
public void setOffline(boolean offline) {
this.offline = offline;
setCancelled(false);
}
/**
* When the message is a notification sets if the receiver of the message cancelled
* composing a reply.
* The Cancelled event is never requested explicitly. It is requested implicitly when
* requesting to be notified of the Composing event.
*
* @param cancelled sets if the receiver of the message cancelled composing a reply
*/
public void setCancelled(boolean cancelled) {
this.cancelled = cancelled;
}
/**
* Sets the unique ID of the message that requested to be notified of the event.
* The packet id is not used when the message is a request for notifications
*
* @param packetID the message id that requested to be notified of the event.
*/
public void setPacketID(String packetID) {
this.packetID = packetID;
}
/**
* Returns true if this MessageEvent is a request for notifications.
* Returns false if this MessageEvent is a notification of an event.
*
* @return true if this message is a request for notifications.
*/
public boolean isMessageEventRequest() {
return this.packetID == null;
}
/**
* Returns the XML representation of a Message Event according the specification.
*
* Usually the XML representation will be inside of a Message XML representation like
* in the following examples:<p>
*
* Request to be notified when displayed:
* <pre>
* &lt;message
* to='romeo@montague.net/orchard'
* from='juliet@capulet.com/balcony'
* id='message22'&gt;
* &lt;x xmlns='jabber:x:event'&gt;
* &lt;displayed/&gt;
* &lt;/x&gt;
* &lt;/message&gt;
* </pre>
*
* Notification of displayed:
* <pre>
* &lt;message
* from='romeo@montague.net/orchard'
* to='juliet@capulet.com/balcony'&gt;
* &lt;x xmlns='jabber:x:event'&gt;
* &lt;displayed/&gt;
* &lt;id&gt;message22&lt;/id&gt;
* &lt;/x&gt;
* &lt;/message&gt;
* </pre>
*
*/
public String toXML() {
StringBuffer buf = new StringBuffer();
buf.append("<").append(getElementName()).append(" xmlns=\"").append(getNamespace()).append(
"\">");
// Note: Cancellation events don't specify any tag. They just send the packetID
// Add the offline tag if the sender requests to be notified of offline events or if
// the target is offline
if (isOffline())
buf.append("<").append(MessageEvent.OFFLINE).append("/>");
// Add the delivered tag if the sender requests to be notified when the message is
// delivered or if the target notifies that the message has been delivered
if (isDelivered())
buf.append("<").append(MessageEvent.DELIVERED).append("/>");
// Add the displayed tag if the sender requests to be notified when the message is
// displayed or if the target notifies that the message has been displayed
if (isDisplayed())
buf.append("<").append(MessageEvent.DISPLAYED).append("/>");
// Add the composing tag if the sender requests to be notified when the target is
// composing a reply or if the target notifies that he/she is composing a reply
if (isComposing())
buf.append("<").append(MessageEvent.COMPOSING).append("/>");
// Add the id tag only if the MessageEvent is a notification message (not a request)
if (getPacketID() != null)
buf.append("<id>").append(getPacketID()).append("</id>");
buf.append("</").append(getElementName()).append(">");
return buf.toString();
}
}

View file

@ -0,0 +1,128 @@
/**
* $RCSfile$
* $Revision$
* $Date$
*
* Copyright 2003-2004 Jive Software.
*
* All rights reserved. Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jivesoftware.smackx.packet;
import org.jivesoftware.smack.packet.PacketExtension;
import org.jivesoftware.smack.provider.PacketExtensionProvider;
import org.xmlpull.v1.XmlPullParser;
/**
* OfflineMessageInfo is an extension included in the retrieved offline messages requested by
* the {@link org.jivesoftware.smackx.OfflineMessageManager}. This extension includes a stamp
* that uniquely identifies the offline message. This stamp may be used for deleting the offline
* message. The stamp may be of the form UTC timestamps but it is not required to have that format.
*
* @author Gaston Dombiak
*/
public class OfflineMessageInfo implements PacketExtension {
private String node = null;
/**
* Returns the XML element name of the extension sub-packet root element.
* Always returns "offline"
*
* @return the XML element name of the packet extension.
*/
public String getElementName() {
return "offline";
}
/**
* Returns the XML namespace of the extension sub-packet root element.
* According the specification the namespace is always "http://jabber.org/protocol/offline"
*
* @return the XML namespace of the packet extension.
*/
public String getNamespace() {
return "http://jabber.org/protocol/offline";
}
/**
* Returns the stamp that uniquely identifies the offline message. This stamp may
* be used for deleting the offline message. The stamp may be of the form UTC timestamps
* but it is not required to have that format.
*
* @return the stamp that uniquely identifies the offline message.
*/
public String getNode() {
return node;
}
/**
* Sets the stamp that uniquely identifies the offline message. This stamp may
* be used for deleting the offline message. The stamp may be of the form UTC timestamps
* but it is not required to have that format.
*
* @param node the stamp that uniquely identifies the offline message.
*/
public void setNode(String node) {
this.node = node;
}
public String toXML() {
StringBuffer buf = new StringBuffer();
buf.append("<").append(getElementName()).append(" xmlns=\"").append(getNamespace()).append(
"\">");
if (getNode() != null)
buf.append("<item node=\"").append(getNode()).append("\"/>");
buf.append("</").append(getElementName()).append(">");
return buf.toString();
}
public static class Provider implements PacketExtensionProvider {
/**
* Creates a new Provider.
* ProviderManager requires that every PacketExtensionProvider has a public,
* no-argument constructor
*/
public Provider() {
}
/**
* Parses a OfflineMessageInfo packet (extension sub-packet).
*
* @param parser the XML parser, positioned at the starting element of the extension.
* @return a PacketExtension.
* @throws Exception if a parsing error occurs.
*/
public PacketExtension parseExtension(XmlPullParser parser)
throws Exception {
OfflineMessageInfo info = new OfflineMessageInfo();
boolean done = false;
while (!done) {
int eventType = parser.next();
if (eventType == XmlPullParser.START_TAG) {
if (parser.getName().equals("item"))
info.setNode(parser.getAttributeValue("", "node"));
} else if (eventType == XmlPullParser.END_TAG) {
if (parser.getName().equals("offline")) {
done = true;
}
}
}
return info;
}
}
}

View file

@ -0,0 +1,237 @@
/**
* $RCSfile$
* $Revision$
* $Date$
*
* Copyright 2003-2004 Jive Software.
*
* All rights reserved. Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jivesoftware.smackx.packet;
import org.jivesoftware.smack.packet.IQ;
import org.jivesoftware.smack.provider.IQProvider;
import org.xmlpull.v1.XmlPullParser;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
/**
* Represents a request to get some or all the offline messages of a user. This class can also
* be used for deleting some or all the offline messages of a user.
*
* @author Gaston Dombiak
*/
public class OfflineMessageRequest extends IQ {
private List items = new ArrayList();
private boolean purge = false;
private boolean fetch = false;
/**
* Returns an Iterator for item childs that holds information about offline messages to
* view or delete.
*
* @return an Iterator for item childs that holds information about offline messages to
* view or delete.
*/
public Iterator getItems() {
synchronized (items) {
return Collections.unmodifiableList(new ArrayList(items)).iterator();
}
}
/**
* Adds an item child that holds information about offline messages to view or delete.
*
* @param item the item child that holds information about offline messages to view or delete.
*/
public void addItem(Item item) {
synchronized (items) {
items.add(item);
}
}
/**
* Returns true if all the offline messages of the user should be deleted.
*
* @return true if all the offline messages of the user should be deleted.
*/
public boolean isPurge() {
return purge;
}
/**
* Sets if all the offline messages of the user should be deleted.
*
* @param purge true if all the offline messages of the user should be deleted.
*/
public void setPurge(boolean purge) {
this.purge = purge;
}
/**
* Returns true if all the offline messages of the user should be retrieved.
*
* @return true if all the offline messages of the user should be retrieved.
*/
public boolean isFetch() {
return fetch;
}
/**
* Sets if all the offline messages of the user should be retrieved.
*
* @param fetch true if all the offline messages of the user should be retrieved.
*/
public void setFetch(boolean fetch) {
this.fetch = fetch;
}
public String getChildElementXML() {
StringBuffer buf = new StringBuffer();
buf.append("<offline xmlns=\"http://jabber.org/protocol/offline\">");
synchronized (items) {
for (int i = 0; i < items.size(); i++) {
Item item = (Item) items.get(i);
buf.append(item.toXML());
}
}
if (purge) {
buf.append("<purge/>");
}
if (fetch) {
buf.append("<fetch/>");
}
// Add packet extensions, if any are defined.
buf.append(getExtensionsXML());
buf.append("</offline>");
return buf.toString();
}
/**
* Item child that holds information about offline messages to view or delete.
*
* @author Gaston Dombiak
*/
public static class Item {
private String action;
private String jid;
private String node;
/**
* Creates a new item child.
*
* @param node the actor's affiliation to the room
*/
public Item(String node) {
this.node = node;
}
public String getNode() {
return node;
}
/**
* Returns "view" or "remove" that indicate if the server should return the specified
* offline message or delete it.
*
* @return "view" or "remove" that indicate if the server should return the specified
* offline message or delete it.
*/
public String getAction() {
return action;
}
/**
* Sets if the server should return the specified offline message or delete it. Possible
* values are "view" or "remove".
*
* @param action if the server should return the specified offline message or delete it.
*/
public void setAction(String action) {
this.action = action;
}
public String getJid() {
return jid;
}
public void setJid(String jid) {
this.jid = jid;
}
public String toXML() {
StringBuffer buf = new StringBuffer();
buf.append("<item");
if (getAction() != null) {
buf.append(" action=\"").append(getAction()).append("\"");
}
if (getJid() != null) {
buf.append(" jid=\"").append(getJid()).append("\"");
}
if (getNode() != null) {
buf.append(" node=\"").append(getNode()).append("\"");
}
buf.append("/>");
return buf.toString();
}
}
public static class Provider implements IQProvider {
public IQ parseIQ(XmlPullParser parser) throws Exception {
OfflineMessageRequest request = new OfflineMessageRequest();
boolean done = false;
while (!done) {
int eventType = parser.next();
if (eventType == XmlPullParser.START_TAG) {
if (parser.getName().equals("item")) {
request.addItem(parseItem(parser));
}
else if (parser.getName().equals("purge")) {
request.setPurge(true);
}
else if (parser.getName().equals("fetch")) {
request.setFetch(true);
}
} else if (eventType == XmlPullParser.END_TAG) {
if (parser.getName().equals("offline")) {
done = true;
}
}
}
return request;
}
private Item parseItem(XmlPullParser parser) throws Exception {
boolean done = false;
Item item = new Item(parser.getAttributeValue("", "node"));
item.setAction(parser.getAttributeValue("", "action"));
item.setJid(parser.getAttributeValue("", "jid"));
while (!done) {
int eventType = parser.next();
if (eventType == XmlPullParser.END_TAG) {
if (parser.getName().equals("item")) {
done = true;
}
}
}
return item;
}
}
}

View file

@ -0,0 +1,52 @@
/**
* $RCSfile$
* $Revision$
* $Date$
*
* Copyright 2003-2004 Jive Software.
*
* All rights reserved. Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jivesoftware.smackx.packet;
/**
* Interface to represent private data. Each private data chunk is an XML sub-document
* with a root element name and namespace.
*
* @see org.jivesoftware.smackx.PrivateDataManager
* @author Matt Tucker
*/
public interface PrivateData {
/**
* Returns the root element name.
*
* @return the element name.
*/
public String getElementName();
/**
* Returns the root element XML namespace.
*
* @return the namespace.
*/
public String getNamespace();
/**
* Returns the XML reppresentation of the PrivateData.
*
* @return the private data as XML.
*/
public String toXML();
}

View file

@ -0,0 +1,175 @@
/**
* $RCSfile$
* $Revision$
* $Date$
*
* Copyright 2003-2004 Jive Software.
*
* All rights reserved. Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jivesoftware.smackx.packet;
import java.util.*;
import org.jivesoftware.smack.*;
import org.jivesoftware.smack.packet.PacketExtension;
import org.jivesoftware.smackx.*;
/**
* Represents XMPP Roster Item Exchange packets.<p>
*
* The 'jabber:x:roster' namespace (which is not to be confused with the 'jabber:iq:roster'
* namespace) is used to send roster items from one client to another. A roster item is sent by
* adding to the &lt;message/&gt; element an &lt;x/&gt; child scoped by the 'jabber:x:roster' namespace. This
* &lt;x/&gt; element may contain one or more &lt;item/&gt; children (one for each roster item to be sent).<p>
*
* Each &lt;item/&gt; element may possess the following attributes:<p>
*
* &lt;jid/&gt; -- The id of the contact being sent. This attribute is required.<br>
* &lt;name/&gt; -- A natural-language nickname for the contact. This attribute is optional.<p>
*
* Each &lt;item/&gt; element may also contain one or more &lt;group/&gt; children specifying the
* natural-language name of a user-specified group, for the purpose of categorizing this contact
* into one or more roster groups.
*
* @author Gaston Dombiak
*/
public class RosterExchange implements PacketExtension {
private List remoteRosterEntries = new ArrayList();
/**
* Creates a new empty roster exchange package.
*
*/
public RosterExchange() {
super();
}
/**
* Creates a new roster exchange package with the entries specified in roster.
*
* @param roster the roster to send to other XMPP entity.
*/
public RosterExchange(Roster roster) {
// Add all the roster entries to the new RosterExchange
for (Iterator rosterEntries = roster.getEntries(); rosterEntries.hasNext();) {
this.addRosterEntry((RosterEntry) rosterEntries.next());
}
}
/**
* Adds a roster entry to the packet.
*
* @param rosterEntry a roster entry to add.
*/
public void addRosterEntry(RosterEntry rosterEntry) {
// Obtain a String[] from the roster entry groups name
ArrayList groupNamesList = new ArrayList();
String[] groupNames;
for (Iterator groups = rosterEntry.getGroups(); groups.hasNext();) {
groupNamesList.add(((RosterGroup) groups.next()).getName());
}
groupNames = (String[]) groupNamesList.toArray(new String[groupNamesList.size()]);
// Create a new Entry based on the rosterEntry and add it to the packet
RemoteRosterEntry remoteRosterEntry = new RemoteRosterEntry(rosterEntry.getUser(), rosterEntry.getName(), groupNames);
addRosterEntry(remoteRosterEntry);
}
/**
* Adds a remote roster entry to the packet.
*
* @param remoteRosterEntry a remote roster entry to add.
*/
public void addRosterEntry(RemoteRosterEntry remoteRosterEntry) {
synchronized (remoteRosterEntries) {
remoteRosterEntries.add(remoteRosterEntry);
}
}
/**
* Returns the XML element name of the extension sub-packet root element.
* Always returns "x"
*
* @return the XML element name of the packet extension.
*/
public String getElementName() {
return "x";
}
/**
* Returns the XML namespace of the extension sub-packet root element.
* According the specification the namespace is always "jabber:x:roster"
* (which is not to be confused with the 'jabber:iq:roster' namespace
*
* @return the XML namespace of the packet extension.
*/
public String getNamespace() {
return "jabber:x:roster";
}
/**
* Returns an Iterator for the roster entries in the packet.
*
* @return an Iterator for the roster entries in the packet.
*/
public Iterator getRosterEntries() {
synchronized (remoteRosterEntries) {
List entries = Collections.unmodifiableList(new ArrayList(remoteRosterEntries));
return entries.iterator();
}
}
/**
* Returns a count of the entries in the roster exchange.
*
* @return the number of entries in the roster exchange.
*/
public int getEntryCount() {
return remoteRosterEntries.size();
}
/**
* Returns the XML representation of a Roster Item Exchange according the specification.
*
* Usually the XML representation will be inside of a Message XML representation like
* in the following example:
* <pre>
* &lt;message id="MlIpV-4" to="gato1@gato.home" from="gato3@gato.home/Smack"&gt;
* &lt;subject&gt;Any subject you want&lt;/subject&gt;
* &lt;body&gt;This message contains roster items.&lt;/body&gt;
* &lt;x xmlns="jabber:x:roster"&gt;
* &lt;item jid="gato1@gato.home"/&gt;
* &lt;item jid="gato2@gato.home"/&gt;
* &lt;/x&gt;
* &lt;/message&gt;
* </pre>
*
*/
public String toXML() {
StringBuffer buf = new StringBuffer();
buf.append("<").append(getElementName()).append(" xmlns=\"").append(getNamespace()).append(
"\">");
// Loop through all roster entries and append them to the string buffer
for (Iterator i = getRosterEntries(); i.hasNext();) {
RemoteRosterEntry remoteRosterEntry = (RemoteRosterEntry) i.next();
buf.append(remoteRosterEntry.toXML());
}
buf.append("</").append(getElementName()).append(">");
return buf.toString();
}
}

View file

@ -0,0 +1,196 @@
/**
* $RCSfile$
* $Revision$
* $Date$
*
* Copyright 2003-2004 Jive Software.
*
* All rights reserved. Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jivesoftware.smackx.packet;
import org.jivesoftware.smack.packet.IQ;
import java.util.*;
import java.text.SimpleDateFormat;
import java.text.DateFormat;
/**
* A Time IQ packet, which is used by XMPP clients to exchange their respective local
* times. Clients that wish to fully support the entitity time protocol should register
* a PacketListener for incoming time requests that then respond with the local time.
* This class can be used to request the time from other clients, such as in the
* following code snippet:
*
* <pre>
* // Request the time from a remote user.
* Time timeRequest = new Time();
* timeRequest.setType(IQ.Type.GET);
* timeRequest.setTo(someUser@example.com);
*
* // Create a packet collector to listen for a response.
* PacketCollector collector = con.createPacketCollector(
* new PacketIDFilter(timeRequest.getPacketID()));
*
* con.sendPacket(timeRequest);
*
* // Wait up to 5 seconds for a result.
* IQ result = (IQ)collector.nextResult(5000);
* if (result != null && result.getType() == IQ.Type.RESULT) {
* Time timeResult = (Time)result;
* // Do something with result...
* }</pre><p>
*
* Warning: this is an non-standard protocol documented by
* <a href="http://www.jabber.org/jeps/jep-0090.html">JEP-90</a>. Because this is a
* non-standard protocol, it is subject to change.
*
* @author Matt Tucker
*/
public class Time extends IQ {
private static SimpleDateFormat utcFormat = new SimpleDateFormat("yyyyMMdd'T'HH:mm:ss");
private static DateFormat displayFormat = DateFormat.getDateTimeInstance();
private String utc = null;
private String tz = null;
private String display = null;
/**
* Creates a new Time instance with empty values for all fields.
*/
public Time() {
this(Calendar.getInstance());
}
/**
* Creates a new Time instance using the specified calendar instance as
* the time value to send.
*
* @param cal the time value.
*/
public Time(Calendar cal) {
TimeZone timeZone = cal.getTimeZone();
tz = cal.getTimeZone().getID();
display = displayFormat.format(cal.getTime());
// Convert local time to the UTC time.
utc = utcFormat.format(new Date(
cal.getTimeInMillis() - timeZone.getOffset(cal.getTimeInMillis())));
}
/**
* Returns the local time or <tt>null</tt> if the time hasn't been set.
*
* @return the lcocal time.
*/
public Date getTime() {
if (utc == null) {
return null;
}
Date date = null;
try {
Calendar cal = Calendar.getInstance();
// Convert the UTC time to local time.
cal.setTime(new Date(utcFormat.parse(utc).getTime() +
cal.getTimeZone().getOffset(cal.getTimeInMillis())));
date = cal.getTime();
}
catch (Exception e) {
e.printStackTrace();
}
return date;
}
/**
* Sets the time using the local time.
*
* @param time the current local time.
*/
public void setTime(Date time) {
// Convert local time to UTC time.
utc = utcFormat.format(new Date(
time.getTime() - TimeZone.getDefault().getOffset(time.getTime())));
}
/**
* Returns the time as a UTC formatted String using the format CCYYMMDDThh:mm:ss.
*
* @return the time as a UTC formatted String.
*/
public String getUtc() {
return utc;
}
/**
* Sets the time using UTC formatted String in the format CCYYMMDDThh:mm:ss.
*
* @param utc the time using a formatted String.
*/
public void setUtc(String utc) {
this.utc = utc;
}
/**
* Returns the time zone.
*
* @return the time zone.
*/
public String getTz() {
return tz;
}
/**
* Sets the time zone.
*
* @param tz the time zone.
*/
public void setTz(String tz) {
this.tz = tz;
}
/**
* Returns the local (non-utc) time in human-friendly format.
*
* @return the local time in human-friendly format.
*/
public String getDisplay() {
return display;
}
/**
* Sets the local time in human-friendly format.
*
* @param display the local time in human-friendly format.
*/
public void setDisplay(String display) {
this.display = display;
}
public String getChildElementXML() {
StringBuffer buf = new StringBuffer();
buf.append("<query xmlns=\"jabber:iq:time\">");
if (utc != null) {
buf.append("<utc>").append(utc).append("</utc>");
}
if (tz != null) {
buf.append("<tz>").append(tz).append("</tz>");
}
if (display != null) {
buf.append("<display>").append(display).append("</display>");
}
buf.append("</query>");
return buf.toString();
}
}

View file

@ -0,0 +1,646 @@
/**
* $RCSfile$
* $Revision$
* $Date$
*
* Copyright 2003-2004 Jive Software.
*
* All rights reserved. Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jivesoftware.smackx.packet;
import org.jivesoftware.smack.PacketCollector;
import org.jivesoftware.smack.SmackConfiguration;
import org.jivesoftware.smack.XMPPConnection;
import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smack.filter.PacketIDFilter;
import org.jivesoftware.smack.packet.IQ;
import org.jivesoftware.smack.packet.XMPPError;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
/**
* A VCard class for use with the
* <a href="http://www.jivesoftware.org/smack/" target="_blank">SMACK jabber library</a>.<p>
*
* You should refer to the
* <a href="http://www.jabber.org/jeps/jep-0054.html" target="_blank">JEP-54 documentation</a>.<p>
*
* Please note that this class is incomplete but it does provide the most commonly found
* information in vCards. Also remember that VCard transfer is not a standard, and the protocol
* may change or be replaced.<p>
*
* <b>Usage:</b>
* <pre>
*
* // To save VCard:
*
* VCard vCard = new VCard();
* vCard.setFirstName("kir");
* vCard.setLastName("max");
* vCard.setEmailHome("foo@fee.bar");
* vCard.setJabberId("jabber@id.org");
* vCard.setOrganization("Jetbrains, s.r.o");
* vCard.setNickName("KIR");
*
* vCard.setField("TITLE", "Mr");
* vCard.setAddressFieldHome("STREET", "Some street");
* vCard.setAddressFieldWork("CTRY", "US");
* vCard.setPhoneWork("FAX", "3443233");
*
* vCard.save(connection);
*
* // To load VCard:
*
* VCard vCard = new VCard();
* vCard.load(conn); // load own VCard
* vCard.load(conn, "joe@foo.bar"); // load someone's VCard
* </pre>
*
* @author Kirill Maximov (kir@maxkir.com)
*/
public class VCard extends IQ {
/**
* Phone types:
* VOICE?, FAX?, PAGER?, MSG?, CELL?, VIDEO?, BBS?, MODEM?, ISDN?, PCS?, PREF?
*/
private Map homePhones = new HashMap();
private Map workPhones = new HashMap();
/**
* Address types:
* POSTAL?, PARCEL?, (DOM | INTL)?, PREF?, POBOX?, EXTADR?, STREET?, LOCALITY?,
* REGION?, PCODE?, CTRY?
*/
private Map homeAddr = new HashMap();
private Map workAddr = new HashMap();
private String firstName;
private String lastName;
private String middleName;
private String emailHome;
private String emailWork;
private String organization;
private String organizationUnit;
/**
* Such as DESC ROLE GEO etc.. see JEP-0054
*/
private Map otherSimpleFields = new HashMap();
public VCard() {
}
/**
* Set generic VCard field.
*
* @param field value of field. Possible values: NICKNAME, PHOTO, BDAY, JABBERID, MAILER, TZ,
* GEO, TITLE, ROLE, LOGO, NOTE, PRODID, REV, SORT-STRING, SOUND, UID, URL, DESC.
*/
public String getField(String field) {
return (String) otherSimpleFields.get(field);
}
/**
* Set generic VCard field.
*
* @param value value of field
* @param field field to set. See {@link #getField(String)}
* @see #getField(String)
*/
public void setField(String field, String value) {
otherSimpleFields.put(field, value);
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getMiddleName() {
return middleName;
}
public void setMiddleName(String middleName) {
this.middleName = middleName;
}
public String getNickName() {
return (String) otherSimpleFields.get("NICKNAME");
}
public void setNickName(String nickName) {
otherSimpleFields.put("NICKNAME", nickName);
}
public String getEmailHome() {
return emailHome;
}
public void setEmailHome(String email) {
this.emailHome = email;
}
public String getEmailWork() {
return emailWork;
}
public void setEmailWork(String emailWork) {
this.emailWork = emailWork;
}
public String getJabberId() {
return (String) otherSimpleFields.get("JABBERID");
}
public void setJabberId(String jabberId) {
otherSimpleFields.put("JABBERID", jabberId);
}
public String getOrganization() {
return organization;
}
public void setOrganization(String organization) {
this.organization = organization;
}
public String getOrganizationUnit() {
return organizationUnit;
}
public void setOrganizationUnit(String organizationUnit) {
this.organizationUnit = organizationUnit;
}
/**
* Get home address field
*
* @param addrField one of POSTAL, PARCEL, (DOM | INTL), PREF, POBOX, EXTADR, STREET,
* LOCALITY, REGION, PCODE, CTRY
*/
public String getAddressFieldHome(String addrField) {
return (String) homeAddr.get(addrField);
}
/**
* Set home address field
*
* @param addrField one of POSTAL, PARCEL, (DOM | INTL), PREF, POBOX, EXTADR, STREET,
* LOCALITY, REGION, PCODE, CTRY
*/
public void setAddressFieldHome(String addrField, String value) {
homeAddr.put(addrField, value);
}
/**
* Get work address field
*
* @param addrField one of POSTAL, PARCEL, (DOM | INTL), PREF, POBOX, EXTADR, STREET,
* LOCALITY, REGION, PCODE, CTRY
*/
public String getAddressFieldWork(String addrField) {
return (String) workAddr.get(addrField);
}
/**
* Set work address field
*
* @param addrField one of POSTAL, PARCEL, (DOM | INTL), PREF, POBOX, EXTADR, STREET,
* LOCALITY, REGION, PCODE, CTRY
*/
public void setAddressFieldWork(String addrField, String value) {
workAddr.put(addrField, value);
}
/**
* Set home phone number
*
* @param phoneType one of VOICE, FAX, PAGER, MSG, CELL, VIDEO, BBS, MODEM, ISDN, PCS, PREF
* @param phoneNum phone number
*/
public void setPhoneHome(String phoneType, String phoneNum) {
homePhones.put(phoneType, phoneNum);
}
/**
* Get home phone number
*
* @param phoneType one of VOICE, FAX, PAGER, MSG, CELL, VIDEO, BBS, MODEM, ISDN, PCS, PREF
*/
public String getPhoneHome(String phoneType) {
return (String) homePhones.get(phoneType);
}
/**
* Set work phone number
*
* @param phoneType one of VOICE, FAX, PAGER, MSG, CELL, VIDEO, BBS, MODEM, ISDN, PCS, PREF
* @param phoneNum phone number
*/
public void setPhoneWork(String phoneType, String phoneNum) {
workPhones.put(phoneType, phoneNum);
}
/**
* Get work phone number
*
* @param phoneType one of VOICE, FAX, PAGER, MSG, CELL, VIDEO, BBS, MODEM, ISDN, PCS, PREF
*/
public String getPhoneWork(String phoneType) {
return (String) workPhones.get(phoneType);
}
/**
* Save this vCard for the user connected by 'connection'. Connection should be authenticated
* and not anonymous.<p>
* <p/>
* NOTE: the method is asynchronous and does not wait for the returned value.
*/
public void save(XMPPConnection connection) {
checkAuthenticated(connection);
setType(IQ.Type.SET);
setFrom(connection.getUser());
connection.sendPacket(this);
}
/**
* Load VCard information for a connected user. Connection should be authenticated
* and not anonymous.
*/
public void load(XMPPConnection connection) throws XMPPException {
checkAuthenticated(connection);
setFrom(connection.getUser());
doLoad(connection, connection.getUser());
}
/**
* Load VCard information for a given user. Connection should be authenticated and not anonymous.
*/
public void load(XMPPConnection connection, String user) throws XMPPException {
checkAuthenticated(connection);
setTo(user);
doLoad(connection, user);
}
private void doLoad(XMPPConnection connection, String user) throws XMPPException {
setType(Type.GET);
PacketCollector collector = connection.createPacketCollector(
new PacketIDFilter(getPacketID()));
connection.sendPacket(this);
VCard result = null;
try {
result = (VCard) collector.nextResult(SmackConfiguration.getPacketReplyTimeout());
if (result == null) {
throw new XMPPException(new XMPPError(408, "Timeout getting VCard information"));
}
if (result.getError() != null) {
throw new XMPPException(result.getError());
}
} catch (ClassCastException e) {
System.out.println("No VCard for " + user);
}
copyFieldsFrom(result);
}
public String getChildElementXML() {
StringBuffer sb = new StringBuffer();
new VCardWriter(sb).write();
return sb.toString();
}
private void copyFieldsFrom(VCard result) {
if (result == null) result = new VCard();
Field[] fields = VCard.class.getDeclaredFields();
for (int i = 0; i < fields.length; i++) {
Field field = fields[i];
if (field.getDeclaringClass() == VCard.class &&
!Modifier.isFinal(field.getModifiers())) {
try {
field.setAccessible(true);
field.set(this, field.get(result));
} catch (IllegalAccessException e) {
throw new RuntimeException("This cannot happen:" + field, e);
}
}
}
}
private void checkAuthenticated(XMPPConnection connection) {
if (connection == null) {
new IllegalArgumentException("No connection was provided");
}
if (!connection.isAuthenticated()) {
new IllegalArgumentException("Connection is not authenticated");
}
if (connection.isAnonymous()) {
new IllegalArgumentException("Connection cannot be anonymous");
}
}
private boolean hasContent() {
//noinspection OverlyComplexBooleanExpression
return hasNameField()
|| hasOrganizationFields()
|| emailHome != null
|| emailWork != null
|| otherSimpleFields.size() > 0
|| homeAddr.size() > 0
|| homePhones.size() > 0
|| workAddr.size() > 0
|| workPhones.size() > 0
;
}
private boolean hasNameField() {
return firstName != null || lastName != null || middleName != null;
}
private boolean hasOrganizationFields() {
return organization != null || organizationUnit != null;
}
// Used in tests:
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
final VCard vCard = (VCard) o;
if (emailHome != null ? !emailHome.equals(vCard.emailHome) : vCard.emailHome != null) {
return false;
}
if (emailWork != null ? !emailWork.equals(vCard.emailWork) : vCard.emailWork != null) {
return false;
}
if (firstName != null ? !firstName.equals(vCard.firstName) : vCard.firstName != null) {
return false;
}
if (!homeAddr.equals(vCard.homeAddr)) {
return false;
}
if (!homePhones.equals(vCard.homePhones)) {
return false;
}
if (lastName != null ? !lastName.equals(vCard.lastName) : vCard.lastName != null) {
return false;
}
if (middleName != null ? !middleName.equals(vCard.middleName) : vCard.middleName != null) {
return false;
}
if (organization != null ?
!organization.equals(vCard.organization) : vCard.organization != null) {
return false;
}
if (organizationUnit != null ?
!organizationUnit.equals(vCard.organizationUnit) : vCard.organizationUnit != null) {
return false;
}
if (!otherSimpleFields.equals(vCard.otherSimpleFields)) {
return false;
}
if (!workAddr.equals(vCard.workAddr)) {
return false;
}
if (!workPhones.equals(vCard.workPhones)) {
return false;
}
return true;
}
public int hashCode() {
int result;
result = homePhones.hashCode();
result = 29 * result + workPhones.hashCode();
result = 29 * result + homeAddr.hashCode();
result = 29 * result + workAddr.hashCode();
result = 29 * result + (firstName != null ? firstName.hashCode() : 0);
result = 29 * result + (lastName != null ? lastName.hashCode() : 0);
result = 29 * result + (middleName != null ? middleName.hashCode() : 0);
result = 29 * result + (emailHome != null ? emailHome.hashCode() : 0);
result = 29 * result + (emailWork != null ? emailWork.hashCode() : 0);
result = 29 * result + (organization != null ? organization.hashCode() : 0);
result = 29 * result + (organizationUnit != null ? organizationUnit.hashCode() : 0);
result = 29 * result + otherSimpleFields.hashCode();
return result;
}
public String toString() {
return getChildElementXML();
}
//==============================================================
private class VCardWriter {
private final StringBuffer sb;
VCardWriter(StringBuffer sb) {
this.sb = sb;
}
public void write() {
appendTag("vCard", "xmlns", "vcard-temp", hasContent(), new ContentBuilder() {
public void addTagContent() {
buildActualContent();
}
});
}
private void buildActualContent() {
if (hasNameField()) {
appendFN();
appendN();
}
appendOrganization();
appendGenericFields();
appendEmail(emailWork, "WORK");
appendEmail(emailHome, "HOME");
appendPhones(workPhones, "WORK");
appendPhones(homePhones, "HOME");
appendAddress(workAddr, "WORK");
appendAddress(homeAddr, "HOME");
}
private void appendEmail(final String email, final String type) {
if (email != null) {
appendTag("EMAIL", true, new ContentBuilder() {
public void addTagContent() {
appendEmptyTag(type);
appendEmptyTag("INTERNET");
appendEmptyTag("PREF");
appendTag("USERID", email);
}
});
}
}
private void appendPhones(Map phones, final String code) {
Iterator it = phones.entrySet().iterator();
while (it.hasNext()) {
final Map.Entry entry = (Map.Entry) it.next();
appendTag("TEL", true, new ContentBuilder() {
public void addTagContent() {
appendEmptyTag(entry.getKey());
appendEmptyTag(code);
appendTag("NUMBER", (String) entry.getValue());
}
});
}
}
private void appendAddress(final Map addr, final String code) {
if (addr.size() > 0) {
appendTag("ADR", true, new ContentBuilder() {
public void addTagContent() {
appendEmptyTag(code);
Iterator it = addr.entrySet().iterator();
while (it.hasNext()) {
final Map.Entry entry = (Map.Entry) it.next();
appendTag((String) entry.getKey(), (String) entry.getValue());
}
}
});
}
}
private void appendEmptyTag(Object tag) {
sb.append('<').append(tag).append("/>");
}
private void appendGenericFields() {
Iterator it = otherSimpleFields.entrySet().iterator();
while (it.hasNext()) {
Map.Entry entry = (Map.Entry) it.next();
appendTag(entry.getKey().toString(), (String) entry.getValue());
}
}
private void appendOrganization() {
if (hasOrganizationFields()) {
appendTag("ORG", true, new ContentBuilder() {
public void addTagContent() {
appendTag("ORGNAME", organization);
appendTag("ORGUNIT", organizationUnit);
}
});
}
}
private void appendField(String tag) {
String value = (String) otherSimpleFields.get(tag);
appendTag(tag, value);
}
private void appendFN() {
final ContentBuilder contentBuilder = new ContentBuilder() {
public void addTagContent() {
if (firstName != null) {
sb.append(firstName + ' ');
}
if (middleName != null) {
sb.append(middleName + ' ');
}
if (lastName != null) {
sb.append(lastName);
}
}
};
appendTag("FN", true, contentBuilder);
}
private void appendN() {
appendTag("N", true, new ContentBuilder() {
public void addTagContent() {
appendTag("FAMILY", lastName);
appendTag("GIVEN", firstName);
appendTag("MIDDLE", middleName);
}
});
}
private void appendTag(String tag, String attr, String attrValue, boolean hasContent,
ContentBuilder builder) {
sb.append('<').append(tag);
if (attr != null) {
sb.append(' ').append(attr).append('=').append('\'').append(attrValue).append('\'');
}
if (hasContent) {
sb.append('>');
builder.addTagContent();
sb.append("</").append(tag).append(">\n");
} else {
sb.append("/>\n");
}
}
private void appendTag(String tag, boolean hasContent, ContentBuilder builder) {
appendTag(tag, null, null, hasContent, builder);
}
private void appendTag(String tag, final String tagText) {
if (tagText == null) return;
final ContentBuilder contentBuilder = new ContentBuilder() {
public void addTagContent() {
sb.append(tagText.trim());
}
};
appendTag(tag, true, contentBuilder);
}
}
//==============================================================
private interface ContentBuilder {
void addTagContent();
}
//==============================================================
}

View file

@ -0,0 +1,132 @@
/**
* $RCSfile$
* $Revision$
* $Date$
*
* Copyright 2003-2004 Jive Software.
*
* All rights reserved. Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jivesoftware.smackx.packet;
import org.jivesoftware.smack.packet.IQ;
/**
* A Version IQ packet, which is used by XMPP clients to discover version information
* about the software running at another entity's JID.<p>
*
* An example to discover the version of the server:
* <pre>
* // Request the version from the server.
* Version versionRequest = new Version();
* timeRequest.setType(IQ.Type.GET);
* timeRequest.setTo("example.com");
*
* // Create a packet collector to listen for a response.
* PacketCollector collector = con.createPacketCollector(
* new PacketIDFilter(versionRequest.getPacketID()));
*
* con.sendPacket(versionRequest);
*
* // Wait up to 5 seconds for a result.
* IQ result = (IQ)collector.nextResult(5000);
* if (result != null && result.getType() == IQ.Type.RESULT) {
* Version versionResult = (Version)result;
* // Do something with result...
* }</pre><p>
*
* @author Gaston Dombiak
*/
public class Version extends IQ {
private String name;
private String version;
private String os;
/**
* Returns the natural-language name of the software. This property will always be
* present in a result.
*
* @return the natural-language name of the software.
*/
public String getName() {
return name;
}
/**
* Sets the natural-language name of the software. This message should only be
* invoked when parsing the XML and setting the property to a Version instance.
*
* @param name the natural-language name of the software.
*/
public void setName(String name) {
this.name = name;
}
/**
* Returns the specific version of the software. This property will always be
* present in a result.
*
* @return the specific version of the software.
*/
public String getVersion() {
return version;
}
/**
* Sets the specific version of the software. This message should only be
* invoked when parsing the XML and setting the property to a Version instance.
*
* @param version the specific version of the software.
*/
public void setVersion(String version) {
this.version = version;
}
/**
* Returns the operating system of the queried entity. This property will always be
* present in a result.
*
* @return the operating system of the queried entity.
*/
public String getOs() {
return os;
}
/**
* Sets the operating system of the queried entity. This message should only be
* invoked when parsing the XML and setting the property to a Version instance.
*
* @param os operating system of the queried entity.
*/
public void setOs(String os) {
this.os = os;
}
public String getChildElementXML() {
StringBuffer buf = new StringBuffer();
buf.append("<query xmlns=\"jabber:iq:version\">");
if (name != null) {
buf.append("<name>").append(name).append("</name>");
}
if (version != null) {
buf.append("<version>").append(version).append("</version>");
}
if (os != null) {
buf.append("<os>").append(os).append("</os>");
}
buf.append("</query>");
return buf.toString();
}
}

View file

@ -0,0 +1,123 @@
/**
* $RCSfile$
* $Revision$
* $Date$
*
* Copyright 2003-2004 Jive Software.
*
* All rights reserved. Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jivesoftware.smackx.packet;
import java.util.*;
import org.jivesoftware.smack.packet.PacketExtension;
/**
* An XHTML sub-packet, which is used by XMPP clients to exchange formatted text. The XHTML
* extension is only a subset of XHTML 1.0.<p>
*
* The following link summarizes the requirements of XHTML IM:
* <a href="http://www.jabber.org/jeps/jep-0071.html#sect-id2598018">Valid tags</a>.<p>
*
* Warning: this is an non-standard protocol documented by
* <a href="http://www.jabber.org/jeps/jep-0071.html">JEP-71</a>. Because this is a
* non-standard protocol, it is subject to change.
*
* @author Gaston Dombiak
*/
public class XHTMLExtension implements PacketExtension {
private List bodies = new ArrayList();
/**
* Returns the XML element name of the extension sub-packet root element.
* Always returns "html"
*
* @return the XML element name of the packet extension.
*/
public String getElementName() {
return "html";
}
/**
* Returns the XML namespace of the extension sub-packet root element.
* According the specification the namespace is always "http://jabber.org/protocol/xhtml-im"
*
* @return the XML namespace of the packet extension.
*/
public String getNamespace() {
return "http://jabber.org/protocol/xhtml-im";
}
/**
* Returns the XML representation of a XHTML extension according the specification.
*
* Usually the XML representation will be inside of a Message XML representation like
* in the following example:
* <pre>
* &lt;message id="MlIpV-4" to="gato1@gato.home" from="gato3@gato.home/Smack"&gt;
* &lt;subject&gt;Any subject you want&lt;/subject&gt;
* &lt;body&gt;This message contains something interesting.&lt;/body&gt;
* &lt;html xmlns="http://jabber.org/protocol/xhtml-im"&gt;
* &lt;body&gt;&lt;p style='font-size:large'&gt;This message contains something &lt;em&gt;interesting&lt;/em&gt;.&lt;/p&gt;&lt;/body&gt;
* &lt;/html&gt;
* &lt;/message&gt;
* </pre>
*
*/
public String toXML() {
StringBuffer buf = new StringBuffer();
buf.append("<").append(getElementName()).append(" xmlns=\"").append(getNamespace()).append(
"\">");
// Loop through all the bodies and append them to the string buffer
for (Iterator i = getBodies(); i.hasNext();) {
buf.append((String) i.next());
}
buf.append("</").append(getElementName()).append(">");
return buf.toString();
}
/**
* Returns an Iterator for the bodies in the packet.
*
* @return an Iterator for the bodies in the packet.
*/
public Iterator getBodies() {
synchronized (bodies) {
return Collections.unmodifiableList(new ArrayList(bodies)).iterator();
}
}
/**
* Adds a body to the packet.
*
* @param body the body to add.
*/
public void addBody(String body) {
synchronized (bodies) {
bodies.add(body);
}
}
/**
* Returns a count of the bodies in the XHTML packet.
*
* @return the number of bodies in the XHTML packet.
*/
public int getBodiesCount() {
return bodies.size();
}
}

View file

@ -0,0 +1 @@
<body>XML packets that are part of the XMPP extension protocols.</body>