⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 agentsession.java

📁 openfire 服务器源码下载
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
/**
 * $RCSfile$
 * $Revision: 28140 $
 * $Date: 2006-03-06 17:18:46 -0800 (Mon, 06 Mar 2006) $
 *
 * 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.xmpp.workgroup;

import org.jivesoftware.openfire.fastpath.util.TaskEngine;
import org.jivesoftware.xmpp.workgroup.interceptor.InterceptorManager;
import org.jivesoftware.xmpp.workgroup.interceptor.OfferInterceptorManager;
import org.jivesoftware.xmpp.workgroup.interceptor.PacketRejectedException;
import org.jivesoftware.xmpp.workgroup.request.UserRequest;
import org.dom4j.Element;
import org.jivesoftware.util.FastDateFormat;
import org.jivesoftware.util.LocaleUtils;
import org.xmpp.component.ComponentManagerFactory;
import org.xmpp.packet.IQ;
import org.xmpp.packet.JID;
import org.xmpp.packet.Packet;
import org.xmpp.packet.Presence;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedQueue;

/**
 * <p>A 'live' agent session.</p>
 * <p>Agent sessions are only created and maintaned for available agents
 * (although they may be show-dnd).</p>
 *
 * @author Derek DeMoro
 */
public class AgentSession {

    private static final FastDateFormat UTC_FORMAT = FastDateFormat.getInstance("yyyyMMdd'T'HH:mm:ss", TimeZone.getTimeZone("GMT+0"));

    private Presence presence;
    private Collection<Workgroup> workgroups = new ConcurrentLinkedQueue<Workgroup>();
    private Offer offer;
    /**
     * Flag that indicates if the agent requested to get information of agents of all the workgroups
     * where the agent has joined.
     */
    private boolean requestedAgentInfo = false;
    private Map<Workgroup, Queue<ChatInfo>> chatInfos = new ConcurrentHashMap<Workgroup, Queue<ChatInfo>>();
    /**
     * By default maxChats has a value of -1 which means that #getMaxChats will return
     * the max number of chats per agent defined in the workgroup. The agent may overwrite
     * the default value but the new value will not be persisted for future sessions.
     */
    private int maxChats;
    private Agent agent;

    private JID address;
    private long id;

    private Date lastChatTime;

    /**
     * @param address the XMPPAddress to create an <code>AgentSession</code>
     * @param agent   the <code>Agent</code>
     */
    public AgentSession(JID address, Agent agent) {
        this.id = -1;
        this.agent = agent;
        this.address = address;
        maxChats = -1;
        presence = new Presence();
    }

    public Presence getPresence() {
        return presence;
    }

    /**
     * Updates the presence of the AgentSession with the new received presence. The max number of
     * chats and number of current chats will be updated if that information was included in the presence.
     * If no information was provided then default values of queues, workgroups or general settings will
     * be used instead.
     *
     * @param packet the new presence sent by the agent.
     */
    public void updatePresence(Presence packet) {
        // Create a copy of the received Presence to use as the presence of the AgentSession
        Presence sessionPresence = packet.createCopy();
        // Remove the "agent-status" element from the new AgentSession's presence
        Element child = sessionPresence.getChildElement("agent-status", "http://jabber.org/protocol/workgroup");
        sessionPresence.getElement().remove(child);
        // Set the new presence to the AgentSession
        presence = sessionPresence;

        // Set the new maximum number of chats and the number of current chats to the
        // AgentSession based on the values sent within the presence (if any)
        Element elem = packet.getChildElement("agent-status", "http://jabber.org/protocol/workgroup");
        if (elem != null) {
            Iterator metaIter = elem.elementIterator();
            while (metaIter.hasNext()) {
                Element agentStatusElement = (Element)metaIter.next();
                if ("max-chats".equals(agentStatusElement.getName())) {
                    String maxChats = agentStatusElement.getText();
                    if (maxChats == null || maxChats.trim().length() == 0) {
                        setMaxChats(-1);
                    }
                    else {
                        setMaxChats(Integer.parseInt(maxChats));
                    }
                }
            }
        }
    }

    public void join(Workgroup workgroup) {
        boolean added = false;
        boolean alreadyJoined = workgroups.contains(workgroup);
        if(!alreadyJoined){
            added = workgroups.add(workgroup);
        }

        for (RequestQueue requestQueue : workgroup.getRequestQueues()) {
            if (requestQueue.isMember(getAgent())) {
                if (added) {
                    requestQueue.getAgentSessionList().addAgentSession(this);
                }
                requestQueue.sendStatus(getJID());
                requestQueue.sendDetailedStatus(getJID());
            }
        }

        updateStatus(workgroup);

        if (added) {
            workgroup.agentJoined(this);
            // Initialize the list that will hold the chats in the workgroup
            chatInfos.put(workgroup, new ConcurrentLinkedQueue<ChatInfo>());
        }
    }

    public void depart(Workgroup workgroup) {
        boolean removed = workgroups.remove(workgroup);
        if (removed) {
            for (RequestQueue requestQueue : workgroup.getRequestQueues()) {
                requestQueue.getAgentSessionList().removeAgentSession(this);
            }
            if (workgroups.isEmpty()) {
                getAgent().closeSession(getJID());
            }
            updateStatus(workgroup);
            workgroup.agentDeparted(this);
        }
    }

    public int getCurrentChats(Workgroup group) {
        return getChats(group).size();
    }

    private void updateStatus(Workgroup workgroup) {
        if (getMaxChats(workgroup) > getCurrentChats(workgroup) && offer != null) {
            offer.removeRejector(this);
        }
        sendStatusToAllAgents(workgroup);
        // When the agent becomes unavailable he will stop receiving presence updates from other
        // agents so the agent will need to request information from agents once again and discard
        // the old presences since they are outdated
        if (!presence.isAvailable()) {
            requestedAgentInfo = false;
        }
    }

    /**
     * Sends a packet to this agent with all the agents that belong to this agent's workgroup. This
     * packet will be sent only when the agent has requested it.<p>
     * <p/>
     * Once the list of agents has been sent the agent will start to receive updates when new
     * agents are added or removed from the workgroup as well as when agents become available
     * or unavailable.
     *
     * @param packet request made by agent.
     * @param workgroup the workgroup whose agents will be sent to the requester.
     */
    public void sendAgentsInWorkgroup(IQ packet, final Workgroup workgroup) {
        IQ statusPacket = IQ.createResultIQ(packet);
        Element agentStatusRequest = statusPacket.setChildElement("agent-status-request",
            "http://jabber.org/protocol/workgroup");
        for (Agent agentInWorkgroup : workgroup.getAgents()) {
            if (agentInWorkgroup == agent) {
                continue;
            }
            // Add the information of the agent
            agentStatusRequest.add(agentInWorkgroup.getAgentInfo());
        }
        // Send the response for this queue
        WorkgroupManager.getInstance().send(statusPacket);
        // Upate the flag to indicate that the agent has requested information about the other
        // agents. This implies that from now on this agent will start to receive presence
        // updates from the other workgroup agents when they become unavailable or new agents
        // join the workgroup
        requestedAgentInfo = true;

        // Send the presence of the available agents to this agent
        // Note: Execute this process in another thread since we want to release this thread as
        // soon as possible so other requests may be read and processed
        TaskEngine.getInstance().submit(new Runnable() {
            public void run() {
                try {
                    sendStatusOfAllAgents(workgroup);
                }
                catch (Exception e) {
                    ComponentManagerFactory.getComponentManager().getLog().error("Error sending status of all agents", e);
                }
            }
        });
    }

    /**
     * Sends information of the agent to the agent that requested it.
     *
     * @param packet the original packet that made the request to obtain the agent's info.
     */
    public void sendAgentInfo(IQ packet) {
        IQ statusPacket = IQ.createResultIQ(packet);
        Element agentInfo = statusPacket.setChildElement("agent-info",
            "http://jivesoftware.com/protocol/workgroup");
        agentInfo.addElement("jid").setText(getAgent().getAgentJID().toBareJID());
        agentInfo.addElement("name").setText(getAgent().getNickname());
        // Send the response
        WorkgroupManager.getInstance().send(statusPacket);
    }

    /**
     * Sends the presence of each available agent in the workgroup to this agent.
     *
     * @param workgroup the workgroup whose agents' presences will be sent to this agent.
     */
    private void sendStatusOfAllAgents(Workgroup workgroup) {
        for (AgentSession agentSession : workgroup.getAgentSessions()) {
            if (!agentSession.getJID().equals(address)) {
                Presence statusPacket = agentSession.getPresence().createCopy();
                statusPacket.setFrom(agentSession.getJID());
                statusPacket.setTo(address);
                // Add the agent-status element
                agentSession.getAgentStatus(statusPacket,workgroup);
                workgroup.send(statusPacket);
            }
        }
    }

    /**
     * Sends this agent's status to all other agents in the Workgroup.
     *
     * @param workgroup the workgroup whose agent will be notified
     */
    private void sendStatusToAllAgents(Workgroup workgroup) {
        for (AgentSession agentSession : workgroup.getAgentSessions()) {
            // Only send presences to Agents that are available and had requested to
            // receive other agents' information
            if (agentSession.hasRequestedAgentInfo() && !agentSession.getJID().equals(address)) {
                Presence statusPacket = presence.createCopy();
                statusPacket.setFrom(address);
                statusPacket.setTo(agentSession.getJID());
                // Add the agent-status element
                getAgentStatus(statusPacket, workgroup);

                workgroup.send(statusPacket);
            }
        }
    }

    private void getAgentStatus(Presence statusPacket, Workgroup workgroup) {
        Element agentStatus = statusPacket.getElement().addElement("agent-status",
            "http://jabber.org/protocol/workgroup");
        // Add the workgroup JID as an attribute to the agent status element
        agentStatus.addAttribute("jid", workgroup.getJID().toBareJID());
        // Add max-chats element to the agent status element
        Element maxChats = agentStatus.addElement("max-chats");
        maxChats.setText(Integer.toString(getMaxChats(workgroup)));

        // Add information about the current chats to the agent status element
        Element currentChats = agentStatus.addElement("current-chats",
            "http://jivesoftware.com/protocol/workgroup");
        for (ChatInfo chatInfo : getChats(workgroup)) {
            Element chatElement = currentChats.addElement("chat");
            chatElement.addAttribute("sessionID", chatInfo.getSessionID());
            chatElement.addAttribute("userID", chatInfo.getUserID());
            chatElement.addAttribute("startTime", UTC_FORMAT.format(chatInfo.getDate()));

            // Check for question
            if (chatInfo.getQuestion() != null) {
                chatElement.addAttribute("question", chatInfo.getQuestion());
            }

            // Check for username
            if (chatInfo.getUsername() != null) {
                chatElement.addAttribute("username", chatInfo.getUsername());
            }

            // Check for email
            if (chatInfo.getEmail() != null) {
                chatElement.addAttribute("email", chatInfo.getEmail());
            }

        }
    }

    public String toString() {
        return "AI-" + Integer.toHexString(hashCode()) +
            " JID " + address.toString() +
            " CC " + Integer.toString(chatInfos.size()) +
            " MC " + Integer.toString(maxChats);
    }

    /**
     * Send an offer
     *
     * @param offer the <code>Offer</code> to send.
     * @param offerPacket the packet to send to the agent with the offer.
     * @return true if the packet was sent to the agent.
     */
    public boolean sendOffer(Offer offer, IQ offerPacket) {
        synchronized (this) {
            if (this.offer != null) {
                return false;
            }
            this.offer = offer;
        }

        try {
            offer.addPendingSession(this);

            InterceptorManager interceptorManager = OfferInterceptorManager.getInstance();
            try {
                Workgroup workgroup = offer.getRequest().getWorkgroup();
                interceptorManager.invokeInterceptors(workgroup.getJID().toBareJID(),
                    offerPacket, false, false);
                // Send the Offer to the agent
                WorkgroupManager.getInstance().send(offerPacket);
                interceptorManager.invokeInterceptors(workgroup.getJID().toBareJID(),
                    offerPacket, false, true);
            }
            catch (PacketRejectedException e) {
                ComponentManagerFactory.getComponentManager().getLog().warn("Offer was not sent " +
                    "due to interceptor REJECTION: " + offerPacket.toXML(), e);
            }
            return true;

        }
        catch (Exception e) {
            ComponentManagerFactory.getComponentManager().getLog().error(LocaleUtils.getLocalizedString("admin.error"), e);
            return false;
        }
    }

    public void sendRevoke(Offer offer, IQ agentRevoke) {
        if (this.offer == null || !this.offer.equals(offer)) {
            return;
        }
        try {
            WorkgroupManager.getInstance().send(agentRevoke);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -