Commit cc734482 authored by guus's avatar guus

Replacing code that's now in the new Tinder project with a jar generated by...

Replacing code that's now in the new Tinder project with a jar generated by the Tinder project (OF-1, TINDER-5).

git-svn-id: http://svn.igniterealtime.org/svn/repos/openfire/trunk@11030 b35dd754-fafc-0310-a699-88a17e54d16e
parent 2e614424
/**
* $RCSfile: $
* $Revision: 2772 $
* $Date: 2005-09-05 01:50:45 -0300 (Mon, 05 Sep 2005) $
*
* Copyright (C) 2005-2008 Jive Software. All rights reserved.
*
* This software is published under the terms of the GNU Public License (GPL),
* a copy of which is included in this distribution, or a commercial license
* agreement with Jive.
*/
package org.jivesoftware.openfire;
import org.xmpp.packet.IQ;
/**
* An IQResultListener will be invoked when a previously IQ packet sent by the server was answered.
* Use {@link IQRouter#addIQResultListener(String, IQResultListener)} to add a new listener that
* will process the answer to the IQ packet being sent. The listener will automatically be
* removed from the {@link IQRouter} as soon as a reply for the sent IQ packet is received. The
* reply can be of type RESULT or ERROR.
*
* @author Gaston Dombiak
*/
public interface IQResultListener {
/**
* Notification method indicating that a previously sent IQ packet has been answered.
* The received IQ packet might be of type ERROR or RESULT.
*
* @param packet the IQ packet answering a previously sent IQ packet.
*/
void receivedAnswer(IQ packet);
/**
* Notification method indicating that a predefined time has passed without
* receiving answer to a previously sent IQ packet.
*
* @param packetId The packet id of a previously sent IQ packet that wasn't answered.
*/
void answerTimeout(String packetId);
}
......@@ -263,7 +263,7 @@ public class InternalComponentManager extends BasicModule implements ComponentMa
}
}
public IQ query(Component component, IQ packet, int timeout) throws ComponentException {
public IQ query(Component component, IQ packet, long timeout) throws ComponentException {
final LinkedBlockingQueue<IQ> answer = new LinkedBlockingQueue<IQ>(8);
XMPPServer.getInstance().getIQRouter().addIQResultListener(packet.getID(), new IQResultListener() {
public void receivedAnswer(IQ packet) {
......
/**
* $RCSfile$
* $Revision: 128 $
* $Date: 2004-10-25 20:42:00 -0300 (Mon, 25 Oct 2004) $
*
* Copyright (C) 2004-2008 Jive Software. All rights reserved.
*
* This software is published under the terms of the GNU Public License (GPL),
* a copy of which is included in this distribution, or a commercial license
* agreement with Jive.
*/
package org.jivesoftware.openfire.forms;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
/**
* Represents a form that could be use for gathering data as well as for reporting data
* returned from a search.
* <p/>
* The form could be of the following types:
* <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>
* <p/>
* In case the form represents a search, the report will be structured in columns and rows. Use
* {@link #addReportedField(FormField)} to set the columns of the report whilst the report's rows
* can be configured using {@link #addItemFields(ArrayList)}.
*
* @author gdombiak
*/
public interface DataForm {
public static final String TYPE_FORM = "form";
public static final String TYPE_SUBMIT = "submit";
public static final String TYPE_CANCEL = "cancel";
public static final String TYPE_RESULT = "result";
/**
* 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 abstract void setTitle(String title);
/**
* Sets the list of instructions that explain how to fill out the form and what the form is
* about. The dataform could include multiple instructions since each instruction could not
* contain newlines characters.
*
* @param instructions list of instructions that explain how to fill out the form.
*/
public abstract void setInstructions(List instructions);
/**
* 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>
* <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 abstract String getType();
/**
* 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 abstract String getTitle();
/**
* Returns an Iterator for the list of instructions that explain how to fill out the form and
* what the form is about. The dataform could include multiple instructions since each
* instruction could not contain newlines characters. Join the instructions together in order
* to show them to the user.
*
* @return an Iterator for the list of instructions that explain how to fill out the form.
*/
public abstract Iterator getInstructions();
/**
* Returns the field of the form whose variable matches the specified variable.
* The fields of type FIXED will never be returned since they do not specify a
* variable.
*
* @param variable the variable to look for in the form fields.
* @return the field of the form whose variable matches the specified variable.
*/
public FormField getField(String variable);
/**
* 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 abstract Iterator getFields();
/**
* Returns the number of fields included in the form.
*
* @return the number of fields included in the form.
*/
public abstract int getFieldsSize();
/**
* Adds a new instruction to the list of instructions that explain how to fill out the form
* and what the form is about. The dataform could include multiple instructions since each
* instruction could not contain newlines characters.
*
* @param instruction the new instruction that explain how to fill out the form.
*/
public abstract void addInstruction(String instruction);
/**
* Adds a new field as part of the form.
*
* @param field the field to add to the form.
*/
public abstract void addField(FormField field);
/**
* Adds a field to the list of fields that will be returned from a search. Each field represents
* a column in the report. The order of the columns in the report will honor the sequence in
* which they were added.
*
* @param field the field to add to the list of fields that will be returned from a search.
*/
public abstract void addReportedField(FormField field);
/**
* Adds a new row of items of reported data. The list of items to add will be formed by
* FormFields. Each FormField variable <b>must</b> be valid (i.e. the variable must be defined
* by the FormFields added as ReportedField.
*
* @param itemFields list of FormFields to add as a row in the report.
*/
public abstract void addItemFields(ArrayList itemFields);
}
/**
* $RCSfile$
* $Revision: 223 $
* $Date: 2004-11-07 22:52:36 -0300 (Sun, 07 Nov 2004) $
*
* Copyright (C) 2004-2008 Jive Software. All rights reserved.
*
* This software is published under the terms of the GNU Public License (GPL),
* a copy of which is included in this distribution, or a commercial license
* agreement with Jive.
*/
package org.jivesoftware.openfire.forms;
import java.util.Iterator;
/**
* 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 interface 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";
/**
* 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);
/**
* Removes all the values of the field.
*/
public void clearValues();
/**
* Adds an available option to the question that the user has in order to answer
* the question.
*
* @param label a label that represents the option.
* @param value the value of the option.
*/
public void addOption(String label, String value);
/**
* Sets an indicative of the format for the data to answer. Valid formats are:
* <p/>
* <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 abstract void setType(String type);
/**
* 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 abstract void setRequired(boolean required);
/**
* 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 abstract void setLabel(String label);
/**
* 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>
* <p/>
* If the question is of type FIXED then the description should remain empty.
*
* @param description provides extra clarification about the question.
*/
public abstract void setDescription(String description);
/**
* 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 abstract boolean isRequired();
/**
* Returns the variable name that the question is filling out.
*
* @return the variable name of the question.
*/
public abstract String getVariable();
/**
* 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 abstract Iterator<String> getValues();
/**
* Returns an indicative of the format for the data to answer. Valid formats are:
* <p/>
* <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 abstract String getType();
/**
* 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 abstract String getLabel();
/**
* 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>
* <p/>
* If the question is of type FIXED then the description should remain empty.
*
* @return description that provides extra clarification about the question.
*/
public abstract String getDescription();
}
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
</head>
<body>
<p>Data forms implementation (JEP-0004).</p>
</body>
</html>
/**
* $RCSfile$
* $Revision: 904 $
* $Date: 2005-01-25 15:41:48 -0300 (Tue, 25 Jan 2005) $
*
* Copyright (C) 2004-2008 Jive Software. All rights reserved.
*
* This software is published under the terms of the GNU Public License (GPL),
* a copy of which is included in this distribution, or a commercial license
* agreement with Jive.
*/
package org.jivesoftware.openfire.forms.spi;
import org.jivesoftware.openfire.forms.FormField;
import java.util.*;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.QName;
/**
* A concrete DataForm capable of sending itself to a writer and recover its state from an XMPP
* stanza. XDataForms are packets of the form:
* <code><pre>
* &lt;x xmlns='jabber:x:data' type='{form-type}'&gt;
* &lt;title/&gt;
* &lt;instructions/&gt;
* &lt;field var='field-name'
* type='{field-type}'
* label='description'&gt;
* &lt;desc/&gt;
* &lt;required/&gt;
* &lt;value&gt;field-value&lt;/value&gt;
* &lt;option label='option-label'&gt;&lt;value&gt;option-value&lt;/value&gt;&lt;/option&gt;
* &lt;option label='option-label'&gt;&lt;value&gt;option-value&lt;/value&gt;&lt;/option&gt;
* &lt;/field&gt;
* &lt;/x&gt;
* </pre></code>
* <p/>
* An XDataFormImpl can contain zero or more XFormFieldImpl 'field' fragments.<p>
* <p/>
* To learn more follow this link: <a href="http://www.jabber.org/jeps/jep-0004.html">JEP-04</a>.
*
* @author gdombiak
*/
public class XDataFormImpl {
private String type;
private String title;
private List instructions = new ArrayList();
private List fields = new ArrayList();
private List reportedFields = new ArrayList();
private List reportedItems = new ArrayList();
public XDataFormImpl() {
super();
}
public XDataFormImpl(String type) {
this.type = type;
}
public void setTitle(String title) {
this.title = title;
}
public void setInstructions(List instructions) {
this.instructions = instructions;
}
public String getType() {
return type;
}
public String getTitle() {
return title;
}
public Iterator getInstructions() {
synchronized (instructions) {
return Collections.unmodifiableList(new ArrayList(instructions)).iterator();
}
}
public FormField getField(String variable) {
if (variable == null || variable.equals("")) {
throw new IllegalArgumentException("Variable must not be null or blank.");
}
// Look for the field whose variable matches the requested variable
FormField field;
for (Iterator it = getFields(); it.hasNext();) {
field = (FormField)it.next();
if (variable.equals(field.getVariable())) {
return field;
}
}
return null;
}
public Iterator getFields() {
synchronized (fields) {
return Collections.unmodifiableList(new ArrayList(fields)).iterator();
}
}
public int getFieldsSize() {
return fields.size();
}
public void addInstruction(String instruction) {
synchronized (instructions) {
instructions.add(instruction);
}
}
public void addField(FormField field) {
synchronized (fields) {
fields.add(field);
}
}
public void addReportedField(FormField field) {
synchronized (reportedFields) {
reportedFields.add(field);
}
}
public void addItemFields(ArrayList itemFields) {
synchronized (reportedItems) {
// We are nesting a List (of fields) inside of the List of items
reportedItems.add(itemFields);
}
}
public String getNamespace() {
// Is someone sending this message?
return "jabber:x:data";
}
public void setNamespace(String namespace) {
// Is someone sending this message?
// Do nothing
}
public String getName() {
// Is someone sending this message?
return "x";
}
public void setName(String name) {
// Is someone sending this message?
// Do nothing
}
public Element asXMLElement() {
Element x = DocumentHelper.createElement(QName.get("x", "jabber:x:data"));
if (getType() != null) {
x.addAttribute("type", getType());
}
if (getTitle() != null) {
x.addElement("title").addText(getTitle());
}
if (instructions.size() > 0) {
Iterator instrItr = getInstructions();
while (instrItr.hasNext()) {
x.addElement("instructions").addText((String)instrItr.next());
}
}
// Append the list of fields returned from a search
if (reportedFields.size() > 0) {
Element reportedElement = x.addElement("reported");
Iterator fieldsItr = reportedFields.iterator();
while (fieldsItr.hasNext()) {
XFormFieldImpl field = (XFormFieldImpl)fieldsItr.next();
reportedElement.add(field.asXMLElement());
}
}
// Append the list of items returned from a search
// Note: each item contains a List of XFormFieldImpls
if (reportedItems.size() > 0) {
Iterator itemsItr = reportedItems.iterator();
while (itemsItr.hasNext()) {
// Add a new item element for this list of fields
Element itemElement = x.addElement("item");
List fields = (List)itemsItr.next();
Iterator fieldsItr = fields.iterator();
// Iterate on the fields and add them to the new item
while (fieldsItr.hasNext()) {
XFormFieldImpl field = (XFormFieldImpl)fieldsItr.next();
itemElement.add(field.asXMLElement());
}
}
}
if (fields.size() > 0) {
Iterator fieldsItr = getFields();
while (fieldsItr.hasNext()) {
XFormFieldImpl field = (XFormFieldImpl)fieldsItr.next();
x.add(field.asXMLElement());
}
}
return x;
}
public void parse(Element formElement) {
type = formElement.attributeValue("type");
Element titleElement = formElement.element("title");
if (titleElement != null) {
setTitle(titleElement.getTextTrim());
}
Iterator instructionElements = formElement.elementIterator("instructions");
while (instructionElements.hasNext()) {
addInstruction(((Element)instructionElements.next()).getTextTrim());
}
Iterator fieldElements = formElement.elementIterator("field");
while (fieldElements.hasNext()) {
XFormFieldImpl field = new XFormFieldImpl();
field.parse((Element)fieldElements.next());
addField(field);
}
Element reportedElement = formElement.element("reported");
if (reportedElement != null) {
Iterator reportedFieldElements = reportedElement.elementIterator("field");
while (reportedFieldElements.hasNext()) {
XFormFieldImpl field = new XFormFieldImpl();
field.parse((Element)reportedFieldElements.next());
addReportedField(field);
}
}
Iterator itemElements = formElement.elementIterator("item");
while (itemElements.hasNext()) {
Element itemElement = (Element)itemElements.next();
Iterator itemFieldElements = itemElement.elementIterator("field");
ArrayList itemFields = new ArrayList();
while (itemFieldElements.hasNext()) {
XFormFieldImpl field = new XFormFieldImpl();
field.parse((Element)itemFieldElements.next());
itemFields.add(field);
}
addItemFields(itemFields);
}
}
}
\ No newline at end of file
/**
* $RCSfile$
* $Revision: 942 $
* $Date: 2005-02-02 21:55:43 -0300 (Wed, 02 Feb 2005) $
*
* Copyright (C) 2004-2008 Jive Software. All rights reserved.
*
* This software is published under the terms of the GNU Public License (GPL),
* a copy of which is included in this distribution, or a commercial license
* agreement with Jive.
*/
package org.jivesoftware.openfire.forms.spi;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.QName;
import org.jivesoftware.openfire.forms.FormField;
/**
* A concrete FormField capable of sending itself to a writer and recover its state from an XMPP
* stanza.
*
* @author gdombiak
*/
public class XFormFieldImpl implements FormField {
private String description;
private boolean required = false;
private String label;
private String variable;
private String type;
private List<Option> options = new ArrayList<Option>();
private List<String> values = new ArrayList<String>();
public XFormFieldImpl() {
super();
}
public XFormFieldImpl(String variable) {
this.variable = variable;
}
public String getNamespace() {
// Is someone sending this message?
return "jabber:x:data";
}
public void setNamespace(String namespace) {
// Is someone sending this message?
// Do nothing
}
public String getName() {
// Is someone sending this message?
return "x";
}
public void setName(String name) {
// Is someone sending this message?
// Do nothing
}
public Element asXMLElement() {
Element field = DocumentHelper.createElement(QName.get("field", "jabber:x:data"));
if (getLabel() != null) {
field.addAttribute("label", getLabel());
}
if (getVariable() != null) {
field.addAttribute("var", getVariable());
}
if (getType() != null) {
field.addAttribute("type", getType());
}
if (getDescription() != null) {
field.addElement("desc").addText(getDescription());
}
if (isRequired()) {
field.addElement("required");
}
// Loop through all the values and append them to the stream writer
if (values.size() > 0) {
Iterator<String> valuesItr = getValues();
while (valuesItr.hasNext()) {
field.addElement("value").addText(valuesItr.next());
}
}
// Loop through all the options and append them to the stream writer
if (options.size() > 0) {
Iterator<Option> optionsItr = getOptions();
while (optionsItr.hasNext()) {
field.add((optionsItr.next()).asXMLElement());
}
}
// Loop through all the values and append them to the stream writer
/*Iterator frags = fragments.iterator();
while (frags.hasNext()){
XMPPFragment frag = (XMPPFragment) frags.next();
frag.send(xmlSerializer,version);
}*/
return field;
}
public void addValue(String value) {
if (value == null) {
value = "";
}
synchronized (values) {
values.add(value);
}
}
public void clearValues() {
synchronized (values) {
values.clear();
}
}
public void addOption(String label, String value) {
synchronized (options) {
options.add(new Option(label, value));
}
}
public void setType(String type) {
this.type = type;
}
public void setRequired(boolean required) {
this.required = required;
}
public void setLabel(String label) {
this.label = label;
}
public void setDescription(String description) {
this.description = description;
}
public boolean isRequired() {
return required;
}
public String getVariable() {
return variable;
}
public Iterator<String> getValues() {
synchronized (values) {
return Collections.unmodifiableList(new ArrayList<String>(values)).iterator();
}
}
public String getType() {
return type;
}
/**
* Returns an Iterator for the available options that the user has in order to answer
* the question.
*
* @return Iterator for the available options.
*/
private Iterator<Option> getOptions() {
synchronized (options) {
return Collections.unmodifiableList(new ArrayList<Option>(options)).iterator();
}
}
public String getLabel() {
return label;
}
public String getDescription() {
return description;
}
public void parse(Element formElement) {
variable = formElement.attributeValue("var");
setLabel(formElement.attributeValue("label"));
setType(formElement.attributeValue("type"));
Element descElement = formElement.element("desc");
if (descElement != null) {
setDescription(descElement.getTextTrim());
}
if (formElement.element("required") != null) {
setRequired(true);
}
Iterator valueElements = formElement.elementIterator("value");
while (valueElements.hasNext()) {
addValue(((Element)valueElements.next()).getTextTrim());
}
Iterator optionElements = formElement.elementIterator("option");
Element optionElement;
while (optionElements.hasNext()) {
optionElement = (Element)optionElements.next();
addOption(optionElement.attributeValue("label"), optionElement.elementTextTrim("value"));
}
}
public String toString() {
return "XFormFieldImpl " + Integer.toHexString(hashCode()) + " " + getVariable() + ">" + values
+ " o: " + (options.isEmpty() ? "no options" : options.toString());
}
/**
* Represents the available option of a given FormField.
*
* @author Gaston Dombiak
*/
private static class Option {
private String label;
private String 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 Element asXMLElement() {
Element option = DocumentHelper.createElement(QName.get("option", "jabber:x:data"));
if (getLabel() != null) {
option.addAttribute("label", getLabel());
}
if (getValue() != null) {
option.addElement("value").addText(getValue());
}
return option;
}
}
}
\ No newline at end of file
/**
* Copyright (C) 2004-2008 Jive Software. All rights reserved.
*
* This software is published under the terms of the GNU Public License (GPL),
* a copy of which is included in this distribution, or a commercial license
* agreement with Jive.
*/
package org.xmpp.component;
import org.xmpp.packet.JID;
import org.xmpp.packet.Packet;
/**
* Component enhance the functionality of an XMPP server.
*
* Components are JavaBeans and will have their properties exposed as ad-hoc commands.
*
* @author Matt Tucker
*/
public interface Component {
/**
* Returns the name of this component.
*
* @return the name of this component.
*/
public String getName();
/**
* Returns the description of this component.
*
* @return the description of this component.
*/
public String getDescription();
/**
* Processes a packet sent to this Component.
*
* @param packet the packet.
* @see ComponentManager#sendPacket(Component, Packet)
*/
public void processPacket(Packet packet);
/**
* Initializes this component with a ComponentManager and the JID
* that this component is available at (e.g. <tt>service.example.com</tt>). If a
* ComponentException is thrown then the component will not be loaded.<p>
*
* The initialization code must not rely on receiving packets from the server since
* the component has not been fully initialized yet. This means that at this point the
* component must not rely on information that is obtained from the server such us
* discovered items.
*
* @param jid the XMPP address that this component is available at.
* @param componentManager the component manager.
* @throws ComponentException if an error occured while initializing the component.
*/
public void initialize(JID jid, ComponentManager componentManager) throws ComponentException;
/**
* Notification message indicating that the component will start receiving incoming
* packets. At this time the component may finish pending initialization issues that
* require information obtained from the server.<p>
*
* It is likely that most of the component will leave this method empty.
*/
public void start();
/**
* Shuts down this component. All component resources must be released as
* part of shutdown.
*/
public void shutdown();
}
\ No newline at end of file
/**
* Copyright (C) 2004-2008 Jive Software. All rights reserved.
*
* This software is published under the terms of the GNU Public License (GPL),
* a copy of which is included in this distribution, or a commercial license
* agreement with Jive.
*/
package org.xmpp.component;
import org.xmpp.packet.StreamError;
/**
* Thrown when an exception occors with a Component.
*
* @author Matt Tucker
*/
public class ComponentException extends Exception {
private StreamError streamError;
public ComponentException() {
super();
}
public ComponentException(String message) {
super(message);
}
public ComponentException(String message, Throwable cause) {
super(message, cause);
}
public ComponentException(Throwable cause) {
super(cause);
}
public ComponentException(String message, StreamError streamError) {
super(message);
this.streamError = streamError;
}
public ComponentException(StreamError streamError) {
super(streamError.getCondition().toXMPP());
this.streamError = streamError;
}
public StreamError getStreamError() {
return streamError;
}
}
/**
* Copyright (C) 2004-2008 Jive Software. All rights reserved.
*
* This software is published under the terms of the GNU Public License (GPL),
* a copy of which is included in this distribution, or a commercial license
* agreement with Jive.
*/
package org.xmpp.component;
import org.jivesoftware.openfire.IQResultListener;
import org.xmpp.packet.IQ;
import org.xmpp.packet.Packet;
/**
* Manages components.
*
* @see Component
* @author Matt Tucker
*/
public interface ComponentManager {
/**
* Adds a component. The {@link Component#initialize(org.xmpp.packet.JID, ComponentManager)}
* method will be called on the component. The subdomain specifies the address of
* the component on a server. For example, if the subdomain is "test" and the XMPP
* server is at "example.com", then the component's address would be "test.example.com".
*
* @param subdomain the subdomain of the component's address.
* @param component the component.
*/
public void addComponent(String subdomain, Component component) throws ComponentException;
/**
* Removes a component. The {@link Component#shutdown} method will be called on the
* component.
*
* @param subdomain the subdomain of the component's address.
*/
public void removeComponent(String subdomain) throws ComponentException;
/**
* Sends a packet to the XMPP server. The "from" value of the packet must not be null.
* An <tt>IllegalArgumentException</tt> will be thrown when the "from" value is null.<p>
*
* Components are trusted by the server and may use any value in from address. Usually
* the from address uses the component's address as the domain but this is not required.
*
* @param component the component sending the packet.
* @param packet the packet to send.
*/
public void sendPacket(Component component, Packet packet) throws ComponentException;
/**
* Sends an IQ packet to the XMPP server and waits to get an IQ of type result or error.
* The "from" value of the packet must not be null. An <tt>IllegalArgumentException</tt>
* will be thrown when the "from" value is null.<p>
*
* Components are trusted by the server and may use any value in from address. Usually
* the from address uses the component's address as the domain but this is not required.
*
* @param component the component sending the packet.
* @param packet the IQ packet to send.
* @param timeout the number of milliseconds to wait before returning an IQ error.
* @return the answer sent by the server. The answer could be an IQ of type result or
* error or null if nothing was received.
*/
public IQ query(Component component, IQ packet, int timeout) throws ComponentException;
/**
* Sends an IQ packet to the server and returns immediately. The specified IQResultListener
* will be invoked when an answer is received.
*
* @param component the component sending the packet.
* @param packet the IQ packet to send.
* @param listener the listener that will be invoked when an answer is received.
*/
public void query(Component component, IQ packet, IQResultListener listener) throws ComponentException;
/**
* Returns a property value specified by name. Properties can be used by
* components to store configuration data. It is recommended that each
* component qualify property names to prevent overlap. For example a
* component that broadcasts messages to groups of users, might prepend
* all property names it uses with "broadcast.".
*
* @param name the property name.
* @return the property value.
*/
public String getProperty(String name);
/**
* Sets a property value. Properties can be used by components to
* store configuration data. It is recommended that each component
* qualify property names to prevent overlap. For example a component
* that broadcasts messages to groups of users, might prepend all
* property names it uses with "broadcast.".
*
* @param name the property name.
* @param value the property value.
*/
public void setProperty(String name, String value);
/**
* Returns the domain of the XMPP server. The domain name may be the IP address or the host
* name.
*
* @return the domain of the XMPP server.
*/
public String getServerName();
/**
* Returns true if components managed by this component manager are external
* components connected to the server over a network connection. Otherwise,
* the components are internal to the server.
*
* @return true if the managed components are external components.
*/
public boolean isExternalMode();
/**
* Returns a Log instance, which can be used by components for logging error,
* warning, info, and debug messages.
*
* @return a Log instance.
*/
public Log getLog();
}
\ No newline at end of file
/**
* Copyright (C) 2004-2008 Jive Software. All rights reserved.
*
* This software is published under the terms of the GNU Public License (GPL),
* a copy of which is included in this distribution, or a commercial license
* agreement with Jive.
*/
package org.xmpp.component;
/**
* Factory to get a ComponentManager implementation. The ComponentManager implementation
* used will determined in the following way:<ul>
*
* <li>An external process can set the ComponentManager using
* {@link #setComponentManager(ComponentManager)}.
* <li>If the component manager is <tt>null</tt>, the factory will check for
* the Java system property "whack.componentManagerClass". The value of the
* property should be the fully qualified class name of a ComponentManager
* implementation (e.g. com.foo.MyComponentManager). The class must have a default
* constructor.
* </ul>
*
* @author Matt Tucker
*/
public class ComponentManagerFactory {
private static ComponentManager componentManager;
/**
* Returns a ComponentManager instance.
*
* @return a ComponentManager instance.
*/
public static synchronized ComponentManager getComponentManager() {
if (componentManager != null) {
return componentManager;
}
// ComponentManager is null so we have to try to figure out how to load
// an instance. Look for a Java property.
String className = System.getProperty("whack.componentManagerClass");
if (className != null) {
try {
Class c = Class.forName(className);
componentManager = (ComponentManager)c.newInstance();
return componentManager;
}
catch (Exception e) {
e.printStackTrace();
}
}
// Got here, so throw exception.
throw new NullPointerException("No ComponentManager implementation available.");
}
/**
* Sets the ComponentManager instance that will be used.
*
* @param manager the ComponentManager instance.
*/
public static void setComponentManager(ComponentManager manager) {
componentManager = manager;
}
}
/**
* Copyright (C) 2004-2008 Jive Software. All rights reserved.
*
* This software is published under the terms of the GNU Public License (GPL),
* a copy of which is included in this distribution, or a commercial license
* agreement with Jive.
*/
package org.xmpp.component;
/**
* A simple logging service for components. Four log levels are provided:<ul>
*
* <li>Error -- an error occured in the component.
* <li>Warn -- a condition occured that an administrator should be warned about.
* <li>Info -- used to send information messages, such as a version or license notice.
* <li>Debug -- used to send debugging information. Most Log implementations will
* disable debug output by default.
* </ul>
*
* Log implementations will attempt use the native logging service of the component host
* server. However, this may not be possible in some cases -- for example, when using an
* external component that is not currently connected to the server.
*
* @author Matt Tucker
*/
public interface Log {
/**
* Logs an error.
*
* @param message the error message.
*/
public void error(String message);
/**
* Logs an error.
*
* @param message the error message.
* @param throwable the Throwable that caused the error.
*/
public void error(String message, Throwable throwable);
/**
* Logs an error.
*
* @param throwable the Throwable that caused the error.
*/
public void error(Throwable throwable);
/**
* Logs a warning.
*
* @param message the warning message.
*/
public void warn(String message);
/**
* Logs a warning.
*
* @param message the warning message.
* @param throwable the Throwable that caused the error.
*/
public void warn(String message, Throwable throwable);
/**
* Logs a warning.
*
* @param throwable the Throwable that caused the error.
*/
public void warn(Throwable throwable);
/**
* Logs an info message.
*
* @param message the info message.
*/
public void info(String message);
/**
* Logs an info message.
*
* @param message the info message.
* @param throwable the Throwable that caused the info message.
*/
public void info(String message, Throwable throwable);
/**
* Logs an info message.
*
* @param throwable the Throwable that caused the info message.
*/
public void info(Throwable throwable);
/**
* Logs a debug message.
*
* @param message the debug message.
*/
public void debug(String message);
/**
* Logs a debug message.
*
* @param message the debug message.
* @param throwable the Throwable that caused the debug message.
*/
public void debug(String message, Throwable throwable);
/**
* Logs a debug message.
*
* @param throwable the Throwable the caused the debug message.
*/
public void debug(Throwable throwable);
}
\ No newline at end of file
This diff is collapsed.
This diff is collapsed.
/**
* Copyright (C) 2004-2008 Jive Software. All rights reserved.
*
* This software is published under the terms of the GNU Public License (GPL),
* a copy of which is included in this distribution, or a commercial license
* agreement with Jive.
*/
package org.xmpp.muc;
import org.dom4j.Element;
import org.xmpp.packet.IQ;
import org.xmpp.packet.JID;
/**
* DestroyRoom is a packet that when sent will ask the server to destroy a given room. The room to
* destroy must be specified in the TO attribute of the IQ packet. The server will send a presence
* unavailable together with the alternate room and reason for the destruction to all the room
* occupants before destroying the room.<p>
*
* When destroying a room it is possible to provide an alternate room which may be replacing the
* room about to be destroyed. It is also possible to provide a reason for the room destruction.
*/
public class DestroyRoom extends IQ {
/**
* Creates a new DestroyRoom with the reason for the destruction and an alternate room JID.
*
* @param alternateJID JID of the alternate room or <tt>null</tt> if none.
* @param reason reason for the destruction or <tt>null</tt> if none.
*/
public DestroyRoom(JID alternateJID, String reason) {
super();
setType(Type.set);
Element query = setChildElement("query", "http://jabber.org/protocol/muc#owner");
Element destroy = query.addElement("destroy");
if (alternateJID != null) {
destroy.addAttribute("jid", alternateJID.toString());
}
if (reason != null) {
destroy.addElement("reason").setText(reason);
}
}
}
/**
* Copyright (C) 2004-2008 Jive Software. All rights reserved.
*
* This software is published under the terms of the GNU Public License (GPL),
* a copy of which is included in this distribution, or a commercial license
* agreement with Jive.
*/
package org.xmpp.muc;
import org.dom4j.Element;
import org.xmpp.packet.Message;
/**
* Represents an invitation to a Multi-User Chat room from a room occupant to a user that is not
* an occupant of the room. The invitation must be <b>sent to the room</b> and it's the room
* responsibility to forward the invitation to the invitee. The <b>sender of the invitation must be
* the real full JID of the inviter</b>.<p>
*
* Code example:
* <pre>
* // Invite the someone to the room.
* Invitation invitation = new Invitation("invitee@jabber.org", "Join this excellent room");
* invitation.setTo("room@conference.jabber.org");
* invitation.setFrom("inviter@jabber.org/notebook");
*
* component.sendPacket(invitation);
* </pre>
*
* @author Gaston Dombiak
*/
public class Invitation extends Message {
/**
* Creates a new invitation.
*
* @param invitee the XMPP address of the invitee. The room will forward the invitation to this
* address.
* @param reason the reason why the invitation is being sent.
*/
public Invitation(String invitee, String reason) {
super();
Element element = addChildElement("x", "http://jabber.org/protocol/muc#user");
Element invite = element.addElement("invite");
invite.addAttribute("to", invitee);
if (reason != null && reason.length() > 0) {
invite.addElement("reason").setText(reason);
}
}
}
/**
* Copyright (C) 2004-2008 Jive Software. All rights reserved.
*
* This software is published under the terms of the GNU Public License (GPL),
* a copy of which is included in this distribution, or a commercial license
* agreement with Jive.
*/
package org.xmpp.muc;
import org.xmpp.packet.Presence;
/**
* Initial presence sent when joining an existing room or creating a new room. The JoinRoom presence
* indicates the posibility of the sender to speak MUC.<p>
*
* Code example:
* <pre>
* // Join an existing room or create a new one.
* JoinRoom joinRoom = new JoinRoom("john@jabber.org/notebook", "room@conference.jabber.org/nick");
*
* component.sendPacket(joinRoom);
* </pre>
*
* @author Gaston Dombiak
*/
public class JoinRoom extends Presence {
/**
* Creates a new Presence packet that could be sent to a MUC service in order to join
* an existing MUC room or create a new one.
*
* @param from the real full JID of the user that will join or create a MUC room.
* @param to a full JID where the bare JID is the MUC room address and the resource is the
* nickname of the user joining the room.
*/
public JoinRoom(String from, String to) {
super();
setFrom(from);
setTo(to);
addChildElement("x", "http://jabber.org/protocol/muc");
}
}
/**
* Copyright (C) 2004-2008 Jive Software. All rights reserved.
*
* This software is published under the terms of the GNU Public License (GPL),
* a copy of which is included in this distribution, or a commercial license
* agreement with Jive.
*/
package org.xmpp.muc;
import org.xmpp.packet.Presence;
/**
* Initial presence sent when joining an existing room or creating a new room. The JoinRoom presence
* indicates the posibility of the sender to speak MUC.<p>
*
* Code example:
* <pre>
* // Join an existing room or create a new one.
* JoinRoom joinRoom = new JoinRoom("john@jabber.org/notebook", "room@conference.jabber.org/nick");
*
* component.sendPacket(joinRoom);
* </pre>
*
* @author Gaston Dombiak
*/
public class LeaveRoom extends Presence {
/**
* Creates a new Presence packet that could be sent to a MUC service in order to leave the room.
*
* @param from the full JID of the user that wants to leave the room.
* @param to the room JID. That is the room address plus the nickname of the user as a resource.
*/
public LeaveRoom(String from, String to) {
super();
setFrom(from);
setTo(to);
setType(Type.unavailable);
}
}
/**
* Copyright (C) 2004-2008 Jive Software. All rights reserved.
*
* This software is published under the terms of the GNU Public License (GPL),
* a copy of which is included in this distribution, or a commercial license
* agreement with Jive.
*/
package org.xmpp.muc;
import org.dom4j.Element;
import org.xmpp.packet.IQ;
import java.util.Collection;
import java.util.Map;
/**
* RoomConfiguration is a packet that helps to set the configuration of MUC rooms. RoomConfiguration
* is a speacial IQ packet whose child element contains a data form. The data form holds the fields
* to set together with a list of values.<p>
*
* Code example:
* <pre>
* // Set the fields and the values.
* Map<String,Collection<String>> fields = new HashMap<String,Collection<String>>();
* // Make a non-public room
* List<String> values = new ArrayList<String>();
* values.add("0");
* fields.put("muc#roomconfig_publicroom", values);
*
* // Create a RoomConfiguration with the fields and values
* RoomConfiguration conf = new RoomConfiguration(fields);
* conf.setTo("room@conference.jabber.org");
* conf.setFrom("john@jabber.org/notebook");
*
* component.sendPacket(conf);
* </pre>
*
* @author Gaston Dombiak
*/
public class RoomConfiguration extends IQ {
/**
* Creates a new IQ packet that contains the field and values to send for setting the room
* configuration.
*
* @param fieldValues the list of fields associated with the list of values.
*/
public RoomConfiguration(Map<String,Collection<String>> fieldValues) {
super();
setType(Type.set);
Element query = setChildElement("query", "http://jabber.org/protocol/muc#owner");
Element form = query.addElement("x", "jabber:x:data");
form.addAttribute("type", "submit");
// Add static field
Element field = form.addElement("field");
field.addAttribute("var", "FORM_TYPE");
field.addElement("value").setText("http://jabber.org/protocol/muc#roomconfig");
// Add the specified fields and their corresponding values
for (String variable : fieldValues.keySet()) {
field = form.addElement("field");
field.addAttribute("var", variable);
for (String value : fieldValues.get(variable)) {
field.addElement("value").setText(value);
}
}
}
}
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
/**
* Copyright (C) 2004-2008 Jive Software. All rights reserved.
*
* This software is published under the terms of the GNU Public License (GPL),
* a copy of which is included in this distribution, or a commercial license
* agreement with Jive.
*/
package org.xmpp.packet;
import org.dom4j.DocumentFactory;
import org.dom4j.Element;
import org.dom4j.QName;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* A packet extension represents a child element of a Packet for a given qualified name. The
* PacketExtension acts as a wrapper on a child element the same way Packet does for a whole
* element. The wrapper provides an easy way to handle the packet extension.<p>
*
* Subclasses of this class can be registered using the static variable
* <tt>registeredExtensions</tt>. The registration process associates the new subclass
* with a given qualified name (ie. element name and namespace). This information will be used by
* {@link Packet#getExtension(String, String)} for locating the corresponding PacketExtension
* subclass to return for the requested qualified name. Each PacketExtension must have a public
* constructor that takes an Element instance as an argument.
*
* @author Gaston Dombiak
*/
public class PacketExtension {
protected static DocumentFactory docFactory = DocumentFactory.getInstance();
/**
* Subclasses of PacketExtension should register the element name and namespace that the
* subclass is using.
*/
protected static Map<QName, Class> registeredExtensions = new ConcurrentHashMap<QName, Class>();
protected Element element;
/**
* Returns the extension class to use for the specified element name and namespace. For
* instance, the DataForm class should be used for the element "x" and
* namespace "jabber:x:data".
*
* @param name the child element name.
* @param namespace the child element namespace.
* @return the extension class to use for the specified element name and namespace.
*/
public static Class getExtensionClass(String name, String namespace) {
return registeredExtensions.get(QName.get(name, namespace));
}
/**
* Constructs a new Packet extension using the specified name and namespace.
*
* @param name the child element name.
* @param namespace the child element namespace.
*/
public PacketExtension(String name, String namespace) {
this.element = docFactory.createDocument().addElement(name, namespace);
}
/**
* Constructs a new PacketExtension.
*
* @param element the XML Element that contains the packet extension contents.
*/
public PacketExtension(Element element) {
this.element = element;
}
/**
* Returns the DOM4J Element that backs the packet. The element is the definitive
* representation of the packet and can be manipulated directly to change
* packet contents.
*
* @return the DOM4J Element that represents the packet.
*/
public Element getElement() {
return element;
}
/**
* Creates a deep copy of this packet extension.
*
* @return a deep copy of this packet extension.
*/
public PacketExtension createCopy() {
Element copy = element.createCopy();
docFactory.createDocument().add(copy);
return new PacketExtension(element);
}
}
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment