📄 chatservicemanager.java
字号:
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* Copyright (C) 2008 Yan Cheng Cheok <yccheok@yahoo.com>
*/
package org.yccheok.jstock.chat;
import java.util.Collection;
import java.util.concurrent.CountDownLatch;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jivesoftware.smack.AccountManager;
import org.jivesoftware.smack.ConnectionListener;
import org.jivesoftware.smack.PacketListener;
import org.jivesoftware.smack.SASLAuthentication;
import org.jivesoftware.smack.XMPPConnection;
import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smack.packet.Packet;
import org.jivesoftware.smack.packet.XMPPError;
import org.jivesoftware.smackx.muc.MultiUserChat;
import org.yccheok.jstock.engine.Subject;
import org.yccheok.jstock.gui.MainFrame;
/**
*
* @author yccheok
*/
public class ChatServiceManager {
public enum State
{
CONNECTING,
CONNECTED,
ACCOUNT_CREATING,
ACCOUNT_CREATED,
ROOM_CREATING,
ROOM_CREATED,
END,
}
private class ChatService implements Runnable
{
public ChatService(String username, String password)
{
this.username = username;
this.password = password;
this.connection = null;
readWriteLock = new java.util.concurrent.locks.ReentrantReadWriteLock();
readerLock = readWriteLock.readLock();
writerLock = readWriteLock.writeLock();
}
public void start()
{
this.runnableFlag = true;
new Thread(this).start();
}
private void notifyPacketObserver(Packet packet) {
// Check for dirty flag before informing observer. Just to make sure we are pretending
// to "dead". Although this is not a clean way, it just work.
if (this.runnableFlag)
ChatServiceManager.this.notifyPacketObserver(packet);
}
private void notifyStateObserver(State state) {
// Check for dirty flag before informing observer. Just to make sure we are pretending
// to "dead". Although this is not a clean way, it just work.
if (this.runnableFlag)
ChatServiceManager.this.notifyStateObserver(state);
}
@Override
public void run()
{
this.me = Thread.currentThread();
// "new XMPPConnection" takes long duration sometimes. To give user a better experience,
// we should inform them that we are currently in connecting state. If not,
// they will be wondering why our program is not working now.
ChatService.this.notifyStateObserver(State.CONNECTING);
this.connection = new XMPPConnection(Utils.getXMPPServer());
while (runnableFlag)
{
try {
State state = State.CONNECTING;
ChatService.this.notifyStateObserver(state);
boolean shouldContinue = true;
while (runnableFlag && shouldContinue)
{
switch (state)
{
case CONNECTING:
state = this.connecting();
break;
case CONNECTED:
state = this.connected();
break;
case ACCOUNT_CREATING:
state = this.account_creating();
break;
case ACCOUNT_CREATED:
state = this.account_created();
break;
case ROOM_CREATING:
state = this.room_creating();
break;
case ROOM_CREATED:
state = this.room_created();
break;
case END:
state = this.end();
shouldContinue = false;
break;
default:
throw new java.lang.IllegalArgumentException("Missing case " + state);
}
}
}
catch (Exception exp) {
log.error("Some stupid thing happens here.", exp);
}
finally {
if (muc != null)
{
try {
this.writerLock.lock();
muc.leave();
muc.removeMessageListener(messageListener);
muc.removeParticipantListener(participantListener);
muc = null;
}
catch (Exception exp) {
log.error("Some stupid thing happens here.", exp);
}
finally {
this.writerLock.unlock();
}
}
}
}
connection.disconnect();
// Shall we?
connection.removeConnectionListener(connectionListener);
}
private State connected()
{
State state = State.CONNECTED;
ChatService.this.notifyStateObserver(state);
state = State.ROOM_CREATING;
return state;
}
private ConnectionListener getConnectionListener() {
return new ConnectionListener() {
@Override
public void connectionClosed() {
if (doneSignal != null)
doneSignal.countDown();
}
@Override
public void connectionClosedOnError(Exception arg0) {
if (doneSignal != null)
doneSignal.countDown();
}
@Override
public void reconnectingIn(int arg0) {
if (doneSignal != null)
doneSignal.countDown();
}
@Override
public void reconnectionSuccessful() {
if (doneSignal != null)
doneSignal.countDown();
}
@Override
public void reconnectionFailed(Exception arg0) {
if (doneSignal != null)
doneSignal.countDown();
}
};
}
private PacketListener getPacketListener() {
return new PacketListener() {
@Override
public void processPacket(Packet arg0) {
ChatService.this.notifyPacketObserver(arg0);
}
};
}
private State room_creating() {
State state = State.ROOM_CREATING;
ChatService.this.notifyStateObserver(state);
Collection<String> serviceNames = null;
try {
serviceNames = MultiUserChat.getServiceNames(connection);
} catch (XMPPException ex) {
log.error(null, ex);
}
String serviceName = "conference." + Utils.getXMPPServer();
if (serviceNames != null)
{
serviceName = serviceNames.toArray(new String[0])[0];
}
//Collection<HostedRoom> hostedRooms = null;
//try {
// hostedRooms = MultiUserChat.getHostedRooms(connection, serviceName);
//} catch (XMPPException ex) {
// log.error(null, ex);
// state = State.CONNECTING;
// return state;
//}
final String roomName = Utils.getRoomName(MainFrame.getJStockOptions().getCountry()) + "@" + serviceName;
if (muc != null) {
muc.removeMessageListener(messageListener);
muc.removeParticipantListener(participantListener);
}
muc = new MultiUserChat(connection, roomName);
muc.addMessageListener(messageListener);
muc.addParticipantListener(participantListener);
if (muc.isJoined() == false)
{
try {
muc.join(username);
} catch (XMPPException ex) {
log.error(null, ex);
XMPPError error = ex.getXMPPError();
if (error != null) {
/* remote-server-not-found(404) */
if (error.getCode() == 404)
{
try {
muc.sendConfigurationForm(null);
muc.create(username);
state = State.ROOM_CREATED;
return state;
} catch (XMPPException ex1) {
log.error(null, ex1);
}
}
}
state = State.CONNECTING;
return state;
}
}
state = State.ROOM_CREATED;
return state;
}
private State end()
{
State state = State.END;
ChatService.this.notifyStateObserver(state);
return state;
}
private State room_created() {
State state = State.ROOM_CREATED;
//try {
// Collection<Occupant> occupants = muc.getParticipants();
//} catch (XMPPException ex) {
// log.error(null, ex);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -