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

📄 connectionmultiplexermanager.java

📁 基于Jabber协议的即时消息服务器
💻 JAVA
字号:
/** * $RCSfile: $ * $Revision: $ * $Date: $ * * Copyright (C) 2006 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. */package org.jivesoftware.wildfire.multiplex;import org.jivesoftware.util.JiveGlobals;import org.jivesoftware.util.Log;import org.jivesoftware.wildfire.*;import org.jivesoftware.wildfire.auth.UnauthorizedException;import org.jivesoftware.wildfire.event.SessionEventDispatcher;import org.jivesoftware.wildfire.event.SessionEventListener;import java.util.Collection;import java.util.List;import java.util.Map;import java.util.Random;import java.util.concurrent.ConcurrentHashMap;/** * A ConnectionMultiplexerManager is responsible for keeping track of the connected * Connection Managers and the sessions that were established with the Connection * Managers. Moreover, a ConnectionMultiplexerManager is able to create, get and close * client sessions based on Connection requests. * * @author Gaston Dombiak */public class ConnectionMultiplexerManager implements SessionEventListener {    private static final ConnectionMultiplexerManager instance = new ConnectionMultiplexerManager();    /**     * Pseudo-random number generator object for use with getMultiplexerSession(String).     */    private static Random randGen = new Random();    static {        // Add the unique instance of this class as a session listener. We need to react        // when sessions are closed so we can clean up the registry of client sessions.        SessionEventDispatcher.addListener(instance);    }    /**     * Map that keeps track of connection managers and hosted connections.     * Key: stream ID; Value: Domain of connection manager hosting connection     */    private Map<String, String> streamIDs = new ConcurrentHashMap<String, String>();    /**     * Map that keeps track of connection managers and hosted sessions.     * Key: Domain of connection manager; Value: Map with Key: stream ID; Value: Client session     */    private Map<String, Map<String, ClientSession>> sessionsByManager =            new ConcurrentHashMap<String, Map<String, ClientSession>>();    private SessionManager sessionManager;    /**     * Returns the unique instance of this class.     *     * @return the unique instance of this class.     */    public static ConnectionMultiplexerManager getInstance() {        return instance;    }    /**     * Returns the default secret key that connection managers should present while trying to     * establish a new connection.     *     * @return the default secret key that connection managers should present while trying to     *         establish a new connection.     */    public static String getDefaultSecret() {        return JiveGlobals.getProperty("xmpp.multiplex.defaultSecret");    }    /**     * Sets the default secret key that connection managers should present while trying to     * establish a new connection.     *     * @param defaultSecret the default secret key that connection managers should present     *        while trying to establish a new connection.     */    public static void setDefaultSecret(String defaultSecret) {        JiveGlobals.setProperty("xmpp.multiplex.defaultSecret", defaultSecret);    }    private ConnectionMultiplexerManager() {        sessionManager = XMPPServer.getInstance().getSessionManager();        // Start thread that will send heartbeats to Connection Managers every 30 seconds        // to keep connections open.        Thread hearbeatThread = new Thread() {            public void run() {                while (true) {                    try {                        Thread.sleep(30000);                        for (ConnectionMultiplexerSession session : sessionManager                                .getConnectionMultiplexerSessions()) {                            session.getConnection().deliverRawText(" ");                        }                    }                    catch (InterruptedException e) {                        // Do nothing                    }                    catch(Exception e) {                        Log.error(e);                    }                }            }        };        hearbeatThread.setDaemon(true);        hearbeatThread.setPriority(Thread.NORM_PRIORITY);        hearbeatThread.start();    }    /**     * Creates a new client session that was established to the specified connection manager.     * The new session will not be findable through its stream ID.     *     * @param connectionManagerDomain the connection manager that is handling the connection     *        of the session.     * @param streamID the stream ID created by the connection manager for the new session.     */    public void createClientSession(String connectionManagerDomain, String streamID) {        try {            Connection connection = new ClientSessionConnection(connectionManagerDomain);            ClientSession session = SessionManager.getInstance()                    .createClientSession(connection, new BasicStreamID(streamID));            // Register that this streamID belongs to the specified connection manager            streamIDs.put(streamID, connectionManagerDomain);            // Register which sessions are being hosted by the speicifed connection manager            Map<String, ClientSession> sessions = sessionsByManager.get(connectionManagerDomain);            if (sessions == null) {                synchronized (connectionManagerDomain.intern()) {                    sessions = sessionsByManager.get(connectionManagerDomain);                    if (sessions == null) {                        sessions = new ConcurrentHashMap<String, ClientSession>();                        sessionsByManager.put(connectionManagerDomain, sessions);                    }                }            }            sessions.put(streamID, session);        }        catch (UnauthorizedException e) {            Log.error("Error creating virtual client session", e);        }    }    /**     * Closes an existing client session that was established through a connection manager.     *     * @param connectionManagerDomain the connection manager that is handling the connection     *        of the session.     * @param streamID the stream ID created by the connection manager for the session.     */    public void closeClientSession(String connectionManagerDomain, String streamID) {        Map<String, ClientSession> sessions = sessionsByManager.get(connectionManagerDomain);        if (sessions != null) {            Session session = sessions.remove(streamID);            if (session != null) {                // Close the session                session.getConnection().close();            }        }    }    /**     * A connection manager has become available. Clients can now connect to the server through     * the connection manager.     *     * @param connectionManagerName the connection manager that has become available.     */    public void multiplexerAvailable(String connectionManagerName) {        // Add a new entry in the list of available managers. Here is where we are going to store        // which clients were connected through which connection manager        Map<String, ClientSession> sessions = sessionsByManager.get(connectionManagerName);        if (sessions == null) {            synchronized (connectionManagerName.intern()) {                sessions = sessionsByManager.get(connectionManagerName);                if (sessions == null) {                    sessions = new ConcurrentHashMap<String, ClientSession>();                    sessionsByManager.put(connectionManagerName, sessions);                }            }        }    }    /**     * A connection manager has gone unavailable. Close client sessions that were established     * to the specified connection manager.     *     * @param connectionManagerName the connection manager that is no longer available.     */    public void multiplexerUnavailable(String connectionManagerName) {        // Remove the connection manager and the hosted sessions        Map<String, ClientSession> sessions = sessionsByManager.remove(connectionManagerName);        if (sessions != null) {            for (String streamID : sessions.keySet()) {                // Remove inverse track of connection manager hosting streamIDs                streamIDs.remove(streamID);                // Close the session                sessions.get(streamID).getConnection().close();            }        }    }    /**     * Returns the ClientSession with the specified stream ID that is being hosted by the     * specified connection manager.     *     * @param connectionManagerDomain the connection manager that is handling the connection     *        of the session.     * @param streamID the stream ID created by the connection manager for the session.     * @return the ClientSession with the specified stream ID.     */    public ClientSession getClientSession(String connectionManagerDomain, String streamID) {        Map<String, ClientSession> sessions = sessionsByManager.get(connectionManagerDomain);        if (sessions != null) {            return sessions.get(streamID);        }        return null;    }    /**     * Returns a {@link ConnectionMultiplexerSession} for the specified connection manager     * domain or <tt>null</tt> if none was found. In case the connection manager has many     * connections established with the server then one of them will be selected randomly.     *     * @param connectionManagerDomain the domain of the connection manager to get a session.     * @return a session to the specified connection manager domain or null if none was found.     */    public ConnectionMultiplexerSession getMultiplexerSession(String connectionManagerDomain) {        List<ConnectionMultiplexerSession> sessions =                sessionManager.getConnectionMultiplexerSessions(connectionManagerDomain);        if (sessions.isEmpty()) {            return null;        }        else if (sessions.size() == 1) {            return sessions.get(0);        }        else {            // Pick a random session so we can distribute traffic evenly            return sessions.get(randGen.nextInt(sessions.size()));        }    }    /**     * Returns the names of the connected connection managers to this server.     *     * @return the names of the connected connection managers to this server.     */    public Collection<String> getMultiplexers() {        return sessionsByManager.keySet();    }    /**     * Returns the number of connected clients to a specific connection manager.     *     * @param managerName the name of the connection manager.     * @return the number of connected clients to a specific connection manager.     */    public int getNumConnectedClients(String managerName) {        Map<String, ClientSession> clients = sessionsByManager.get(managerName);        if (clients == null) {            return 0;        }        else {            return clients.size();        }    }    public void anonymousSessionCreated(Session session) {        // Do nothing.    }    public void anonymousSessionDestroyed(Session session) {        removeSession(session);    }    public void sessionCreated(Session session) {        // Do nothing.    }    public void sessionDestroyed(Session session) {        removeSession(session);    }    private void removeSession(Session session) {        // Remove trace indicating that a connection manager is hosting a connection        String streamID = session.getStreamID().getID();        String connectionManagerDomain = streamIDs.remove(streamID);        // Remove trace indicating that a connection manager is hosting a session        if (connectionManagerDomain != null) {            Map<String, ClientSession> sessions = sessionsByManager.get(connectionManagerDomain);            if (sessions != null) {                sessions.remove(streamID);            }        }    }    /**     * Simple implementation of the StreamID interface to hold the stream ID assigned by     * the Connection Manager to the Session.     */    private class BasicStreamID implements StreamID {        String id;        public BasicStreamID(String id) {            this.id = id;        }        public String getID() {            return id;        }        public String toString() {            return id;        }        public int hashCode() {            return id.hashCode();        }    }}

⌨️ 快捷键说明

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