diff --git a/source/org/jivesoftware/smackx/Form.java b/source/org/jivesoftware/smackx/Form.java new file mode 100644 index 000000000..ca129fceb --- /dev/null +++ b/source/org/jivesoftware/smackx/Form.java @@ -0,0 +1,297 @@ +/** +* $RCSfile$ +* $Revision$ +* $Date$ +* +* Copyright (C) 2002-2003 Jive Software. All rights reserved. +* ==================================================================== +* The Jive Software License (based on Apache Software License, Version 1.1) +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* 1. Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* +* 2. Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in +* the documentation and/or other materials provided with the +* distribution. +* +* 3. The end-user documentation included with the redistribution, +* if any, must include the following acknowledgment: +* "This product includes software developed by +* Jive Software (http://www.jivesoftware.com)." +* Alternately, this acknowledgment may appear in the software itself, +* if and wherever such third-party acknowledgments normally appear. +* +* 4. The names "Smack" and "Jive Software" must not be used to +* endorse or promote products derived from this software without +* prior written permission. For written permission, please +* contact webmaster@jivesoftware.com. +* +* 5. Products derived from this software may not be called "Smack", +* nor may "Smack" appear in their name, without prior written +* permission of Jive Software. +* +* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED +* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL JIVE SOFTWARE OR +* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF +* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT +* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +* SUCH DAMAGE. +* ==================================================================== +*/ + +package org.jivesoftware.smackx; + +import java.util.*; + +import org.jivesoftware.smack.packet.*; +import org.jivesoftware.smackx.packet.DataForm; + +/** + * Represents a Form for gathering data. The form could be of the following types: + * + * + * Depending of the form's type different operations are available. For example, if the form + * is of type "submit", it's not possible to add a new Field to the form. + * + * @author Gaston Dombiak + */ +public class Form { + + private DataForm dataForm; + + /** + * Returns a new ReportedData if the packet is used for gathering data and includes an + * extension that matches the elementName and namespace "x","jabber:x:data". + * + * @param packet the packet used for gathering data. + */ + public static Form getFormFrom(Packet packet) { + // Check if the packet includes the DataForm extension + PacketExtension packetExtension = packet.getExtension("x","jabber:x:data"); + if (packetExtension != null) { + // Check if the existing DataForm is not a result of a search + DataForm dataForm = (DataForm) packetExtension; + if (dataForm.getReportedData() == null) + return new Form(dataForm); + } + // Otherwise return null + return null; + } + + /** + * Creates a new Form that will wrap an existing DataForm. The wrapped DataForm must be + * used for gathering data. + * + * @param dataForm the data form used for gathering data. + */ + private Form(DataForm dataForm) { + this.dataForm = dataForm; + } + + /** + * Creates a new Form of a given type from scratch.

+ * + * Possible form types are: + *

+ * + * @param type the form's type (e.g. form, submit,cancel,result). + */ + public Form(String type) { + this.dataForm = new DataForm(type); + } + + /** + * Adds a new field to complete as part of the form. + * + * @param field the field to complete. + */ + public void addField(FormField field) { + if (!isFormType()) { + throw new IllegalStateException("Cannot add fields if the form is not of type \"form\""); + } + dataForm.addField(field); + } + + /** + * Adds a new answer as part of the form. The answer to add is a FormField whose variable + * and value attributes are completed. + * + * @param variable the variable that was completed. + * @param value the value that was answered. + */ + public void addAnswer(String variable, String value) { + if (!isSubmitType()) { + throw new IllegalStateException("Cannot add fields if the form is not of type \"submit\""); + } + FormField field = new FormField(); + field.setVariable(variable); + field.addValue(value); + dataForm.addField(field); + } + + /** + * Adds a new answer as part of the form. The answer to add is a FormField whose variable + * and values attributes are completed. + * + * @param variable the variable that was completed. + * @param values the values that were answered. + */ + public void addAnswer(String variable, List values) { + if (!isSubmitType()) { + throw new IllegalStateException("Cannot add fields if the form is not of type \"submit\""); + } + FormField field = new FormField(); + field.setVariable(variable); + field.addValues(values); + dataForm.addField(field); + } + + /** + * 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() { + return dataForm.getFields(); + } + + + /** + * Returns the instructions that explain how to fill out the form and what the form is about. + * + * @return instructions that explain how to fill out the form. + */ + public String getInstructions() { + return dataForm.getInstructions(); + } + + + /** + * Returns the description of the data. It is similar to the title on a web page or an X + * window. You can put a on either a form to fill out, or a set of data results. + * + * @return description of the data. + */ + public String getTitle() { + return dataForm.getTitle(); + } + + + /** + * 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 -> Indicates a form to fill out.</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 dataForm.getType(); + } + + + /** + * Sets instructions that explain how to fill out the form and what the form is about. + * + * @param instructions instructions that explain how to fill out the form. + */ + public void setInstructions(String instructions) { + dataForm.setInstructions(instructions); + } + + + /** + * 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) { + dataForm.setTitle(title); + } + + /** + * Returns the wrapped DataForm. + * + * @return the wrapped DataForm. + */ + DataForm getDataForm() { + return dataForm; + } + + /** + * Returns true if the form is a form to fill out. + * + * @return if the form is a form to fill out. + */ + private boolean isFormType() { + return DataForm.TYPE_FORM.equals(dataForm.getType()); + } + + /** + * Returns true if the form is a form to submit. + * + * @return if the form is a form to submit. + */ + private boolean isSubmitType() { + return DataForm.TYPE_SUBMIT.equals(dataForm.getType()); + } + + /** + * Returns a new Form to submit the completed values. The new Form will include the hidden + * fields of the original form. + * + * @return a Form to submit the completed values. + */ + public Form createAnswerForm() { + if (!isFormType()) { + throw new IllegalStateException("Only forms of type \"form\" could be answered"); + } + // Create a new Form + Form form = new Form(DataForm.TYPE_SUBMIT); + // Copy the hidden fields to the new form + for (Iterator fields=getFields(); fields.hasNext();) { + FormField field = (FormField)fields.next(); + if (FormField.TYPE_HIDDEN.equals(field.getType())) { + // Since a hidden field could have many values we need to collect them in a list + List values = new ArrayList(); + for (Iterator it=field.getValues();it.hasNext();) { + values.add((String)it.next()); + } + form.addAnswer(field.getVariable(), values); + } + } + return form; + } + +} diff --git a/source/org/jivesoftware/smackx/FormField.java b/source/org/jivesoftware/smackx/FormField.java new file mode 100644 index 000000000..046d459e2 --- /dev/null +++ b/source/org/jivesoftware/smackx/FormField.java @@ -0,0 +1,362 @@ +/** +* $RCSfile$ +* $Revision$ +* $Date$ +* +* Copyright (C) 2002-2003 Jive Software. All rights reserved. +* ==================================================================== +* The Jive Software License (based on Apache Software License, Version 1.1) +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* 1. Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* +* 2. Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in +* the documentation and/or other materials provided with the +* distribution. +* +* 3. The end-user documentation included with the redistribution, +* if any, must include the following acknowledgment: +* "This product includes software developed by +* Jive Software (http://www.jivesoftware.com)." +* Alternately, this acknowledgment may appear in the software itself, +* if and wherever such third-party acknowledgments normally appear. +* +* 4. The names "Smack" and "Jive Software" must not be used to +* endorse or promote products derived from this software without +* prior written permission. For written permission, please +* contact webmaster@jivesoftware.com. +* +* 5. Products derived from this software may not be called "Smack", +* nor may "Smack" appear in their name, without prior written +* permission of Jive Software. +* +* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED +* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL JIVE SOFTWARE OR +* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF +* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT +* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +* SUCH DAMAGE. +* ==================================================================== +*/ + +package org.jivesoftware.smackx; + +import java.util.*; + +/** + * Represents a field of a form. The field could be used to represent a question to complete, + * a completed question or a data returned from a search. The exact interpretation of the field + * depends on the context where the field is used. + * + * @author Gaston Dombiak + */ +public class FormField { + public static final String TYPE_BOOLEAN = "boolean"; + public static final String TYPE_FIXED = "fixed"; + public static final String TYPE_HIDDEN = "hidden"; + public static final String TYPE_JID_MULTI = "jid-multi"; + public static final String TYPE_JID_SINGLE = "jid-single"; + public static final String TYPE_LIST_MULTI = "list-multi"; + public static final String TYPE_LIST_SINGLE = "list-single"; + public static final String TYPE_TEXT_MULTI = "text-multi"; + public static final String TYPE_TEXT_PRIVATE = "text-private"; + public static final String TYPE_TEXT_SINGLE = "text-single"; + + private String description; + private boolean required = false; + private String label; + private String variable; + private String type; + private List options = new ArrayList(); + private List values = new ArrayList(); + + /** + * Returns a description that provides extra clarification about the question. This information + * could be presented to the user either in tool-tip, help button, or as a section of text + * before the question.<p> + * + * If the question is of type FIXED then the description should remain empty. + * + * @return description that provides extra clarification about the question. + */ + public String getDescription() { + return description; + } + + /** + * Returns the label of the question which should give enough information to the user to + * fill out the form. + * + * @return label of the question. + */ + public String getLabel() { + return label; + } + + /** + * Returns an Iterator for the available options that the user has in order to answer + * the question. + * + * @return Iterator for the available options. + */ + public Iterator getOptions() { + synchronized (options) { + return Collections.unmodifiableList(new ArrayList(options)).iterator(); + } + } + + /** + * Returns true if the question must be answered in order to complete the questionnaire. + * + * @return true if the question must be answered in order to complete the questionnaire. + */ + public boolean isRequired() { + return required; + } + + /** + * Returns an indicative of the format for the data to answer. Valid formats are: + * + * <ul> + * <li>text-single -> single line or word of text + * <li>text-private -> instead of showing the user what they typed, you show ***** to + * protect it + * <li>text-multi -> multiple lines of text entry + * <li>list-single -> given a list of choices, pick one + * <li>list-multi -> given a list of choices, pick one or more + * <li>boolean -> 0 or 1, true or false, yes or no. Default value is 0 + * <li>fixed -> fixed for putting in text to show sections, or just advertise your web + * site in the middle of the form + * <li>hidden -> is not given to the user at all, but returned with the questionnaire + * <li>jid-single -> Jabber ID - choosing a JID from your roster, and entering one based + * on the rules for a JID. + * <li>jid-multi -> multiple entries for JIDs + * </ul> + * + * @return format for the data to answer. + */ + public String getType() { + return type; + } + + /** + * Returns an Iterator for the default values of the question if the question is part + * of a form to fill out. Otherwise, returns an Iterator for the answered values of + * the question. + * + * @return an Iterator for the default values or answered values of the question. + */ + public Iterator getValues() { + synchronized (values) { + return Collections.unmodifiableList(new ArrayList(values)).iterator(); + } + } + + /** + * Returns the variable name that the question is filling out. + * + * @return the variable name of the question. + */ + public String getVariable() { + return variable; + } + + /** + * Sets a description that provides extra clarification about the question. This information + * could be presented to the user either in tool-tip, help button, or as a section of text + * before the question.<p> + * + * If the question is of type FIXED then the description should remain empty. + * + * @param description provides extra clarification about the question. + */ + public void setDescription(String description) { + this.description = description; + } + + /** + * Sets the label of the question which should give enough information to the user to + * fill out the form. + * + * @param label the label of the question. + */ + public void setLabel(String label) { + this.label = label; + } + + /** + * Sets if the question must be answered in order to complete the questionnaire. + * + * @param required if the question must be answered in order to complete the questionnaire. + */ + public void setRequired(boolean required) { + this.required = required; + } + + /** + * Sets an indicative of the format for the data to answer. Valid formats are: + * + * <ul> + * <li>text-single -> single line or word of text + * <li>text-private -> instead of showing the user what they typed, you show ***** to + * protect it + * <li>text-multi -> multiple lines of text entry + * <li>list-single -> given a list of choices, pick one + * <li>list-multi -> given a list of choices, pick one or more + * <li>boolean -> 0 or 1, true or false, yes or no. Default value is 0 + * <li>fixed -> fixed for putting in text to show sections, or just advertise your web + * site in the middle of the form + * <li>hidden -> is not given to the user at all, but returned with the questionnaire + * <li>jid-single -> Jabber ID - choosing a JID from your roster, and entering one based + * on the rules for a JID. + * <li>jid-multi -> multiple entries for JIDs + * </ul> + * + * @param type an indicative of the format for the data to answer. + */ + public void setType(String type) { + this.type = type; + } + + /** + * Returns the variable name that the question is filling out. + * + * @param variable the variable name of the question. + */ + public void setVariable(String variable) { + this.variable = variable; + } + + /** + * Adds a default value to the question if the question is part of a form to fill out. + * Otherwise, adds an answered value to the question. + * + * @param value a default value or an answered value of the question. + */ + public void addValue(String value) { + synchronized (values) { + values.add(value); + } + } + + /** + * Adds a default values to the question if the question is part of a form to fill out. + * Otherwise, adds an answered values to the question. + * + * @param values default values or an answered values of the question. + */ + public void addValues(List newValues) { + synchronized (values) { + values.addAll(newValues); + } + } + + /** + * Adss an available options to the question that the user has in order to answer + * the question. + * + * @param option a new available option for the question. + */ + public void addOption(Option option) { + synchronized (options) { + options.add(option); + } + } + + public String toXML() { + StringBuffer buf = new StringBuffer(); + buf.append("<field"); + // Add attributes + if (getLabel() != null) { + buf.append(" label=\"").append(getLabel()).append("\""); + } + if (getVariable() != null) { + buf.append(" var=\"").append(getVariable()).append("\""); + } + if (getType() != null) { + buf.append(" type=\"").append(getType()).append("\""); + } + buf.append(">"); + // Add elements + if (getDescription() != null) { + buf.append("<desc>").append(getDescription()).append("</desc>"); + } + if (isRequired()) { + buf.append("<required/>"); + } + // Loop through all the values and append them to the string buffer + for (Iterator i = getValues(); i.hasNext();) { + buf.append("<value>").append(i.next()).append("</value>"); + } + // Loop through all the values and append them to the string buffer + for (Iterator i = getOptions(); i.hasNext();) { + buf.append(((Option)i.next()).toXML()); + } + buf.append("</field>"); + return buf.toString(); + } + + /** + * + * Represents the available option of a given FormField. + * + * @author Gaston Dombiak + */ + public static class Option { + private String label; + private String value; + + public Option(String value) { + this.value = value; + } + + public Option(String label, String value) { + this.label = label; + this.value = value; + } + + /** + * Returns the label that represents the option. + * + * @return the label that represents the option. + */ + public String getLabel() { + return label; + } + + /** + * Returns the value of the option. + * + * @return the value of the option. + */ + public String getValue() { + return value; + } + + public String toXML() { + StringBuffer buf = new StringBuffer(); + buf.append("<option"); + // Add attribute + if (getLabel() != null) { + buf.append(" label=\"").append(getLabel()).append("\""); + } + buf.append(">"); + // Add element + buf.append("<value>").append(getValue()).append("</value>"); + + buf.append("</option>"); + return buf.toString(); + } + } +} diff --git a/source/org/jivesoftware/smackx/MultiUserChat.java b/source/org/jivesoftware/smackx/MultiUserChat.java new file mode 100644 index 000000000..fca9d199e --- /dev/null +++ b/source/org/jivesoftware/smackx/MultiUserChat.java @@ -0,0 +1,422 @@ +/** + * $RCSfile$ + * $Revision$ + * $Date$ + * + * Copyright (C) 2002-2003 Jive Software. All rights reserved. + * ==================================================================== + * The Jive Software License (based on Apache Software License, Version 1.1) + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by + * Jive Software (http://www.jivesoftware.com)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Smack" and "Jive Software" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please + * contact webmaster@jivesoftware.com. + * + * 5. Products derived from this software may not be called "Smack", + * nor may "Smack" appear in their name, without prior written + * permission of Jive Software. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL JIVE SOFTWARE OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + */ +package org.jivesoftware.smackx; + +import java.util.*; + +import org.jivesoftware.smack.*; +import org.jivesoftware.smack.filter.*; +import org.jivesoftware.smack.packet.*; +import org.jivesoftware.smackx.packet.*; + +/** + * A MultiUserChat is a conversation that takes place among many users in a virtual + * room. A room could have many occupants with different affiliation and roles. + * Possible affiliatons are "owner", "admin", "member", and "outcast". Possible roles + * are "moderator", "participant", and "visitor". Each role and affiliation guarantees + * different privileges (e.g. Send messages to all occupants, Kick participants and visitors, + * Grant voice, Edit member list, etc.). + * + * @author Gaston Dombiak + */ +public class MultiUserChat { + + private XMPPConnection connection; + private String room; + private String nickname = null; + private boolean joined = false; + private List participants = new ArrayList(); + + private PacketFilter presenceFilter; + private PacketFilter messageFilter; + private PacketCollector messageCollector; + + public MultiUserChat(XMPPConnection connection, String room) { + this.connection = connection; + this.room = room; + // Create a collector for all incoming messages. + messageFilter = + new AndFilter(new FromContainsFilter(room), new PacketTypeFilter(Message.class)); + messageFilter = new AndFilter(messageFilter, new PacketFilter() { + public boolean accept(Packet packet) { + Message msg = (Message) packet; + return msg.getType() == Message.Type.GROUP_CHAT; + } + }); + messageCollector = connection.createPacketCollector(messageFilter); + // Create a listener for all presence updates. + presenceFilter = + new AndFilter(new FromContainsFilter(room), new PacketTypeFilter(Presence.class)); + connection.addPacketListener(new PacketListener() { + public void processPacket(Packet packet) { + Presence presence = (Presence) packet; + String from = presence.getFrom(); + if (presence.getType() == Presence.Type.AVAILABLE) { + synchronized (participants) { + if (!participants.contains(from)) { + participants.add(from); + } + } + } + else if (presence.getType() == Presence.Type.UNAVAILABLE) { + synchronized (participants) { + participants.remove(from); + } + } + } + }, presenceFilter); + } + + /** + * Returns the name of the room this GroupChat object represents. + * + * @return the groupchat room name. + */ + public String getRoom() { + return room; + } + + public void join(String nickname) throws XMPPException { + join(nickname, SmackConfiguration.getPacketReplyTimeout(), null, -1, -1, -1, null); + } + + public void join(String nickname, String password) throws XMPPException { + join(nickname, SmackConfiguration.getPacketReplyTimeout(), password, -1, -1, -1, null); + } + + // TODO Review protocol (too many params). Use setters or history class? + public synchronized void join( + String nickname, + long timeout, + String password, + int maxchars, + int maxstanzas, + int seconds, + Date since) + throws XMPPException { + if (nickname == null || nickname.equals("")) { + throw new IllegalArgumentException("Nickname must not be null or blank."); + } + // If we've already joined the room, leave it before joining under a new + // nickname. + if (joined) { + leave(); + } + // We join a room by sending a presence packet where the "to" + // field is in the form "roomName@service/nickname" + Presence joinPresence = new Presence(Presence.Type.AVAILABLE); + joinPresence.setTo(room + "/" + nickname); + + // Indicate the the client supports MUC + MUCInitialPresence mucInitialPresence = new MUCInitialPresence(); + if (password != null) { + mucInitialPresence.setPassword(password); + } + if (maxchars > -1 || maxstanzas > -1 || seconds > -1 || since != null) { + MUCInitialPresence.History history = new MUCInitialPresence.History(); + if (maxchars > -1) { + history.setMaxChars(maxchars); + } + if (maxstanzas > -1) { + history.setMaxStanzas(maxstanzas); + } + if (seconds > -1) { + history.setSeconds(seconds); + } + if (since != null) { + history.setSince(since); + } + mucInitialPresence.setHistory(history); + } + joinPresence.addExtension(mucInitialPresence); + + // Wait for a presence packet back from the server. + PacketFilter responseFilter = + new AndFilter( + new FromContainsFilter(room + "/" + nickname), + new PacketTypeFilter(Presence.class)); + PacketCollector response = connection.createPacketCollector(responseFilter); + // Send join packet. + connection.sendPacket(joinPresence); + // Wait up to a certain number of seconds for a reply. + Presence presence = (Presence) response.nextResult(timeout); + if (presence == null) { + throw new XMPPException("No response from server."); + } + else if (presence.getError() != null) { + throw new XMPPException(presence.getError()); + } + this.nickname = nickname; + joined = true; + } + + /** + * Returns true if currently in the group chat (after calling the {@link + * #join(String)} method. + * + * @return true if currently in the group chat room. + */ + public boolean isJoined() { + return joined; + } + + /** + * Leave the chat room. + */ + public synchronized void leave() { + // If not joined already, do nothing. + if (!joined) { + return; + } + // We leave a room by sending a presence packet where the "to" + // field is in the form "roomName@service/nickname" + Presence leavePresence = new Presence(Presence.Type.UNAVAILABLE); + leavePresence.setTo(room + "/" + nickname); + connection.sendPacket(leavePresence); + // Reset participant information. + participants = new ArrayList(); + nickname = null; + joined = false; + } + + /** + * Returns the room's configuration form that the room's owner can use. The configuration + * form allows to set the room's language, enable logging, specify room's type, etc.. + * + * @return the Form that contains the fields to complete together with the instrucions. + * @throws XMPPException if an error occurs asking the configuration form for the room. + */ + public Form getConfigurationForm() throws XMPPException { + MUCOwner iq = new MUCOwner(); + iq.setTo(room); + iq.setType(IQ.Type.GET); + + // Wait for a presence packet back from the server. + PacketFilter responseFilter = + new AndFilter( + new FromContainsFilter(room), + new PacketTypeFilter(IQ.class)); + PacketCollector response = connection.createPacketCollector(responseFilter); + // Request the configuration form to the server. + connection.sendPacket(iq); + // Wait up to a certain number of seconds for a reply. + IQ answer = (IQ) response.nextResult(SmackConfiguration.getPacketReplyTimeout()); + // Stop queuing results + response.cancel(); + + if (answer == null) { + throw new XMPPException("No response from server."); + } + else if (answer.getError() != null) { + throw new XMPPException(iq.getError()); + } + return Form.getFormFrom(answer); + } + + /** + * Sends the completed configuration form to the server. The room will be configured + * with the new settings defined in the form. + * + * @param form the form with the new settings. + * @throws XMPPException if an error occurs setting the new rooms' configuration. + */ + public void submitConfigurationForm(Form form) throws XMPPException { + MUCOwner iq = new MUCOwner(); + iq.setTo(room); + iq.setType(IQ.Type.SET); + iq.addExtension(form.getDataForm()); + + // Send the completed configuration form to the server. + connection.sendPacket(iq); + + // TODO Check for possible returned errors? permission errors? + // TODO Check that the form is of type "submit" + } + + /** + * Returns the nickname that was used to join the room, or <tt>null</tt> if not + * currently joined. + * + * @return the nickname currently being used. + */ + public String getNickname() { + return nickname; + } + + /** + * Returns the number of participants in the group chat.<p> + * + * Note: this value will only be accurate after joining the group chat, and + * may fluctuate over time. If you query this value directly after joining the + * group chat it may not be accurate, as it takes a certain amount of time for + * the server to send all presence packets to this client. + * + * @return the number of participants in the group chat. + */ + public int getParticipantCount() { + synchronized (participants) { + return participants.size(); + } + } + + /** + * Returns an Iterator (of Strings) for the list of fully qualified participants + * in the group chat. For example, "conference@chat.jivesoftware.com/SomeUser". + * Typically, a client would only display the nickname of the participant. To + * get the nickname from the fully qualified name, use the + * {@link org.jivesoftware.smack.util.StringUtils#parseResource(String)} method. + * Note: this value will only be accurate after joining the group chat, and may + * fluctuate over time. + * + * @return an Iterator for the participants in the group chat. + */ + public Iterator getParticipants() { + synchronized (participants) { + return Collections.unmodifiableList(new ArrayList(participants)).iterator(); + } + } + + /** + * Adds a packet listener that will be notified of any new Presence packets + * sent to the group chat. Using a listener is a suitable way to know when the list + * of participants should be re-loaded due to any changes. + * + * @param listener a packet listener that will be notified of any presence packets + * sent to the group chat. + */ + public void addParticipantListener(PacketListener listener) { + connection.addPacketListener(listener, presenceFilter); + } + + /** + * Sends a message to the chat room. + * + * @param text the text of the message to send. + * @throws XMPPException if sending the message fails. + */ + public void sendMessage(String text) throws XMPPException { + Message message = new Message(room, Message.Type.GROUP_CHAT); + message.setBody(text); + connection.sendPacket(message); + } + + /** + * Creates a new Message to send to the chat room. + * + * @return a new Message addressed to the chat room. + */ + public Message createMessage() { + return new Message(room, Message.Type.GROUP_CHAT); + } + + /** + * Sends a Message to the chat room. + * + * @param message the message. + * @throws XMPPException if sending the message fails. + */ + public void sendMessage(Message message) throws XMPPException { + connection.sendPacket(message); + } + + /** + * Polls for and returns the next message, or <tt>null</tt> if there isn't + * a message immediately available. This method provides significantly different + * functionalty than the {@link #nextMessage()} method since it's non-blocking. + * In other words, the method call will always return immediately, whereas the + * nextMessage method will return only when a message is available (or after + * a specific timeout). + * + * @return the next message if one is immediately available and + * <tt>null</tt> otherwise. + */ + public Message pollMessage() { + return (Message) messageCollector.pollResult(); + } + + /** + * Returns the next available message in the chat. The method call will block + * (not return) until a message is available. + * + * @return the next message. + */ + public Message nextMessage() { + return (Message) messageCollector.nextResult(); + } + + /** + * Returns the next available message in the chat. The method call will block + * (not return) until a packet is available or the <tt>timeout</tt> has elapased. + * If the timeout elapses without a result, <tt>null</tt> will be returned. + * + * @param timeout the maximum amount of time to wait for the next message. + * @return the next message, or <tt>null</tt> if the timeout elapses without a + * message becoming available. + */ + public Message nextMessage(long timeout) { + return (Message) messageCollector.nextResult(timeout); + } + + /** + * Adds a packet listener that will be notified of any new messages in the + * group chat. Only "group chat" messages addressed to this group chat will + * be delivered to the listener. If you wish to listen for other packets + * that may be associated with this group chat, you should register a + * PacketListener directly with the XMPPConnection with the appropriate + * PacketListener. + * + * @param listener a packet listener. + */ + public void addMessageListener(PacketListener listener) { + connection.addPacketListener(listener, messageFilter); + } +} diff --git a/source/org/jivesoftware/smackx/ReportedData.java b/source/org/jivesoftware/smackx/ReportedData.java new file mode 100644 index 000000000..3d7a28dc7 --- /dev/null +++ b/source/org/jivesoftware/smackx/ReportedData.java @@ -0,0 +1,267 @@ +/** +* $RCSfile$ +* $Revision$ +* $Date$ +* +* Copyright (C) 2002-2003 Jive Software. All rights reserved. +* ==================================================================== +* The Jive Software License (based on Apache Software License, Version 1.1) +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* 1. Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* +* 2. Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in +* the documentation and/or other materials provided with the +* distribution. +* +* 3. The end-user documentation included with the redistribution, +* if any, must include the following acknowledgment: +* "This product includes software developed by +* Jive Software (http://www.jivesoftware.com)." +* Alternately, this acknowledgment may appear in the software itself, +* if and wherever such third-party acknowledgments normally appear. +* +* 4. The names "Smack" and "Jive Software" must not be used to +* endorse or promote products derived from this software without +* prior written permission. For written permission, please +* contact webmaster@jivesoftware.com. +* +* 5. Products derived from this software may not be called "Smack", +* nor may "Smack" appear in their name, without prior written +* permission of Jive Software. +* +* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED +* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL JIVE SOFTWARE OR +* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF +* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT +* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +* SUCH DAMAGE. +* ==================================================================== +*/ + +package org.jivesoftware.smackx; + +import java.util.*; + +import org.jivesoftware.smack.packet.*; +import org.jivesoftware.smackx.packet.DataForm; + +/** + * Represents a set of data results returned as part of a search. The report is structured + * in columns and rows. + * + * @author Gaston Dombiak + */ +public class ReportedData { + + private List columns = new ArrayList(); + private List rows = new ArrayList(); + private String title = ""; + + /** + * Returns a new ReportedData if the packet is used for reporting data and includes an + * extension that matches the elementName and namespace "x","jabber:x:data". + * + * @param packet the packet used for reporting data. + */ + public static ReportedData getReportedDataFrom(Packet packet) { + // Check if the packet includes the DataForm extension + PacketExtension packetExtension = packet.getExtension("x","jabber:x:data"); + if (packetExtension != null) { + // Check if the existing DataForm is a result of a search + DataForm dataForm = (DataForm) packetExtension; + if (dataForm.getReportedData() != null) + return new ReportedData(dataForm); + } + // Otherwise return null + return null; + } + + + /** + * Creates a new ReportedData based on the returned dataForm from a search + *(namespace "jabber:iq:search"). + * + * @param dataForm the dataForm returned from a search (namespace "jabber:iq:search"). + */ + private ReportedData(DataForm dataForm) { + // Add the columns to the report based on the reported data fields + for (Iterator fields = dataForm.getReportedData().getFields(); fields.hasNext();) { + FormField field = (FormField)fields.next(); + columns.add(new Column(field.getLabel(), field.getVariable(), field.getType())); + } + + // Add the rows to the report based on the form's items + for (Iterator items = dataForm.getItems(); items.hasNext();) { + DataForm.Item item = (DataForm.Item)items.next(); + List fieldList = new ArrayList(columns.size()); + FormField field; + for (Iterator fields = item.getFields(); fields.hasNext();) { + field = (FormField) fields.next(); + // Note: The field is created based on the FIRST value of the data form's field + fieldList.add(new Field(field.getVariable(), (String)field.getValues().next())); + } + rows.add(new Row(fieldList)); + } + + // Set the report's title + this.title = dataForm.getTitle(); + } + + /** + * Returns an Iterator for the rows returned from a search. + * + * @return an Iterator for the rows returned from a search. + */ + public Iterator getRows() { + return Collections.unmodifiableList(new ArrayList(rows)).iterator(); + } + + /** + * Returns an Iterator for the columns returned from a search. + * + * @return an Iterator for the columns returned from a search. + */ + public Iterator getColumns() { + return Collections.unmodifiableList(new ArrayList(columns)).iterator(); + } + + + /** + * Returns the report's title. It is similar to the title on a web page or an X + * window. + * + * @return title of the report. + */ + public String getTitle() { + return title; + } + + /** + * + * Represents the columns definition of the reported data. + * + * @author Gaston Dombiak + */ + public static class Column { + private String label; + private String variable; + private String type; + + /** + * Creates a new column with the specified definition. + * + * @param label the columns's label. + * @param variable the variable name of the column. + * @param type the format for the returned data. + */ + private Column(String label, String variable, String type) { + this.label = label; + this.variable = variable; + this.type = type; + } + + /** + * Returns the column's label. + * + * @return label of the column. + */ + public String getLabel() { + return label; + } + + + /** + * Returns the column's data format. Valid formats are: + * + * <ul> + * <li>text-single -> single line or word of text + * <li>text-private -> instead of showing the user what they typed, you show ***** to + * protect it + * <li>text-multi -> multiple lines of text entry + * <li>list-single -> given a list of choices, pick one + * <li>list-multi -> given a list of choices, pick one or more + * <li>boolean -> 0 or 1, true or false, yes or no. Default value is 0 + * <li>fixed -> fixed for putting in text to show sections, or just advertise your web + * site in the middle of the form + * <li>hidden -> is not given to the user at all, but returned with the questionnaire + * <li>jid-single -> Jabber ID - choosing a JID from your roster, and entering one based + * on the rules for a JID. + * <li>jid-multi -> multiple entries for JIDs + * </ul> + * + * @return format for the returned data. + */ + public String getType() { + return type; + } + + + /** + * Returns the variable name that the column is showing. + * + * @return the variable name of the column. + */ + public String getVariable() { + return variable; + } + + + } + + public static class Row { + private List fields = new ArrayList(); + + private Row(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 static class Field { + private String variable; + private String value; + + private Field(String variable, String value) { + this.variable = variable; + this.value = value; + } + + /** + * Returns the variable name that the field represents. + * + * @return the variable name of the field. + */ + public String getVariable() { + return variable; + } + + /** + * Returns the value reported as part of the search. + * + * @return the returned value of the search. + */ + public String getValue() { + return value; + } + } +} diff --git a/source/org/jivesoftware/smackx/packet/DataForm.java b/source/org/jivesoftware/smackx/packet/DataForm.java new file mode 100644 index 000000000..b82f5db9b --- /dev/null +++ b/source/org/jivesoftware/smackx/packet/DataForm.java @@ -0,0 +1,311 @@ +/** + * $RCSfile$ + * $Revision$ + * $Date$ + * + * Copyright (C) 2002-2003 Jive Software. All rights reserved. + * ==================================================================== + * The Jive Software License (based on Apache Software License, Version 1.1) + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by + * Jive Software (http://www.jivesoftware.com)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Smack" and "Jive Software" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please + * contact webmaster@jivesoftware.com. + * + * 5. Products derived from this software may not be called "Smack", + * nor may "Smack" appear in their name, without prior written + * permission of Jive Software. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL JIVE SOFTWARE OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + */ +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 { + + public static final String TYPE_FORM = "form"; + public static final String TYPE_SUBMIT = "submit"; + public static final String TYPE_RESULT = "result"; + + private String type; + private String title; + private String instructions; + 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 the instructions that explain how to fill out the form and what the form is about. + * + * @return instructions that explain how to fill out the form. + */ + public String getInstructions() { + return instructions; + } + + /** + * 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 instructions that explain how to fill out the form and what the form is about. + * + * @param instructions instructions that explain how to fill out the form. + */ + public void setInstructions(String 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 item returned from a search. + * + * @param field 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(""); + } + if (getInstructions() != null) { + buf.append("").append(getInstructions()).append(""); + } + // 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(""); + 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(""); + // 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(""); + 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(""); + // 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(""); + return buf.toString(); + } + } +} diff --git a/source/org/jivesoftware/smackx/packet/MUCAdmin.java b/source/org/jivesoftware/smackx/packet/MUCAdmin.java new file mode 100644 index 000000000..c5105bfcf --- /dev/null +++ b/source/org/jivesoftware/smackx/packet/MUCAdmin.java @@ -0,0 +1,68 @@ +/** +* $RCSfile$ +* $Revision$ +* $Date$ +* +* Copyright (C) 2002-2003 Jive Software. All rights reserved. +* ==================================================================== +* The Jive Software License (based on Apache Software License, Version 1.1) +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* 1. Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* +* 2. Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in +* the documentation and/or other materials provided with the +* distribution. +* +* 3. The end-user documentation included with the redistribution, +* if any, must include the following acknowledgment: +* "This product includes software developed by +* Jive Software (http://www.jivesoftware.com)." +* Alternately, this acknowledgment may appear in the software itself, +* if and wherever such third-party acknowledgments normally appear. +* +* 4. The names "Smack" and "Jive Software" must not be used to +* endorse or promote products derived from this software without +* prior written permission. For written permission, please +* contact webmaster@jivesoftware.com. +* +* 5. Products derived from this software may not be called "Smack", +* nor may "Smack" appear in their name, without prior written +* permission of Jive Software. +* +* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED +* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL JIVE SOFTWARE OR +* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF +* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT +* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +* SUCH DAMAGE. +* ==================================================================== +*/ + +package org.jivesoftware.smackx.packet; +import org.jivesoftware.smack.packet.IQ; + +/** + * Represents ..... + * + * @author Gaston Dombiak + */ +public class MUCAdmin extends IQ { + + public String getChildElementXML() { + // TODO Auto-generated method stub + return null; + } + +} diff --git a/source/org/jivesoftware/smackx/packet/MUCInitialPresence.java b/source/org/jivesoftware/smackx/packet/MUCInitialPresence.java new file mode 100644 index 000000000..1abad806e --- /dev/null +++ b/source/org/jivesoftware/smackx/packet/MUCInitialPresence.java @@ -0,0 +1,202 @@ +/** + * $RCSfile$ + * $Revision$ + * $Date$ + * + * Copyright (C) 2002-2003 Jive Software. All rights reserved. + * ==================================================================== + * The Jive Software License (based on Apache Software License, Version 1.1) + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by + * Jive Software (http://www.jivesoftware.com)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Smack" and "Jive Software" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please + * contact webmaster@jivesoftware.com. + * + * 5. Products derived from this software may not be called "Smack", + * nor may "Smack" appear in their name, without prior written + * permission of Jive Software. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL JIVE SOFTWARE OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + */ +package org.jivesoftware.smackx.packet; + +import java.text.SimpleDateFormat; +import java.util.Date; + +import org.jivesoftware.smack.packet.PacketExtension; + +/** + * Represents... + * + * @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("\""); + } + if (getHistory() != null) { + buf.append(getHistory().toXML()); + } + buf.append(""); + return buf.toString(); + } + + /** + * @return + */ + public History getHistory() { + return history; + } + + /** + * @return + */ + public String getPassword() { + return password; + } + + /** + * @param history + */ + public void setHistory(History history) { + this.history = history; + } + + /** + * @param string + */ + public void setPassword(String string) { + password = string; + } + + public static class History { + + private int maxChars = -1; + private int maxStanzas = -1; + private int seconds = -1; + private Date since; + + /** + * @return + */ + public int getMaxChars() { + return maxChars; + } + + /** + * @return + */ + public int getMaxStanzas() { + return maxStanzas; + } + + /** + * @return + */ + public int getSeconds() { + return seconds; + } + + /** + * @return + */ + public Date getSince() { + return since; + } + + /** + * @param i + */ + public void setMaxChars(int i) { + maxChars = i; + } + + /** + * @param i + */ + public void setMaxStanzas(int i) { + maxStanzas = i; + } + + /** + * @param i + */ + public void setSeconds(int i) { + seconds = i; + } + + /** + * @param date + */ + public void setSince(Date date) { + since = date; + } + + public String toXML() { + StringBuffer buf = new StringBuffer(); + buf.append(""); + return buf.toString(); + } + } +} diff --git a/source/org/jivesoftware/smackx/packet/MUCOwner.java b/source/org/jivesoftware/smackx/packet/MUCOwner.java new file mode 100644 index 000000000..87fbb6f0c --- /dev/null +++ b/source/org/jivesoftware/smackx/packet/MUCOwner.java @@ -0,0 +1,303 @@ +/** +* $RCSfile$ +* $Revision$ +* $Date$ +* +* Copyright (C) 2002-2003 Jive Software. All rights reserved. +* ==================================================================== +* The Jive Software License (based on Apache Software License, Version 1.1) +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* 1. Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* +* 2. Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in +* the documentation and/or other materials provided with the +* distribution. +* +* 3. The end-user documentation included with the redistribution, +* if any, must include the following acknowledgment: +* "This product includes software developed by +* Jive Software (http://www.jivesoftware.com)." +* Alternately, this acknowledgment may appear in the software itself, +* if and wherever such third-party acknowledgments normally appear. +* +* 4. The names "Smack" and "Jive Software" must not be used to +* endorse or promote products derived from this software without +* prior written permission. For written permission, please +* contact webmaster@jivesoftware.com. +* +* 5. Products derived from this software may not be called "Smack", +* nor may "Smack" appear in their name, without prior written +* permission of Jive Software. +* +* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED +* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL JIVE SOFTWARE OR +* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF +* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT +* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +* SUCH DAMAGE. +* ==================================================================== +*/ + +package org.jivesoftware.smackx.packet; +import java.util.*; + +import org.jivesoftware.smack.packet.IQ; + +/** + * Represents ..... + * + * @author Gaston Dombiak + */ +public class MUCOwner extends IQ { + + private List items = new ArrayList(); + private Destroy destroy; + + public Iterator getItems() { + synchronized (items) { + return Collections.unmodifiableList(new ArrayList(items)).iterator(); + } + } + + public Destroy getDestroy() { + return destroy; + } + + public void setDestroy(Destroy destroy) { + this.destroy = destroy; + } + + public void addItem(Item item) { + synchronized (items) { + items.add(item); + } + } + + public String getChildElementXML() { + StringBuffer buf = new StringBuffer(); + buf.append(""); + 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(""); + return buf.toString(); + } + + /** + * + * Item child that holds information about affiliation, jids and nicks. + * + * @author Gaston Dombiak + */ + public static class Item { + + // TODO repasar si los comentarios estan OK porque son copy&paste + + private String actor; + private String reason; + private String affiliation; + private String jid; + private String nick; + + /** + * 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 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; + } + + /** + * 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 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(""); + } + else { + buf.append(">"); + if (getReason() != null) { + buf.append("").append(getReason()).append(""); + } + if (getActor() != null) { + buf.append(""); + } + buf.append(""); + } + return buf.toString(); + } + }; + + public static class Destroy { + private String reason; + private String jid; + + + /** + * @return + */ + public String getJid() { + return jid; + } + + /** + * @return + */ + public String getReason() { + return reason; + } + + /** + * @param jid + */ + public void setJid(String jid) { + this.jid = jid; + } + + /** + * @param reason + */ + public void setReason(String reason) { + this.reason = reason; + } + + public String toXML() { + StringBuffer buf = new StringBuffer(); + buf.append(""); + } + else { + buf.append(">"); + if (getReason() != null) { + buf.append("").append(getReason()).append(""); + } + buf.append(""); + } + return buf.toString(); + } + + } +} diff --git a/source/org/jivesoftware/smackx/packet/MUCUser.java b/source/org/jivesoftware/smackx/packet/MUCUser.java new file mode 100644 index 000000000..56cf01fda --- /dev/null +++ b/source/org/jivesoftware/smackx/packet/MUCUser.java @@ -0,0 +1,523 @@ +/** + * $RCSfile$ + * $Revision$ + * $Date$ + * + * Copyright (C) 2002-2003 Jive Software. All rights reserved. + * ==================================================================== + * The Jive Software License (based on Apache Software License, Version 1.1) + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by + * Jive Software (http://www.jivesoftware.com)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Smack" and "Jive Software" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please + * contact webmaster@jivesoftware.com. + * + * 5. Products derived from this software may not be called "Smack", + * nor may "Smack" appear in their name, without prior written + * permission of Jive Software. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL JIVE SOFTWARE OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + */ +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 String alt; + private Invite invite; + private Decline decline; + private Item item; + private String password; + private Status status; + + 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 (getAlt() != null) { + buf.append("").append(getAlt()).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("").append(getPassword()).append(""); + } + if (getStatus() != null) { + buf.append(getStatus().toXML()); + } + buf.append(""); + return buf.toString(); + } + + /** + * @return + */ + public String getAlt() { + return alt; + } + + /** + * @return + */ + public Invite getInvite() { + return invite; + } + + /** + * @return + */ + public Decline getDecline() { + return decline; + } + + /** + * @return + */ + public Item getItem() { + return item; + } + + /** + * @return + */ + public String getPassword() { + return password; + } + + /** + * @return + */ + public Status getStatus() { + return status; + } + + /** + * @param string + */ + public void setAlt(String string) { + alt = string; + } + + /** + * @param invite + */ + public void setInvite(Invite invite) { + this.invite = invite; + } + + /** + * @param decline + */ + public void setDecline(Decline decline) { + this.decline = decline; + } + + /** + * @param item + */ + public void setItem(Item item) { + this.item = item; + } + + /** + * @param string + */ + public void setPassword(String string) { + password = string; + } + + /** + * @param status + */ + public void setStatus(Status status) { + this.status = status; + } + + /** + * + * 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; + + /** + * @return + */ + public String getFrom() { + return from; + } + + /** + * @return + */ + public String getReason() { + return reason; + } + + /** + * @return + */ + public String getTo() { + return to; + } + + /** + * @param string + */ + public void setFrom(String string) { + from = string; + } + + /** + * @param string + */ + public void setReason(String string) { + reason = string; + } + + /** + * @param string + */ + public void setTo(String string) { + to = string; + } + + public String toXML() { + StringBuffer buf = new StringBuffer(); + buf.append(""); + if (getReason() != null) { + buf.append("").append(getReason()).append(""); + } + buf.append(""); + 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; + + /** + * @return + */ + public String getFrom() { + return from; + } + + /** + * @return + */ + public String getReason() { + return reason; + } + + /** + * @return + */ + public String getTo() { + return to; + } + + /** + * @param string + */ + public void setFrom(String string) { + from = string; + } + + /** + * @param string + */ + public void setReason(String string) { + reason = string; + } + + /** + * @param string + */ + public void setTo(String string) { + to = string; + } + + public String toXML() { + StringBuffer buf = new StringBuffer(); + buf.append(""); + if (getReason() != null) { + buf.append("").append(getReason()).append(""); + } + buf.append(""); + 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 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 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(""); + } + else { + buf.append(">"); + if (getReason() != null) { + buf.append("").append(getReason()).append(""); + } + if (getActor() != null) { + buf.append(""); + } + buf.append(""); + } + return buf.toString(); + } + }; + + /** + * + * Status code assists in presenting notification messages. + * + * @author Gaston Dombiak + */ + public static class Status { + private String code; + + /** + * + * @param code + */ + public Status(String code) { + this.code = code; + } + + /** + * @return + */ + public String getCode() { + return code; + } + + public String toXML() { + StringBuffer buf = new StringBuffer(); + buf.append(""); + return buf.toString(); + } + }; +} \ No newline at end of file diff --git a/source/org/jivesoftware/smackx/provider/DataFormProvider.java b/source/org/jivesoftware/smackx/provider/DataFormProvider.java new file mode 100644 index 000000000..278253a1d --- /dev/null +++ b/source/org/jivesoftware/smackx/provider/DataFormProvider.java @@ -0,0 +1,193 @@ +/** +* $RCSfile$ +* $Revision$ +* $Date$ +* +* Copyright (C) 2002-2003 Jive Software. All rights reserved. +* ==================================================================== +* The Jive Software License (based on Apache Software License, Version 1.1) +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* 1. Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* +* 2. Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in +* the documentation and/or other materials provided with the +* distribution. +* +* 3. The end-user documentation included with the redistribution, +* if any, must include the following acknowledgment: +* "This product includes software developed by +* Jive Software (http://www.jivesoftware.com)." +* Alternately, this acknowledgment may appear in the software itself, +* if and wherever such third-party acknowledgments normally appear. +* +* 4. The names "Smack" and "Jive Software" must not be used to +* endorse or promote products derived from this software without +* prior written permission. For written permission, please +* contact webmaster@jivesoftware.com. +* +* 5. Products derived from this software may not be called "Smack", +* nor may "Smack" appear in their name, without prior written +* permission of Jive Software. +* +* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED +* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL JIVE SOFTWARE OR +* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF +* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT +* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +* SUCH DAMAGE. +* ==================================================================== +*/ + +package org.jivesoftware.smackx.provider; + +import java.util.ArrayList; +import java.util.List; + +import org.jivesoftware.smack.packet.PacketExtension; +import org.jivesoftware.smack.provider.PacketExtensionProvider; +import org.jivesoftware.smackx.FormField; +import org.jivesoftware.smackx.packet.DataForm; +import org.xmlpull.v1.XmlPullParser; + +/** + * The DataFormProvider parses DataForm packets. + * + * @author Gaston Dombiak + */ +public class DataFormProvider implements PacketExtensionProvider { + + /** + * Creates a new DataFormProvider. + * ProviderManager requires that every PacketExtensionProvider has a public, no-argument constructor + */ + public DataFormProvider() { + } + + public PacketExtension parseExtension(XmlPullParser parser) throws Exception { + boolean done = false; + StringBuffer buffer = null; + DataForm dataForm = new DataForm(parser.getAttributeValue("", "type")); + while (!done) { + int eventType = parser.next(); + if (eventType == XmlPullParser.START_TAG) { + if (parser.getName().equals("instructions")) { + dataForm.setInstructions(parser.nextText()); + } + else if (parser.getName().equals("title")) { + dataForm.setTitle(parser.nextText()); + } + else if (parser.getName().equals("field")) { + dataForm.addField(parseField(parser)); + } + else if (parser.getName().equals("item")) { + dataForm.addItem(parseItem(parser)); + } + else if (parser.getName().equals("reported")) { + dataForm.setReportedData(parseReported(parser)); + } + } else if (eventType == XmlPullParser.END_TAG) { + if (parser.getName().equals(dataForm.getElementName())) { + done = true; + } + } + } + return dataForm; + } + + private FormField parseField(XmlPullParser parser) throws Exception { + boolean done = false; + FormField formField = new FormField(); + formField.setLabel(parser.getAttributeValue("", "label")); + formField.setVariable(parser.getAttributeValue("", "var")); + formField.setType(parser.getAttributeValue("", "type")); + while (!done) { + int eventType = parser.next(); + if (eventType == XmlPullParser.START_TAG) { + if (parser.getName().equals("desc")) { + formField.setDescription(parser.nextText()); + } + else if (parser.getName().equals("value")) { + formField.addValue(parser.nextText()); + } + else if (parser.getName().equals("required")) { + formField.setRequired(true); + } + else if (parser.getName().equals("option")) { + formField.addOption(parseOption(parser)); + } + } else if (eventType == XmlPullParser.END_TAG) { + if (parser.getName().equals("field")) { + done = true; + } + } + } + return formField; + } + + private DataForm.Item parseItem(XmlPullParser parser) throws Exception { + boolean done = false; + List fields = new ArrayList(); + while (!done) { + int eventType = parser.next(); + if (eventType == XmlPullParser.START_TAG) { + if (parser.getName().equals("field")) { + fields.add(parseField(parser)); + } + } else if (eventType == XmlPullParser.END_TAG) { + if (parser.getName().equals("item")) { + done = true; + } + } + } + return new DataForm.Item(fields); + } + + private DataForm.ReportedData parseReported(XmlPullParser parser) throws Exception { + boolean done = false; + List fields = new ArrayList(); + while (!done) { + int eventType = parser.next(); + if (eventType == XmlPullParser.START_TAG) { + if (parser.getName().equals("field")) { + fields.add(parseField(parser)); + } + } else if (eventType == XmlPullParser.END_TAG) { + if (parser.getName().equals("reported")) { + done = true; + } + } + } + return new DataForm.ReportedData(fields); + } + + private FormField.Option parseOption(XmlPullParser parser) throws Exception { + boolean done = false; + FormField.Option option = null; + String label = parser.getAttributeValue("", "label"); + while (!done) { + int eventType = parser.next(); + if (eventType == XmlPullParser.START_TAG) { + if (parser.getName().equals("value")) { + option = new FormField.Option(label, parser.nextText()); + } + } else if (eventType == XmlPullParser.END_TAG) { + if (parser.getName().equals("option")) { + done = true; + } + } + } + return option; + } +} diff --git a/source/org/jivesoftware/smackx/provider/MUCAdminProvider.java b/source/org/jivesoftware/smackx/provider/MUCAdminProvider.java new file mode 100644 index 000000000..7314ad9c9 --- /dev/null +++ b/source/org/jivesoftware/smackx/provider/MUCAdminProvider.java @@ -0,0 +1,74 @@ +/** +* $RCSfile$ +* $Revision$ +* $Date$ +* +* Copyright (C) 2002-2003 Jive Software. All rights reserved. +* ==================================================================== +* The Jive Software License (based on Apache Software License, Version 1.1) +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* 1. Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* +* 2. Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in +* the documentation and/or other materials provided with the +* distribution. +* +* 3. The end-user documentation included with the redistribution, +* if any, must include the following acknowledgment: +* "This product includes software developed by +* Jive Software (http://www.jivesoftware.com)." +* Alternately, this acknowledgment may appear in the software itself, +* if and wherever such third-party acknowledgments normally appear. +* +* 4. The names "Smack" and "Jive Software" must not be used to +* endorse or promote products derived from this software without +* prior written permission. For written permission, please +* contact webmaster@jivesoftware.com. +* +* 5. Products derived from this software may not be called "Smack", +* nor may "Smack" appear in their name, without prior written +* permission of Jive Software. +* +* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED +* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL JIVE SOFTWARE OR +* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF +* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT +* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +* SUCH DAMAGE. +* ==================================================================== +*/ + +package org.jivesoftware.smackx.provider; + +import org.jivesoftware.smack.packet.IQ; +import org.jivesoftware.smack.provider.IQProvider; +import org.xmlpull.v1.XmlPullParser; + +/** + * Represents ..... + * + * @author Gaston Dombiak + */ +public class MUCAdminProvider implements IQProvider { + + /* (non-Javadoc) + * @see org.jivesoftware.smack.provider.IQProvider#parseIQ(org.xmlpull.v1.XmlPullParser) + */ + public IQ parseIQ(XmlPullParser parser) throws Exception { + // TODO Auto-generated method stub + return null; + } + +} diff --git a/source/org/jivesoftware/smackx/provider/MUCOwnerProvider.java b/source/org/jivesoftware/smackx/provider/MUCOwnerProvider.java new file mode 100644 index 000000000..b193d26dd --- /dev/null +++ b/source/org/jivesoftware/smackx/provider/MUCOwnerProvider.java @@ -0,0 +1,143 @@ +/** +* $RCSfile$ +* $Revision$ +* $Date$ +* +* Copyright (C) 2002-2003 Jive Software. All rights reserved. +* ==================================================================== +* The Jive Software License (based on Apache Software License, Version 1.1) +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* 1. Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* +* 2. Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in +* the documentation and/or other materials provided with the +* distribution. +* +* 3. The end-user documentation included with the redistribution, +* if any, must include the following acknowledgment: +* "This product includes software developed by +* Jive Software (http://www.jivesoftware.com)." +* Alternately, this acknowledgment may appear in the software itself, +* if and wherever such third-party acknowledgments normally appear. +* +* 4. The names "Smack" and "Jive Software" must not be used to +* endorse or promote products derived from this software without +* prior written permission. For written permission, please +* contact webmaster@jivesoftware.com. +* +* 5. Products derived from this software may not be called "Smack", +* nor may "Smack" appear in their name, without prior written +* permission of Jive Software. +* +* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED +* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL JIVE SOFTWARE OR +* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF +* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT +* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +* SUCH DAMAGE. +* ==================================================================== +*/ + +package org.jivesoftware.smackx.provider; + +import org.jivesoftware.smack.packet.*; +import org.jivesoftware.smack.provider.*; +import org.jivesoftware.smack.util.PacketParserUtils; +import org.jivesoftware.smackx.packet.MUCOwner; +import org.xmlpull.v1.XmlPullParser; + +/** + * Represents ..... + * + * @author Gaston Dombiak + */ +public class MUCOwnerProvider implements IQProvider { + + public IQ parseIQ(XmlPullParser parser) throws Exception { + MUCOwner mucOwner = new MUCOwner(); + boolean done = false; + MUCOwner.Item item = null; + while (!done) { + int eventType = parser.next(); + if (eventType == XmlPullParser.START_TAG) { + if (parser.getName().equals("item")) { + mucOwner.addItem(parseItem(parser)); + } + if (parser.getName().equals("destroy")) { + mucOwner.setDestroy(parseDestroy(parser)); + } + // Otherwise, it must be a packet extension. + else { + mucOwner.addExtension( + PacketParserUtils.parsePacketExtension( + parser.getName(), + parser.getNamespace(), + parser)); + } + } + else if (eventType == XmlPullParser.END_TAG) { + if (parser.getName().equals("query")) { + done = true; + } + } + } + + return mucOwner; + } + + private MUCOwner.Item parseItem(XmlPullParser parser) throws Exception { + boolean done = false; + MUCOwner.Item item = new MUCOwner.Item(parser.getAttributeValue("", "affiliation")); + item.setNick(parser.getAttributeValue("", "nick")); + item.setJid(parser.getAttributeValue("", "jid")); + while (!done) { + int eventType = parser.next(); + if (eventType == XmlPullParser.START_TAG) { + if (parser.getName().equals("actor")) { + item.setActor(parser.getAttributeValue("", "jid")); + } + if (parser.getName().equals("reason")) { + item.setReason(parser.getText()); + } + } + else if (eventType == XmlPullParser.END_TAG) { + if (parser.getName().equals("item")) { + done = true; + } + } + } + return item; + } + + private MUCOwner.Destroy parseDestroy(XmlPullParser parser) throws Exception { + boolean done = false; + MUCOwner.Destroy destroy = new MUCOwner.Destroy(); + destroy.setJid(parser.getAttributeValue("", "jid")); + while (!done) { + int eventType = parser.next(); + if (eventType == XmlPullParser.START_TAG) { + if (parser.getName().equals("reason")) { + destroy.setReason(parser.getText()); + } + } + else if (eventType == XmlPullParser.END_TAG) { + if (parser.getName().equals("destroy")) { + done = true; + } + } + } + return destroy; + } +} diff --git a/source/org/jivesoftware/smackx/provider/MUCUserProvider.java b/source/org/jivesoftware/smackx/provider/MUCUserProvider.java new file mode 100644 index 000000000..20acaed93 --- /dev/null +++ b/source/org/jivesoftware/smackx/provider/MUCUserProvider.java @@ -0,0 +1,135 @@ +/** + * $RCSfile$ + * $Revision$ + * $Date$ + * + * Copyright (C) 2002-2003 Jive Software. All rights reserved. + * ==================================================================== + * The Jive Software License (based on Apache Software License, Version 1.1) + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by + * Jive Software (http://www.jivesoftware.com)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Smack" and "Jive Software" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please + * contact webmaster@jivesoftware.com. + * + * 5. Products derived from this software may not be called "Smack", + * nor may "Smack" appear in their name, without prior written + * permission of Jive Software. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL JIVE SOFTWARE OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + */ +package org.jivesoftware.smackx.provider; + +import org.jivesoftware.smack.packet.*; +import org.jivesoftware.smack.provider.*; +import org.jivesoftware.smackx.packet.*; +import org.xmlpull.v1.XmlPullParser; + +/** + * The MUCUserProvider parses packets with extended presence information about + * roles and affiliations. + * + * @author Gaston Dombiak + */ +public class MUCUserProvider implements PacketExtensionProvider { + + /** + * Creates a new MUCUserProvider. + * ProviderManager requires that every PacketExtensionProvider has a public, no-argument + * constructor + */ + public MUCUserProvider() { + } + + /** + * Parses a MUCUser 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 { + MUCUser mucUser = new MUCUser(); + boolean done = false; + MUCUser.Item item = null; + while (!done) { + int eventType = parser.next(); + if (eventType == XmlPullParser.START_TAG) { + if (parser.getName().equals("item")) { + item = + new MUCUser.Item( + parser.getAttributeValue("", "affiliation"), + parser.getAttributeValue("", "role")); + item.setNick(parser.getAttributeValue("", "nick")); + item.setJid(parser.getAttributeValue("", "jid")); + } + if (parser.getName().equals("actor")) { + item.setActor(parser.getAttributeValue("", "jid")); + } + if (parser.getName().equals("reason")) { + item.setReason(parser.getText()); + } + if (parser.getName().equals("password")) { + mucUser.setPassword(parser.getText()); + } + if (parser.getName().equals("alt")) { + // TODO Implement alt? Is it being used? + System.out.println("alt - Not implemented yet!"); + } + if (parser.getName().equals("invite")) { + // TODO Implement invitation decoding + System.out.println("invite - Not implemented yet!"); + } + if (parser.getName().equals("decline")) { + // TODO Implement decline decoding + System.out.println("decline - Not implemented yet!"); + } + if (parser.getName().equals("status")) { + mucUser.setStatus(new MUCUser.Status(parser.getAttributeValue("", "code"))); + } + } + else if (eventType == XmlPullParser.END_TAG) { + if (parser.getName().equals("item")) { + mucUser.setItem(item); + } + if (parser.getName().equals("x")) { + done = true; + } + } + } + + return mucUser; + } + +}