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

📄 chatservicemanager.java

📁 JStock是一个免费股市软件
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
/*
 * 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 + -