use of org.jivesoftware.xmpp.workgroup.request.UserRequest in project Openfire by igniterealtime.
the class RoundRobinDispatcher method dispatch.
/**
* Dispatch the given request to one or more agents in the agent pool.<p>
*
* If this method returns, it is assumed that the request was properly
* dispatched.The only exception is if an agent is not in the pool for routing
* within the agent timeout period, the dispatch will throw an AgentNotFoundException
* so the request can be re-routed.
*
* @param offer the offer to send to the best agent available.
*/
public void dispatch(Offer offer) {
// The time when the request should timeout
long timeoutTime = System.currentTimeMillis() + info.getRequestTimeout();
final Request request = offer.getRequest();
boolean canBeInQueue = request instanceof UserRequest;
Map<String, List<String>> map = request.getMetaData();
String initialAgent = map.get("agent") == null || map.get("agent").isEmpty() ? null : map.get("agent").get(0);
String ignoreAgent = map.get("ignore") == null || map.get("ignore").isEmpty() ? null : map.get("ignore").get(0);
// Log debug trace
Log.debug("RR - Dispatching request: " + request + " in queue: " + queue.getAddress());
// to overflow the current request
if (!agentList.isEmpty()) {
for (long timeRemaining = timeoutTime - System.currentTimeMillis(); !offer.isAccepted() && timeRemaining > 0 && !offer.isCancelled(); timeRemaining = timeoutTime - System.currentTimeMillis()) {
try {
AgentSession session = getBestNextAgent(initialAgent, ignoreAgent, offer);
if (session == null && agentList.isEmpty()) {
// Stop looking for an agent since there are no more agent available
break;
} else if (session == null || offer.isRejector(session)) {
initialAgent = null;
Thread.sleep(1000);
} else {
// Recheck for changed maxchat setting
Workgroup workgroup = request.getWorkgroup();
if (session.getCurrentChats(workgroup) < session.getMaxChats(workgroup)) {
// Set the timeout of the offer based on the remaining time of the
// initial request and the default offer timeout
timeRemaining = timeoutTime - System.currentTimeMillis();
offer.setTimeout(timeRemaining < info.getOfferTimeout() ? timeRemaining : info.getOfferTimeout());
// Make the offer and wait for a resolution to the offer
if (!request.sendOffer(session, queue)) {
// Log debug trace
Log.debug("RR - Offer for request: " + offer.getRequest() + " FAILED TO BE SENT to agent: " + session.getJID());
continue;
}
// Log debug trace
Log.debug("RR - Offer for request: " + offer.getRequest() + " SENT to agent: " + session.getJID());
offer.waitForResolution();
// and reset the offer
if (offer.isAccepted()) {
// Get the first agent that accepted the offer
AgentSession selectedAgent = offer.getAcceptedSessions().get(0);
// Log debug trace
Log.debug("RR - Agent: " + selectedAgent.getJID() + " ACCEPTED request: " + request);
// Create the room and send the invitations
offer.invite(selectedAgent);
// has finished
for (AgentSession agent : offer.getAcceptedSessions()) {
agent.removeOffer(offer);
}
if (canBeInQueue) {
// Remove the user from the queue since his request has
// been accepted
queue.removeRequest((UserRequest) request);
}
}
} else {
// Log debug trace
Log.debug("RR - Selected agent: " + session.getJID() + " has reached max number of chats");
}
}
} catch (Exception e) {
Log.error(e.getMessage(), e);
}
}
}
if (!offer.isAccepted() && !offer.isCancelled()) {
// Calculate the maximum time limit for an unattended request before cancelling it
long limit = request.getCreationTime().getTime() + (info.getRequestTimeout() * (getOverflowTimes() + 1));
if (limit - System.currentTimeMillis() <= 0 || !canBeInQueue) {
// Log debug trace
Log.debug("RR - Cancelling request that maxed out overflow limit or cannot be queued: " + request);
// Cancel the request if it has overflowed 'n' times
request.cancel(Request.CancelType.AGENT_NOT_FOUND);
} else {
// Overflow if request timed out and was not dispatched and max number of overflows
// has not been reached yet
overflow(offer);
// If there is no other queue to overflow then cancel the request
if (!offer.isAccepted() && !offer.isCancelled()) {
// Log debug trace
Log.debug("RR - Cancelling request that didn't overflow: " + request);
request.cancel(Request.CancelType.AGENT_NOT_FOUND);
}
}
}
}
use of org.jivesoftware.xmpp.workgroup.request.UserRequest in project Openfire by igniterealtime.
the class Chatbot method handleCommand.
/**
* Returns true if the message sent by the user requested to run a command. Depending on the
* stage of the conversation different commands may be executed.
*
* @param message the message.
* @param session the session.
* @return true if the message sent by the user requested to run a command.
*/
private boolean handleCommand(Message message, ChatbotSession session) {
String command = message.getBody().trim();
if (getHelpCommand().equalsIgnoreCase(command)) {
sendHelpMessage(message);
return true;
} else if (getByeCommand().equalsIgnoreCase(command)) {
userDepartQueue(message);
return true;
}
if (session.getCurrentStep() == 1) {
if (getRepeatCommand().equalsIgnoreCase(command)) {
// Send the join question
sendJoinQuestion(message, session);
return true;
} else if (getPositionCommand().equalsIgnoreCase(command)) {
// Tell the user that he is not waiting in the queue
sendReply(message, getNotInQueueMessage());
return true;
}
} else if (session.getCurrentStep() == 2) {
if (getBackCommand().equalsIgnoreCase(command)) {
sendPreviousQuestion(message, session);
return true;
} else if (getRepeatCommand().equalsIgnoreCase(command)) {
// Resend the last question
repeatQuestion(message, session);
return true;
} else if (getPositionCommand().equalsIgnoreCase(command)) {
// Tell the user that he is not waiting in the queue
sendReply(message, getNotInQueueMessage());
return true;
}
} else if (session.getCurrentStep() == 3) {
if (getPositionCommand().equalsIgnoreCase(command)) {
try {
UserRequest request = UserRequest.getRequest(workgroup, message.getFrom());
request.updateQueueStatus(true);
} catch (NotFoundException e) {
// Tell the user that he is not waiting in the queue
sendReply(message, getNotInQueueMessage());
}
return true;
}
} else if (session.getCurrentStep() == 6) {
if (getRepeatCommand().equalsIgnoreCase(command)) {
// Resend the last question
sendEmailQuestion(message.getFrom(), session);
return true;
}
} else if (session.getCurrentStep() == 7) {
if (getRepeatCommand().equalsIgnoreCase(command)) {
// Resend the last question
sendGetEmailQuestion(message, session);
return true;
}
}
return false;
}
use of org.jivesoftware.xmpp.workgroup.request.UserRequest in project Openfire by igniterealtime.
the class Chatbot method userJoinQueue.
private void userJoinQueue(Message message, ChatbotSession session) {
InterceptorManager interceptorManager = QueueInterceptorManager.getInstance();
try {
interceptorManager.invokeInterceptors(workgroup.getJID().toBareJID(), message, true, false);
if (getRoutingMessage() != null && getRoutingMessage().length() > 0) {
sendReply(message, getRoutingMessage());
}
// Set that we are currently joining a waiting queue
session.setCurrentStep(3);
// Received a Join Queue request from a visitor, create a new request.
UserRequest request = new UserRequest(session, workgroup);
// Let the workgroup process the new request
if (!workgroup.queueRequest(request)) {
// It was not possible to add the request to a queue so send message saying that
// the workgroup is not accepting new join requests
sendReply(message, getCannotJoinMessage());
// Send the goodbye message and close the session
closeSession(message);
} else {
session.setRequest(request);
}
interceptorManager.invokeInterceptors(workgroup.getJID().toBareJID(), message, true, true);
} catch (PacketRejectedException e) {
workgroup.rejectPacket(message, e);
}
}
use of org.jivesoftware.xmpp.workgroup.request.UserRequest in project Openfire by igniterealtime.
the class Workgroup method roomActivity.
// ###############################################################################
// MUC related packets
// ###############################################################################
/**
* Notification message indicating that there has been new activity in a room. This implies
* that we need to update the conversation transcript of the group chat room and possibly
* update the number of occupants within the room.<p>
* <p/>
* If only the workgroup is present in the room then leave the room (i.e. destroying room) and
* proceed to save the room conversation transcript to the database.<p>
*
* @param packet the packet that was sent to the group chat room.
*/
private void roomActivity(Packet packet) {
// Skip packet sent from this workgroup in the room
if (packet.getFrom().toBareJID().equals(getGroupChatRoomName())) {
return;
}
RoomInterceptorManager interceptorManager = RoomInterceptorManager.getInstance();
String roomID = packet.getFrom().getNode();
// Get the sessionID
String sessionID = packet.getFrom().getNode();
synchronized (sessionID.intern()) {
if (packet instanceof Presence) {
Presence presence = (Presence) packet;
if (Presence.Type.error == presence.getType()) {
// A configuration must be wrong (eg. workgroup is not allowed to create rooms).
// Log the error presence
String warnMessage = "Possible server misconfiguration. Received error " + "presence:" + presence.toXML();
Log.warn(warnMessage);
return;
}
// Get the JID of the presence's user
Element mucUser = presence.getChildElement("x", "http://jabber.org/protocol/muc#user");
// Skip this presence if no extended info was included in the presence
if (mucUser == null) {
return;
}
Element item = mucUser.element("item");
// Skip this presence if no item was included in the presence
if (item == null) {
return;
}
// Skip this presence if it's the presence of this workgroup in the room
if (workgroupName.equals(packet.getFrom().getResource())) {
return;
}
JID presenceFullJID = new JID(item.attributeValue("jid"));
String presenceJID = presenceFullJID.toBareJID();
// Invoke the room interceptor before processing the presence
interceptorManager.invokeInterceptors(getJID().toBareJID(), packet, false, false);
// Get the userID associated to this sessionID
UserRequest initialRequest = requests.get(sessionID);
// Add the new presence to the list of sent packets
Map<Packet, java.util.Date> messageList = transcripts.get(roomID);
if (messageList == null) {
messageList = new LinkedHashMap<Packet, java.util.Date>();
transcripts.put(roomID, messageList);
// Trigger the event that a chat support has started
WorkgroupEventDispatcher.chatSupportStarted(this, sessionID);
}
messageList.put(packet.createCopy(), new java.util.Date());
// Update the number of occupants in the room.
boolean occupantAdded = false;
Set<String> set = occupantsCounter.get(roomID);
if (set == null) {
set = new HashSet<String>();
occupantsCounter.put(roomID, set);
}
if (presence.isAvailable()) {
occupantAdded = set.add(presenceJID);
} else {
String xpath = "/presence/*[name()='x']/*[name()='status']";
Element status = (Element) presence.getElement().selectSingleNode(xpath);
if (status == null || !"303".equals(status.attributeValue("code"))) {
// Remove the occupant unless the occupant is changing his nickname
set.remove(presenceJID);
}
}
// If the presence belongs to an Agent then create/update a track
// Look for an agent whose JID matches the presence's JID
String agentJID = null;
for (Agent agent : getAgents()) {
if (agent.getAgentJID().toBareJID().equals(presenceJID)) {
agentJID = agent.getAgentJID().toBareJID();
}
}
if (agentJID != null) {
AgentSession agentSession;
// Update the current chats that the agent is having
try {
agentSession = agentManager.getAgentSession(presenceFullJID);
if (agentSession != null) {
if (presence.isAvailable()) {
if (occupantAdded) {
agentSession.addChatInfo(this, sessionID, initialRequest, new java.util.Date());
// Trigger the event that an agent has joined a chat session
WorkgroupEventDispatcher.agentJoinedChatSupport(this, sessionID, agentSession);
}
} else {
agentSession.removeChatInfo(this, sessionID);
// Trigger the event that an agent has left a chat session
WorkgroupEventDispatcher.agentLeftChatSupport(this, sessionID, agentSession);
}
}
} catch (AgentNotFoundException e) {
// Do nothing since the AgentSession was not found
}
if (presence.isAvailable()) {
if (occupantAdded) {
// Store in the DB that an agent has joined a room
DbWorkgroup.updateJoinedSession(sessionID, agentJID, true);
}
} else {
// Store in the DB that an agent has left a room
DbWorkgroup.updateJoinedSession(sessionID, agentJID, false);
}
} else {
if (occupantAdded) {
// Notify the request that the user has joined a support session
initialRequest.supportStarted(roomID);
}
}
if (occupantAdded) {
initialRequest.userJoinedRoom(new JID(packet.getFrom().toBareJID()), presenceFullJID);
}
// If just the user has left the room, just persist the transcript
boolean isAgent = false;
try {
isAgent = agentManager.getAgentSession(presenceFullJID) != null;
} catch (AgentNotFoundException e) {
// Ignore.
}
if (!((Presence) packet).isAvailable() && !isAgent) {
// Build the XML for the transcript
Map<Packet, java.util.Date> map = transcripts.get(roomID);
StringBuilder buf = new StringBuilder();
buf.append("<transcript>");
for (Packet p : map.keySet()) {
java.util.Date date = map.get(p);
// Add the delay information
if (p instanceof Message) {
Message storedMessage = (Message) p;
Element delay = storedMessage.addChildElement("x", "jabber:x:delay");
delay.addAttribute("stamp", UTC_FORMAT.format(date));
if (ModelUtil.hasLength(storedMessage.getBody())) {
buf.append(p.toXML());
}
} else {
Presence storedPresence = (Presence) p;
Element delay = storedPresence.addChildElement("x", "jabber:x:delay");
delay.addAttribute("stamp", UTC_FORMAT.format(date));
buf.append(p.toXML());
}
// Append an XML representation of the packet to the string buffer
}
buf.append("</transcript>");
// Save the transcript (in XML) to the DB
DbWorkgroup.updateTranscript(sessionID, buf.toString(), new java.util.Date());
}
// the DB and destroy the room
if (!((Presence) packet).isAvailable() && set.isEmpty()) {
// Delete the counter of occupants for this room
occupantsCounter.remove(roomID);
initialRequest = requests.remove(sessionID);
if (initialRequest != null && initialRequest.hasJoinedRoom()) {
// Notify the request that the support session has finished
initialRequest.supportEnded();
}
// Build the XML for the transcript
Map<Packet, java.util.Date> map = transcripts.get(roomID);
StringBuilder buf = new StringBuilder();
buf.append("<transcript>");
for (Packet p : map.keySet()) {
java.util.Date date = map.get(p);
// Add the delay information
if (p instanceof Message) {
Message storedMessage = (Message) p;
Element delay = storedMessage.addChildElement("x", "jabber:x:delay");
delay.addAttribute("stamp", UTC_FORMAT.format(date));
if (ModelUtil.hasLength(storedMessage.getBody())) {
buf.append(p.toXML());
}
} else {
Presence storedPresence = (Presence) p;
Element delay = storedPresence.addChildElement("x", "jabber:x:delay");
delay.addAttribute("stamp", UTC_FORMAT.format(date));
buf.append(p.toXML());
}
// Append an XML representation of the packet to the string buffer
}
buf.append("</transcript>");
// Save the transcript (in XML) to the DB
//DbWorkgroup.updateTranscript(sessionID, buf.toString(), new java.util.Date());
// Leave Chat Room (the room will be destroyed)
String roomJID = packet.getFrom().toString() + "/" + getJID().getNode();
LeaveRoom leaveRoom = new LeaveRoom(getFullJID().toString(), roomJID);
send(leaveRoom);
// Remove the transcript information of this room since the room no
// longer exists
transcripts.remove(roomID);
// Trigger the event that a chat support has finished
WorkgroupEventDispatcher.chatSupportFinished(this, sessionID);
}
// Invoke the room interceptor after the presence has been processed
interceptorManager.invokeInterceptors(getJID().toBareJID(), packet, false, true);
} else if (packet instanceof Message) {
// transcript to include things like "room locked"
if (packet.getFrom().getResource() != null) {
// Invoke the room interceptor before processing the presence
interceptorManager.invokeInterceptors(getJID().toBareJID(), packet, false, false);
// Add the new message to the list of sent packets
Map<Packet, java.util.Date> messageList = transcripts.get(roomID);
if (messageList == null) {
messageList = new LinkedHashMap<Packet, java.util.Date>();
transcripts.put(roomID, messageList);
}
messageList.put(packet.createCopy(), new java.util.Date());
// Invoke the room interceptor after the presence has been processed
interceptorManager.invokeInterceptors(getJID().toBareJID(), packet, false, true);
}
}
}
}
use of org.jivesoftware.xmpp.workgroup.request.UserRequest in project Openfire by igniterealtime.
the class RequestQueue method getDetailedStatusPresence.
public Presence getDetailedStatusPresence() {
Presence queueStatus = new Presence();
queueStatus.setFrom(address);
if (workgroup.getStatus() == Workgroup.Status.OPEN && presenceAvailable) {
queueStatus.setType(null);
} else {
queueStatus.setType(Presence.Type.unavailable);
}
Element details = queueStatus.addChildElement("notify-queue-details", "http://jabber.org/protocol/workgroup");
int i = 0;
for (UserRequest request : getRequests()) {
Element user = details.addElement("user", "http://jabber.org/protocol/workgroup");
try {
user.addAttribute("jid", request.getUserJID().toString());
// Add Sub-Elements
Element position = user.addElement("position");
position.setText(Integer.toString(i));
Element time = user.addElement("time");
time.setText(Integer.toString(request.getTimeStatus()));
Element joinTime = user.addElement("join-time");
joinTime.setText(UTC_FORMAT.format(request.getCreationTime()));
i++;
} catch (Exception e) {
// Since we are not locking the list of requests while doing this operation (for
// performance reasons) it is possible that the request got accepted or cancelled
// thus generating a NPE
// Remove the request that generated the exception
details.remove(user);
// Log an error if the request still belongs to this queue
if (this.equals(request.getRequestQueue())) {
Log.error(e.getMessage(), e);
}
}
}
return queueStatus;
}
Aggregations