use of org.jivesoftware.smackx.xdata.Form in project Smack by igniterealtime.
the class Workgroup method joinQueue.
/**
* <p>Joins the workgroup queue to wait to be routed to an agent. After joining
* the queue, queue status events will be sent to indicate the user's position and
* estimated time left in the queue. Once joining the queue, there are three ways
* the user can leave the queue: <ul>
* <p/>
* <li>The user is routed to an agent, which triggers a GroupChat invitation.
* <li>The user asks to leave the queue by calling the {@link #departQueue} method.
* <li>A server error occurs, or an administrator explicitly removes the user
* from the queue.
* </ul>
* <p/>
* A user cannot request to join the queue again if already in the queue. Therefore,
* this method will throw an IllegalStateException if the user is already in the queue.<p>
* <p/>
* Some servers may be configured to require certain meta-data in order to
* join the queue.<p>
* <p/>
* The server tracks the conversations that a user has with agents over time. By
* default, that tracking is done using the user's JID. However, this is not always
* possible. For example, when the user is logged in anonymously using a web client.
* In that case the user ID might be a randomly generated value put into a persistent
* cookie or a username obtained via the session. When specified, that userID will
* be used instead of the user's JID to track conversations. The server will ignore a
* manually specified userID if the user's connection to the server is not anonymous.
*
* @param metadata metadata to create a dataform from.
* @param userID String that represents the ID of the user when using anonymous sessions
* or <tt>null</tt> if a userID should not be used.
* @throws XMPPException if an error occured joining the queue. An error may indicate
* that a connection failure occured or that the server explicitly rejected the
* request to join the queue.
* @throws SmackException
* @throws InterruptedException
*/
public void joinQueue(Map<String, Object> metadata, Jid userID) throws XMPPException, SmackException, InterruptedException {
// If already in the queue ignore the join request.
if (inQueue) {
throw new IllegalStateException("Already in queue " + workgroupJID);
}
// Build dataform from metadata
Form form = new Form(DataForm.Type.submit);
Iterator<String> iter = metadata.keySet().iterator();
while (iter.hasNext()) {
String name = iter.next();
String value = metadata.get(name).toString();
FormField field = new FormField(name);
field.setType(FormField.Type.text_single);
form.addField(field);
form.setAnswer(name, value);
}
joinQueue(form, userID);
}
use of org.jivesoftware.smackx.xdata.Form in project Smack by igniterealtime.
the class ServiceAdministrationManager method addUser.
public void addUser(final EntityBareJid userJid, final String password) throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException {
RemoteCommand command = addUser();
command.execute();
Form answerForm = command.getForm().createAnswerForm();
FormField accountJidField = answerForm.getField("accountjid");
accountJidField.addValue(userJid.toString());
FormField passwordField = answerForm.getField("password");
passwordField.addValue(password);
FormField passwordVerifyField = answerForm.getField("password-verify");
passwordVerifyField.addValue(password);
command.next(answerForm);
assert (command.isCompleted());
}
use of org.jivesoftware.smackx.xdata.Form in project Smack by igniterealtime.
the class NodeUtils method getFormFromPacket.
/**
* Get a {@link ConfigureForm} from a packet.
*
* @param packet
* @param elem
* @return The configuration form
*/
public static ConfigureForm getFormFromPacket(Stanza packet, PubSubElementType elem) {
FormNode config = packet.getExtension(elem.getElementName(), elem.getNamespace().getXmlns());
Form formReply = config.getForm();
return new ConfigureForm(formReply);
}
use of org.jivesoftware.smackx.xdata.Form in project Smack by igniterealtime.
the class OfflineMessageManager method getMessageCount.
/**
* Returns the number of offline messages for the user of the connection.
*
* @return the number of offline messages for the user of the connection.
* @throws XMPPErrorException If the user is not allowed to make this request or the server does
* not support offline message retrieval.
* @throws NoResponseException if there was no response from the server.
* @throws NotConnectedException
* @throws InterruptedException
*/
public int getMessageCount() throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException {
DiscoverInfo info = ServiceDiscoveryManager.getInstanceFor(connection).discoverInfo(null, namespace);
Form extendedInfo = Form.getFormFrom(info);
if (extendedInfo != null) {
String value = extendedInfo.getField("number_of_messages").getValues().get(0);
return Integer.parseInt(value);
}
return 0;
}
use of org.jivesoftware.smackx.xdata.Form in project Smack by igniterealtime.
the class AdHocCommandManager method processAdHocCommand.
/**
* Process the AdHoc-Command stanza(/packet) that request the execution of some
* action of a command. If this is the first request, this method checks,
* before executing the command, if:
* <ul>
* <li>The requested command exists</li>
* <li>The requester has permissions to execute it</li>
* <li>The command has more than one stage, if so, it saves the command and
* session ID for further use</li>
* </ul>
*
* <br>
* <br>
* If this is not the first request, this method checks, before executing
* the command, if:
* <ul>
* <li>The session ID of the request was stored</li>
* <li>The session life do not exceed the time out</li>
* <li>The action to execute is one of the available actions</li>
* </ul>
*
* @param requestData
* the stanza(/packet) to process.
* @throws NotConnectedException
* @throws NoResponseException
* @throws InterruptedException
*/
private IQ processAdHocCommand(AdHocCommandData requestData) throws NoResponseException, NotConnectedException, InterruptedException {
// Creates the response with the corresponding data
AdHocCommandData response = new AdHocCommandData();
response.setTo(requestData.getFrom());
response.setStanzaId(requestData.getStanzaId());
response.setNode(requestData.getNode());
response.setId(requestData.getTo());
String sessionId = requestData.getSessionID();
String commandNode = requestData.getNode();
if (sessionId == null) {
// command exists
if (!commands.containsKey(commandNode)) {
// item_not_found error.
return respondError(response, XMPPError.Condition.item_not_found);
}
// Create new session ID
sessionId = StringUtils.randomString(15);
try {
// Create a new instance of the command with the
// corresponding sessioid
LocalCommand command = newInstanceOfCmd(commandNode, sessionId);
response.setType(IQ.Type.result);
command.setData(response);
// enough to execute the requested command
if (!command.hasPermission(requestData.getFrom())) {
return respondError(response, XMPPError.Condition.forbidden);
}
Action action = requestData.getAction();
// If the action is unknown then respond an error.
if (action != null && action.equals(Action.unknown)) {
return respondError(response, XMPPError.Condition.bad_request, AdHocCommand.SpecificErrorCondition.malformedAction);
}
// If the action is not execute, then it is an invalid action.
if (action != null && !action.equals(Action.execute)) {
return respondError(response, XMPPError.Condition.bad_request, AdHocCommand.SpecificErrorCondition.badAction);
}
// Increase the state number, so the command knows in witch
// stage it is
command.incrementStage();
// Executes the command
command.execute();
if (command.isLastStage()) {
// If there is only one stage then the command is completed
response.setStatus(Status.completed);
} else {
// Else it is still executing, and is registered to be
// available for the next call
response.setStatus(Status.executing);
executingCommands.put(sessionId, command);
// See if the session reaping thread is started. If not, start it.
if (sessionsSweeper == null) {
sessionsSweeper = new Thread(new Runnable() {
@Override
public void run() {
while (true) {
for (String sessionId : executingCommands.keySet()) {
LocalCommand command = executingCommands.get(sessionId);
// map.
if (command != null) {
long creationStamp = command.getCreationDate();
// invalid session error and not a time out error.
if (System.currentTimeMillis() - creationStamp > SESSION_TIMEOUT * 1000 * 2) {
// Remove the expired session
executingCommands.remove(sessionId);
}
}
}
try {
Thread.sleep(1000);
} catch (InterruptedException ie) {
// Ignore.
}
}
}
});
sessionsSweeper.setDaemon(true);
sessionsSweeper.start();
}
}
// Sends the response packet
return response;
} catch (XMPPErrorException e) {
// If there is an exception caused by the next, complete,
// prev or cancel method, then that error is returned to the
// requester.
XMPPError error = e.getXMPPError();
// command be removed from the executing list.
if (XMPPError.Type.CANCEL.equals(error.getType())) {
response.setStatus(Status.canceled);
executingCommands.remove(sessionId);
}
return respondError(response, XMPPError.getBuilder(error));
}
} else {
LocalCommand command = executingCommands.get(sessionId);
// of getting the key and the value of the map.
if (command == null) {
return respondError(response, XMPPError.Condition.bad_request, AdHocCommand.SpecificErrorCondition.badSessionid);
}
// Check if the Session data has expired (default is 10 minutes)
long creationStamp = command.getCreationDate();
if (System.currentTimeMillis() - creationStamp > SESSION_TIMEOUT * 1000) {
// Remove the expired session
executingCommands.remove(sessionId);
// Answer a not_allowed error (session-expired)
return respondError(response, XMPPError.Condition.not_allowed, AdHocCommand.SpecificErrorCondition.sessionExpired);
}
/*
* Since the requester could send two requests for the same
* executing command i.e. the same session id, all the execution of
* the action must be synchronized to avoid inconsistencies.
*/
synchronized (command) {
Action action = requestData.getAction();
// If the action is unknown the respond an error
if (action != null && action.equals(Action.unknown)) {
return respondError(response, XMPPError.Condition.bad_request, AdHocCommand.SpecificErrorCondition.malformedAction);
}
// action then follow the actual default execute action
if (action == null || Action.execute.equals(action)) {
action = command.getExecuteAction();
}
// offered
if (!command.isValidAction(action)) {
return respondError(response, XMPPError.Condition.bad_request, AdHocCommand.SpecificErrorCondition.badAction);
}
try {
// TODO: Check that all the required fields of the form are
// TODO: filled, if not throw an exception. This will simplify the
// TODO: construction of new commands
// Since all errors were passed, the response is now a
// result
response.setType(IQ.Type.result);
// Set the new data to the command.
command.setData(response);
if (Action.next.equals(action)) {
command.incrementStage();
command.next(new Form(requestData.getForm()));
if (command.isLastStage()) {
// If it is the last stage then the command is
// completed
response.setStatus(Status.completed);
} else {
// Otherwise it is still executing
response.setStatus(Status.executing);
}
} else if (Action.complete.equals(action)) {
command.incrementStage();
command.complete(new Form(requestData.getForm()));
response.setStatus(Status.completed);
// Remove the completed session
executingCommands.remove(sessionId);
} else if (Action.prev.equals(action)) {
command.decrementStage();
command.prev();
} else if (Action.cancel.equals(action)) {
command.cancel();
response.setStatus(Status.canceled);
// Remove the canceled session
executingCommands.remove(sessionId);
}
return response;
} catch (XMPPErrorException e) {
// If there is an exception caused by the next, complete,
// prev or cancel method, then that error is returned to the
// requester.
XMPPError error = e.getXMPPError();
// command be removed from the executing list.
if (XMPPError.Type.CANCEL.equals(error.getType())) {
response.setStatus(Status.canceled);
executingCommands.remove(sessionId);
}
return respondError(response, XMPPError.getBuilder(error));
}
}
}
}
Aggregations