1 package org.opensrf.net.xmpp;
4 import java.net.Socket;
8 * Represents a single XMPP session. Sessions are responsible for writing to
9 * the stream and for managing a stream reader.
11 public class XMPPSession {
13 /** Initial jabber message */
14 public static final String JABBER_CONNECT =
15 "<stream:stream to='%s' xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams'>";
17 /** Basic auth message */
18 public static final String JABBER_BASIC_AUTH =
19 "<iq id='123' type='set'><query xmlns='jabber:iq:auth'>" +
20 "<username>%s</username><password>%s</password><resource>%s</resource></query></iq>";
22 public static final String JABBER_DISCONNECT = "</stream:stream>";
28 /** jabber username */
29 private String username;
30 /** jabber password */
31 private String password;
32 /** jabber resource */
33 private String resource;
35 /** XMPP stream reader */
37 /** Fprint-capable socket writer */
39 /** Raw socket output stream */
40 OutputStream outStream;
44 /** The process-wide session. All communication occurs
45 * accross this single connection */
46 private static XMPPSession globalSession;
50 * Creates a new session.
51 * @param host The jabber domain
52 * @param port The jabber port
54 public XMPPSession( String host, int port ) {
60 * Returns the global, process-wide session
62 public static XMPPSession getGlobalSession() {
67 * Sets the global, process-wide section
69 public static void setGlobalSession(XMPPSession ses) {
74 /** true if this session is connected to the server */
75 public boolean connected() {
78 reader.getXMPPStreamState() ==
79 XMPPReader.XMPPStreamState.CONNECTED);
84 * Connects to the network.
85 * @param username The jabber username
86 * @param password The jabber password
87 * @param resource The Jabber resource
89 public void connect(String username, String password, String resource) throws XMPPException {
91 this.username = username;
92 this.password = password;
93 this.resource = resource;
96 /* open the socket and associated streams */
97 socket = new Socket(host, port);
99 /** the session maintains control over the output stream */
100 outStream = socket.getOutputStream();
101 writer = new PrintWriter(outStream, true);
103 /** pass the input stream to the reader */
104 reader = new XMPPReader(socket.getInputStream());
106 } catch(IOException ioe) {
108 XMPPException("unable to communicate with host " + host + " on port " + port);
111 /* build the reader thread */
112 Thread thread = new Thread(reader);
113 thread.setDaemon(true);
116 /* send the initial jabber message */
118 reader.waitCoreEvent(10000);
119 if( reader.getXMPPStreamState() != XMPPReader.XMPPStreamState.CONNECT_RECV )
120 throw new XMPPException("unable to connect to jabber server");
122 /* send the basic auth message */
123 sendBasicAuth(); /* XXX add support for other auth mechanisms */
124 reader.waitCoreEvent(10000);
126 throw new XMPPException("Authentication failed");
129 /** Sends the initial jabber message */
130 private void sendConnect() {
131 writer.printf(JABBER_CONNECT, host);
132 reader.setXMPPStreamState(XMPPReader.XMPPStreamState.CONNECT_SENT);
135 /** Send the basic auth message */
136 private void sendBasicAuth() {
137 writer.printf(JABBER_BASIC_AUTH, username, password, resource);
138 reader.setXMPPStreamState(XMPPReader.XMPPStreamState.AUTH_SENT);
143 * Sends an XMPPMessage.
144 * @param msg The message to send.
146 public synchronized void send(XMPPMessage msg) throws XMPPException {
149 String xml = msg.toXML();
150 outStream.write(xml.getBytes());
151 } catch (Exception e) {
152 throw new XMPPException(e.toString());
158 * @throws XMPPException if we are no longer connected.
160 private void checkConnected() throws XMPPException {
162 throw new XMPPException("Disconnected stream");
167 * Receives messages from the network.
168 * @param timeout Maximum number of milliseconds to wait for a message to arrive.
169 * If timeout is negative, this method will wait indefinitely.
170 * If timeout is 0, this method will not block at all, but will return a
171 * message if there is already a message available.
173 public XMPPMessage recv(long timeout) throws XMPPException {
179 while(true) { /* wait indefinitely for a message to arrive */
180 reader.waitCoreEvent(timeout);
181 msg = reader.popMessageQueue();
182 if( msg != null ) return msg;
188 while(timeout >= 0) { /* wait at most 'timeout' milleseconds for a message to arrive */
189 timeout -= reader.waitCoreEvent(timeout);
190 msg = reader.popMessageQueue();
191 if( msg != null ) return msg;
201 * Disconnects from the jabber server and closes the socket
203 public void disconnect() {
205 outStream.write(JABBER_DISCONNECT.getBytes());
207 } catch(Exception e) {}