/** * $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.multiplexer; import org.dom4j.Element; import java.util.Date; import java.util.Map; import java.util.Queue; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentLinkedQueue; /** * The session represents a connection between the server and a client (c2s) or * another server (s2s) as well as a connection with a component. Authentication and * user accounts are associated with c2s connections while s2s has an optional authentication * association but no single user user.<p> * * Obtain object managers from the session in order to access server resources. * * @author Gaston Dombiak */ public abstract class Session { /** * Version of the XMPP spec supported as MAJOR_VERSION.MINOR_VERSION (e.g. 1.0). */ public static final int MAJOR_VERSION = 1; public static final int MINOR_VERSION = 0; /** * The utf-8 charset for decoding and encoding Jabber packet streams. */ protected static String CHARSET = "UTF-8"; public static final int STATUS_CLOSED = -1; public static final int STATUS_CONNECTED = 1; public static final int STATUS_STREAMING = 2; public static final int STATUS_AUTHENTICATED = 3; /** * The stream id for this session (random and unique). */ private String streamID; /** * The current session status. */ protected int status = STATUS_CONNECTED; /** * The connection that this session represents. */ protected Connection conn; private String serverName; private Date startDate = new Date(); private Queue<Element> stanzaQueue = new ConcurrentLinkedQueue<Element>(); /** * Map of existing sessions. A session is added just after the initial stream header * was processed. Key: stream ID, value: the session. */ private static Map<String, Session> sessions = new ConcurrentHashMap<String, Session>(); public static StreamIDFactory idFactory = new StreamIDFactory(); public static void addSession(String streamID, Session session) { sessions.put(streamID, session); } public static void removeSession(String streamID) { sessions.remove(streamID); } /** * Returns the session whose stream ID matches the specified stream ID. * * @param streamID the stream ID of the session to look for. * @return the session whose stream ID matches the specified stream ID. */ public static Session getSession(String streamID) { return sessions.get(streamID); } /** * Closes connections of connected clients since the server or the connection * manager is being shut down. If the server is the one that is being shut down * then the connection manager will keep running and will try to establish new * connections to the server (on demand). */ public static void closeAll() { for (Session session : sessions.values()) { session.close(true); } } /** * Creates a session with an underlying connection and permission protection. * * @param connection The connection we are proxying */ public Session(String serverName, Connection connection, String streamID) { conn = connection; this.streamID = streamID; this.serverName = serverName; } /** * Obtain the current status of this session. * * @return The status code for this session */ public int getStatus() { return status; } /** * Set the new status of this session. Setting a status may trigger * certain events to occur (setting a closed status will close this * session). * * @param status The new status code for this session */ public void setStatus(int status) { this.status = status; } /** * Obtain the stream ID associated with this sesison. Stream ID's are generated by the server * and should be unique and random. * * @return This session's assigned stream ID */ public String getStreamID() { return streamID; } /** * Obtain the name of the server this session belongs to. * * @return the server name. */ public String getServerName() { return serverName; } /** * Obtain the date the session was created. * * @return the session's creation date. */ public Date getCreationDate() { return startDate; } /** * @return the current stanza queue for this session */ public Queue<Element> getStanzaQueue() { return stanzaQueue; } /** * Returns a text with the available stream features. Each subclass may return different * values depending whether the session has been authenticated or not. * * @return a text with the available stream features or <tt>null</tt> to add nothing. */ public abstract String getAvailableStreamFeatures(); /** * Indicate the server that the session has been closed. Do nothing if the session * was the one that originated the close action. */ public abstract void close(); public abstract void close(boolean isServerShuttingDown); public abstract void deliver(Element stanza); @Override public String toString() { return super.toString() + " status: " + status + " id: " + streamID; } protected static int[] decodeVersion(String version) { int[] answer = new int[] {0 , 0}; String [] versionString = version.split("\\."); answer[0] = Integer.parseInt(versionString[0]); answer[1] = Integer.parseInt(versionString[1]); return answer; } public abstract boolean isClosed(); }