Package pictionary.pictionaryserver

Source Code of pictionary.pictionaryserver.PictionaryServer$ClientConnection$SendThread

package pictionary.pictionaryserver;

import pictionary.message.*;
import pictionary.message.Message.MessageType;
import pictionary.PictionaryPlayer;
import pictionary.PictionaryGame;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.*;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Iterator;
import java.util.Scanner;
import java.util.HashMap;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.ArrayList;
import javax.swing.*;
import java.util.HashSet;
import java.util.List;
/**
* Responsible for sending messages between the connected clients,
* and between the Pictionary game and the clients.
* Keeps track of the clients with a HashMap<String, ClientConnection> where String is the clients unique name;
* there is one {@link ClientConnection} per connected client.
*
* @author Kristoffer Nordkvist
*/
public final class PictionaryServer extends JFrame
{
    /**
     * The collection that stores all the client connections. Clients are identified with their unique name.
     */
    private HashMap<String, ClientConnection> clientConnections = new HashMap<String, ClientConnection>();
   
    /**
     * The {@link PictionaryGame} instance used by the server.
     */
    private PictionaryGame pictionaryGame;
   
    /**
     * The server's queue with incoming messages. Every time a {@link ClientConnection} receives a message,
     * it puts that message in this queue.
     */
    private LinkedBlockingQueue<ClientConnectionMessage> incomingMessages =
        new LinkedBlockingQueue<ClientConnectionMessage>();
   
    /**
     * Responsible for accepting new connections.
     */
    private ServerSocket serverSocket;
   
    /**
     * The {@link ServerThread} instance used for accepting and creating new client connections.
     */
    private ServerThread serverThread;
   
    /**
     * True if the server thread is shut down, else false.
     * Used in {@link ServerThread}.
     */
    volatile private boolean shutdown;
   
    /**
     * The port on which this server is listening.
     */
    private final int port;
   
    /**
     * This server's hostname.
     */
    private final String host;
   
    /**
     * The button used when starting or shutting down the server.
     */
    private JButton disconnectOrConnectBtn = new JButton("Connect");
   
    /**
     * True if the server is running, else false. Used by the server's GUI.
     */
    private boolean running = false;
   
   
    /**
     * True if this server has been shut down, else false. Used by the server's GUI.
     */
    private boolean wasShutDown = false;
   
    /**
     * A collection of usernames that are unavailable.
     */
    private HashSet<String> illegalUsernames = new HashSet<String>();
   
    /**
     * The current word category in the Pictionary game.
     */
    public final String category;
   
    /**
     * The words used in the Pictionary game.
     */
    public final ArrayList<String> words;

    /**
     * The server's constructor.
     * @param host      The server's hostname.
     * @param port      The port that the server listens for new connections on.
     * @param category  The Pictionary game's word category.
     * @param words     The list of words to be used in the Pictionary game.
     */
    public PictionaryServer(String host, int port, String category, ArrayList<String> words)
    {
        this.host = host;
        this.port = port;
        this.category = category;
        this.words = words;
        pictionaryGame = new PictionaryGame(category, words, 60);
        disconnectOrConnectBtn.addActionListener(new ConnectButtonListener());
        initIllegalNames();
        this.addWindowListener(new CloseWindowListener());
        this.add(disconnectOrConnectBtn);
        this.setResizable(false);
        this.setTitle("Server not started");
        this.setSize(240, 100);
    }
   
    /**
     * Clears the list of illegal names and adds some standard ones.
     */
    private void initIllegalNames()
    {
        illegalUsernames.clear();
        illegalUsernames.add("server");
        illegalUsernames.add("admin");
        illegalUsernames.add("");
    }

    /**
     * Checks whether and username is valid or not.
     * @param   username The name to check for validity.
     * @return  True if the username is legal, else false.
     */
    public boolean validusername(String username)
    {
        return username != null && !illegalUsernames.contains(username.toLowerCase());
    }
   
    /**
     * Overrides the default behavior when the window is closed.
     * @author Kristoffer Nordkvist
     */
    private class CloseWindowListener extends WindowAdapter
    {
        /**
         * Shuts down the server and exits the program.
         */
        @Override
        public void windowClosing(WindowEvent e)
        {
            shutDownServer();
            System.exit(0);
        }
    }
   
    /**
     * The listener for {@link PictionaryServer#disconnectOrConnectBtn}.
     * @author Kristoffer Nordkvist
     */
    private class ConnectButtonListener implements ActionListener
    {
        /**
         * Starts or stops the server.
         */
        @Override
        public void actionPerformed(ActionEvent ae)
        {
            if(!running)
            {
                try
                {
                    disconnectOrConnectBtn.setText("Disconnect");
                    running = true;
                    PictionaryServer.this.setTitle("Up and running");
                    if(!wasShutDown)
                    {
                        connect();
                    }
                    else
                    {
                        restartServer(port);
                    }
                }
                catch (IOException e)
                {
                    JOptionPane.showMessageDialog(PictionaryServer.this, "Could not start server, exiting.");
                    PictionaryServer.this.processWindowEvent(
                            new WindowEvent(
                                    PictionaryServer.this, WindowEvent.WINDOW_CLOSING));
                }
            }
            else
            {
                shutDownServer();
                running = false;
                wasShutDown = true;
                disconnectOrConnectBtn.setText("Connect");
                PictionaryServer.this.setTitle("Server stopped");
            }
        }
    }
   
    /**
     * Creates a new ServerSocket and starts listening for new connections.
     * @throws IOException If the ServerSocket cannot be created.
     */
    private void connect() throws IOException
    {
        serverSocket = new ServerSocket(port, 0, InetAddress.getByName(host));
        System.out.println("Listening for client connections on " + serverSocket.toString());
        serverThread = new ServerThread();
        serverThread.start();
        Thread readerThread = new Thread()
        {
            public void run()
            {
                while (true)
                {
                    try
                    {
                        ClientConnectionMessage msg = incomingMessages.take(); // Ta n�sta meddelande fr�n k�n.
                        messageReceived(msg.clientConnection, msg.message); // G�r n�got med meddelandet
                    }
                    catch (Exception e)
                    {
                        System.out.println("Exception while handling received message:");
                        e.printStackTrace();
                    }
                }
            }
        };
        readerThread.setDaemon(true);
        readerThread.start();
    }
   
    /**
     * Called when a new message has been received
     * @param client    The client that sent the message.
     * @param message   The message that was sent from the client.
     */
    private void messageReceived(ClientConnection client, Message message)
    {
        if(message.messageType == MessageType.JoinGameRequest)
        {
            GameStatusData gameStatus = new GameStatusData(pictionaryGame.getPlayerNames(), pictionaryGame.getStatus());
            sendToOne(client.clientID, Message.CreateDataMessage(MessageType.JoinGameMessage, gameStatus));
            pictionaryGame.join(client);
        }
        else if(message.messageType == MessageType.Guess)
        {
            pictionaryGame.guessWord(client, (String)message.messageData.data);
        }
        // Klienten vill koppla ner.
        else if(message.messageType == MessageType.DisconnectRequest)
        {
            System.out.println(client.getClientID() + " sent a disconnect request");
            // Om spelaren var mitt i ett spel
            if(pictionaryGame.playerExists(client))
            {
                System.out.println(client.getClientID() + " is being removed from the game");
                // Informera spelet om att en klient har l�mnat
                pictionaryGame.playerLeft(client);
               
            }
            clientDisconnected(client);
            client.close();
        }
        else
        {
            sendToAll(message);
        }
    }
   
    /**
     * Gets the connected client's unique names.
     * @return  A list containing the unique identifiers for each client.
     */
    synchronized private List<String> getClients()
    {
        List<String> clients = new ArrayList<String>();
        Iterator<String> it = PictionaryServer.this.clientConnections.keySet().iterator();
        while(it.hasNext())
        {
            clients.add(it.next());
        }
        return clients;
    }

    /**
     * Clears the queue of incoming messages, shuts down the listener thread,
     * sets the listener thread and ServerSocket to null.
     */
    private void shutdownServerSocket()
    {
        if (serverThread == null)
            return;
        incomingMessages.clear();
        shutdown = true;
        try
        {
            serverSocket.close();
        }
        catch (IOException e){}
        serverThread = null;
        serverSocket = null;
    }
   
    /**
     * Starts the server again by creating a new ServerSocket and listener thread.
     * Should be called after {@link #shutDownServer()}.
     * @param port          The port which the server will listen on for new connections.
     * @throws IOException  If a new ServerSocket could not be created.
     */
    private void restartServer(int port) throws IOException
    {
        initIllegalNames();
        pictionaryGame = new PictionaryGame(category, words, 60);
        if (serverThread != null && serverThread.isAlive())
            throw new IllegalStateException("Server is already listening for connections.");
        shutdown = false;
        serverSocket = new ServerSocket(port);
        serverThread = new ServerThread();
        serverThread.start();
        System.out.println("Server restarted. Listening for client connections on port " + port);
    }

    /**
     * Disconnects all clients and stops accepting new connections.
     */
    private void shutDownServer()
    {
        shutdownServerSocket();
        sendToAll(new Message(MessageType.ServerDisconnecting));
        try
        {
            Thread.sleep(1000);
        }
        catch (InterruptedException e) {}
        for (ClientConnection clientConnection : clientConnections.values())
        {
            clientConnection.close();
        }
    }

    /**
     * Sends a message to all clients.
     * @param message   The message to be sent.
     */
    synchronized private void sendToAll(Message message)
    {
        for (ClientConnection clientConnection : clientConnections.values())
        {
            clientConnection.send(message);
        }
    }

    /**
     * Sends a message to one client.
     * @param recipient The receiving client.
     * @param message   The message to be sent.
     * @return          True if the message was sent, else false.
     */
    synchronized private boolean sendToOne(String recipient, Message message)
    {
        ClientConnection clientConnection = clientConnections.get(recipient);
        if (clientConnection == null)
        {
            return false;
        }
        else
        {
            clientConnection.send(message);
            return true;
        }
    }
   
    /**
     * Adds a connection to {@link #clientConnections}, adds the client's name to {@link #illegalUsernames}
     * and informs all connected clients that someone connected to the server.
     * @param newConnection The client that connected to the server.
     */
    synchronized private void acceptConnection(ClientConnection newConnection)
    {
        clientConnections.put(newConnection.clientID, newConnection);
        illegalUsernames.add(newConnection.clientID.toLowerCase());
        sendToAll(new Message(MessageType.AClientConnectedToServer, newConnection.clientID));
    }
   
    /**
     * Removes a client from {@link #clientConnections}, removes the username for {@link #illegalUsernames}
     * and informs all connected clients that someone left the server.
     * @param client    The client that has disconnected from the server.
     */
    synchronized private void clientDisconnected(ClientConnection client)
    {
        if (clientConnections.containsKey(client.clientID))
        {
            System.out.println("clientDisconnected: " + client.clientID);
            clientConnections.remove(client.clientID);
            illegalUsernames.remove(client.clientID.toLowerCase());
            Message message = new Message(MessageType.AClientDisconnected, client.clientID);
            sendToAll(message);
        }
    }
   
    /**
     * Calls {@link #clientDisconnected(ClientConnection)}
     * and prints a message to standard error output.
     * @param client        The client that disconnected.
     * @param errorMessage  The message to print.
     */
    synchronized private void connectionToClientClosedWithError(ClientConnection client, String errorMessage)
    {
        clientDisconnected(client);
        System.err.println(errorMessage);
    }
   
    /**
     * A simple class containing a {@link ClientConnection} and a String message.
     * @author Kristoffer Nordkvist
     */
    private class ClientConnectionMessage
    {
        ClientConnection clientConnection;
        Message message;
    }
   
    /**
     * Listen for new clients,
     * if a new client is found it is passed to {@link ClientConnection#ClientConnection(BlockingQueue, Socket)}
     * along with {@link PictionaryServer#incomingMessages}.
     * @author Kristoffer Nordkvist
     */
    private class ServerThread extends Thread
    {
        /**
         * Listens for and accepts new clients.
         */
        @Override
        public void run()
        {
            try
            {
                while (!shutdown)
                {
                    Socket connection = serverSocket.accept();
                    new ClientConnection(incomingMessages, connection);
                }
                System.out.println("Listener socket has shut down gracefully.");
            }
            catch (Exception e)
            {
                if (shutdown)
                    System.out.println("Listener socket encountered and error while being shut down.");
                else
                    System.out.println("Listener socket has been shut down by error: " + e);
            }
        }
    }
   
    /**
     * Handles communication with one client; there is one ClientConnection per connected client.
     * Also extends {@link PictionaryPlayer} so it can be used with {@link PictionaryServer#pictionaryGame}.
     * Has one thread for receiving messages from the client and one for sending messages.
     */
    private class ClientConnection extends PictionaryPlayer
    {
        /**
         * The clients unique identifier, a String containing it's name.
         */
        private String clientID;
       
        /**
         * Received messages are put in this collection,
         * this is a reference to {@link PictionaryServer#incomingMessages}.
         */
        private BlockingQueue<ClientConnectionMessage> incomingMessages;
       
        /**
         * A collection of messages waiting to be sent to the client.
         */
        private LinkedBlockingQueue<Message> outgoingMessages;
       
        /**
         * The Socket used for getting the in and output streams.
         */
        private Socket connection;
       
        /**
         * The stream used for reading messages from the client.
         */
        private ObjectInputStream in;
       
        /**
         * The stream used for sending messages to the client.
         */
        private ObjectOutputStream out;
       
        /**
         * Is set to true if the client should be disconnected gracefully.
         */
        private volatile boolean closed;
       
        /**
         * The {@link SendThread} instance.
         */
        private Thread sendThread;
       
        /**
         * Takes care of receiving and forwarding messages from the client to the server.
         */
        private volatile Thread receiveThread;
       
        /**
         * The constructor.
         * @param receivedMessageQueue  The queue where received messages will be put.
         * @param connection            The Socket that will be used to get streams from.
         */
        public ClientConnection(BlockingQueue<ClientConnectionMessage> receivedMessageQueue, Socket connection)
        {
            super(0, -1);
            System.out.println("NEW ClientConnection");
            this.connection = connection;
            incomingMessages = receivedMessageQueue;
            outgoingMessages = new LinkedBlockingQueue<Message>();
            sendThread =  new SendThread();
            sendThread.start();
        }
       
        /**
         * Get method for {@link #clientID}.
         */
        public String getClientID()
        {
            return clientID;
        }
       
        /**
         * Closes this connection and terminates the send and receive threads.
         */
        private void close()
        {
            closed = true;
            sendThread.interrupt();
            if (receiveThread != null)
            {
                receiveThread.interrupt();
            }
            try
            {
                connection.close();
            }
            catch (IOException e) { }
        }
       
        /**
         * Adds a message to {@link #outgoingMessages}.
         * @param message   The message to be sent.
         */
        public void send(Message message)
        {
            outgoingMessages.add(message);
        }
       
        /**
         * Sends the message to {@link PictionaryServer#connectionToClientClosedWithError(ClientConnection, String)}
         * and calls {@link #close()}.
         * @param message   The message to be printed.
         */
        private void closedWithError(String message)
        {
            connectionToClientClosedWithError(this, message);
            close();
        }
       
        /**
         * Initially handles setup,
         * then takes care of sending messages to the client.
         * @author Kristoffer Nordkvist
         */
        private class SendThread extends Thread
        {
            /**
             * This is where SendThread does all the work.
             */
            @Override
            public void run()
            {
                try
                {
                    out = new ObjectOutputStream(connection.getOutputStream());
                    in = new ObjectInputStream(connection.getInputStream());
                    // Be klienten om ett anv�ndarnamn tills den ger oss ett som blir godk�nt.
                    while(true)
                    {
                        out.writeObject(new Message(MessageType.ServerRequestUsername));
                        out.flush();
                        Message message = (Message)in.readObject();
                        if(message == null)
                        {
                            ClientConnection.this.closedWithError("The client is not behaving");
                            return;
                        }
                        if(message.messageType == MessageType.ClientUsernameResponse)
                        {
                            // Anv�ndarnamnet �r OK.
                            if(validusername(message.client))
                            {
                                // Sluta be om ett anv�ndarnamn.
                                ClientConnection.this.clientID = message.client;
                                break;
                            }
                        }
                    }
                    acceptConnection(ClientConnection.this);
                    StatusData clients = new StatusData(getClients());
                    Message serverAccept = Message.CreateDataMessage(MessageType.ServerAcceptedConnection, clients);
                    out.writeObject(serverAccept);
                    out.flush();
                    receiveThread = new ReceiveThread();
                    receiveThread.start();
                }
                catch(Exception e)
                {
                    try
                    {
                        closed = true;
                        connection.close();
                    }
                    catch (Exception e1)
                    {
                    }
                    System.out.println("Error while setting up connection:\n");
                    e.printStackTrace();
                    return;
                }
                try
                {
                    // Get messages from outgoingMessages queue and send them.
                    while (!closed)
                    {
                        try
                        {
                            Message message = outgoingMessages.take();
                            out.reset();
                            out.writeObject(message);
                            out.flush();
                            /*if (message.messageType == MessageType.DisconnectRequest) // A signal to close the connection.
                            {
                                outgoingMessages.clear();
                                close();
                            }*/
                        }
                        catch (InterruptedException e)
                        {
                            // should mean that connection is closing
                        }
                    }
                }
                catch (IOException e)
                {
                    if (!closed)
                    {
                        closedWithError("Error while sending data to client.");
                        System.out.println("PictionaryServer send thread terminated by IOException: " + e);
                    }
                }
                catch (Exception e)
                {
                    if (!closed)
                    {
                        closedWithError("Internal Error: Unexpected exception in output thread: " + e);
                        System.out.println("\nUnexpected error shuts down PictionaryServer's send thread:");
                        e.printStackTrace();
                    }
                }
            }

        } // end SendThread

        /**
         * Receives messages from the client and adds them to the server's message queue.
         */
        private class ReceiveThread extends Thread
        {
            /**
             * This is where ReceiveThread does all the work.
             */
            @Override
            public void run()
            {
                try
                {
                    while (!closed)
                    {
                        try
                        {
                            Message message = (Message)in.readObject();
                            ClientConnectionMessage clientConnectionMessage = new ClientConnectionMessage();
                            clientConnectionMessage.clientConnection = ClientConnection.this;
                            clientConnectionMessage.message = message;
                            incomingMessages.put(clientConnectionMessage);
                        }
                        catch (InterruptedException e)
                        {
                            // should mean that connection is closing
                            return;
                        }
                    }
                }
                catch (IOException e)
                {
                    if (!closed)
                    {
                        closedWithError("Error while reading data from client.");
                        System.out.println("PictionaryServer receive thread terminated by IOException: " + e);
                    }
                }
                catch (Exception e)
                {
                    if (!closed)
                    {
                        closedWithError("Internal Error: Unexpected exception in input thread: " + e);
                        System.out.println("\nUnexpected error shuts down PictionaryServer's receive thread:");
                        e.printStackTrace();
                    }
                }
            }
        }

        //------------------------ PictionaryPlayer abstract method implementations
        //--------------------------------------------------------------------------
        @Override
        public void stopDraw()
        {
            send(new Message(MessageType.StopDrawing));
        }
       
        @Override
        public void playerStoppedDrawing(String clientID)
        {
            send(new Message(MessageType.AClientStoppedDrawing, clientID));
        }
       
        @Override
        public void startDraw(String wordToDraw)
        {
            StartDrawData startDrawData = new StartDrawData(wordToDraw, pictionaryGame.drawTimeLimit);
            Message theMessage =
                    Message.CreateDataMessage(MessageType.StartDrawing, startDrawData);
            send(theMessage);
        }

        @Override
        public void playerStartedDrawing(String clientID)
        {
           
            send(new Message(MessageType.AClientStartedDrawing, clientID));
        }
       
        @Override
        public void gameStarted()
        {
            send(Message.CreateDataMessage(MessageType.ServerMessage, "A new game of pictionary started. " +
                "The category is \"" + pictionaryGame.getCategory() + "\"."));
        }
       
        @Override
        public void correctGuess(String guess)
        {
            send(Message.CreateDataMessage(MessageType.CorrectGuess, guess));
        }

        @Override
        public void correctGuessBroadcast(String clientID, String guess)
        {
            send(Message.CreateDataMessage(MessageType.AClientCorrectGuess, clientID, guess));
        }

        @Override
        public void startGuessing()
        {
            send(new Message(MessageType.StartGuessing));
        }

        @Override
        public void stopGuessing()
        {
            send(new Message(MessageType.StopGuessing));
        }

        @Override
        public void wrongGuess(String clientID, String guess)
        {
            send(Message.CreateDataMessage(MessageType.AClientIncorrectGuess, clientID, guess));
        }

        @Override
        public void reportScores(List<String> players, List<Integer> scores)
        {
            StringBuilder message = new StringBuilder();
            int highScore = -1;
            for(int i = 0; i < players.size(); ++ i)
            {
                message.append(players.get(i) + " finished with " + scores.get(i) + " points.\n");
                if(scores.get(i) > highScore)
                {
                    highScore = scores.get(i);
                }
            }

            ArrayList<String> winners = new ArrayList<String>();
            for(int i = 0; i < scores.size(); ++i)
            {
                if(scores.get(i) == highScore)
                {
                    winners.add(players.get(i));
                }
            }

            if(winners.size() == 1)
            {
                message.append("The winner is " + winners.get(0) + " with " + highScore + " points.");
            }
            else
            {
                message.append("The winners, with " + highScore + " points, are:");
                String delim = "\n";
                for(String winner : winners)
                {
                    message.append(delim).append(winner);
                    delim = ",\n";
                }
            }
            send(Message.CreateDataMessage(MessageType.ServerMessage, message.toString()));
        }
       
        @Override
        public void tellWord(String word)
        {
            send(Message.CreateDataMessage(MessageType.ServerMessage, "The word was \"" + word + "\""));
        }

        //--------------------------- end PictionaryPlayer abstract method implementations
        //---------------------------------------------------------------------------------

    // end nested class ClientConnection

    /**
     * Tries to read settings.txt and then start the server.
     * If settings.txt does not exist, a new one is created and we read that one instead.
     */
    public static void main(String[] args)
    {
        final String currentDirectory = System.getProperty("user.dir");
        File settingsFile = new File(currentDirectory + "\\settings.txt");

        // Filen finns inte, skapa en ny med standarnv�rden
        if(!settingsFile.exists())
        {
            final String newline = System.getProperty("line.separator");
            try
            {
                FileWriter fstream = new FileWriter(settingsFile);
                BufferedWriter writer = new BufferedWriter(fstream);
                writer.write("comment#This is a generated version of the settings file.#" + newline);
                writer.write("host#127.0.0.1#" + newline);
                writer.write("port#2012#" + newline);
                writer.write("category#Mixed categories#" + newline);
                writer.write("wordfile#"+currentDirectory + "\\mixed.txt#");
                writer.close();
            }
            catch (Exception ex)
            {
                System.err.println("Error: " + ex.getMessage());
            }
            System.err.println("The settings file was missing, but I have created a new one for you. You're welcome.");
        } // end if

        Scanner scanner;
        String host = "";
        int port = -1;
        String category = "";
        String wordFilePath = "";
        boolean useDefault = false;
        // L�s in inst�llningarna fr�n filen
        try
        {
            scanner = new Scanner(new FileReader(settingsFile));
            scanner.useDelimiter("#");
        }
        catch (FileNotFoundException fnfex)
        {
            System.err.println("The settings file coult not be found...");
            useDefault = true;
            return;
        }
        try
        {
            System.out.println("Reading settings from file:");
            while ( scanner.hasNextLine() )
            {
                if ( scanner.hasNext() )
                {
                    String name = scanner.next().trim();
                    String value = scanner.next().trim();
                    if(name.equals("comment"))
                    {
                        System.out.println("Comment: " + value.trim());
                        continue;
                    }
                    System.out.println("Setting name is '" + name + "' and value is '" + value + "'.");
                    if(name.equals("host")) host = value;
                    else if(name.equals("port")) port = Integer.parseInt(value);
                    else if(name.equals("category")) category = value;
                    else if(name.equals("wordfile")) wordFilePath = value;
                }
                else
                {
                    break;
                }
            }
            System.out.println("Finished reading settings file.");
        }
        catch (Exception ex)
        {
            useDefault = true;
        }
        if(useDefault)
        {
            useDefault = true;
            System.err.println("The settings file coult not be read... Using default values instead.");
            host = "127.0.0.1";
            port = 2012;
            category = "Mixed categories";
            wordFilePath = currentDirectory + "\\mixed.txt";
        }
        ArrayList<String> words = new ArrayList<String>();
        System.out.println("Trying to read words from the file '" + wordFilePath + "'.");
        try
        {
            File wordFile = new File(wordFilePath);
            scanner = new Scanner(new FileReader(wordFile));
            while ( scanner.hasNextLine() )
            {
                words.add(scanner.nextLine());
            }
            System.out.println("Finished reading " + words.size() + " words.");
        }
        catch(Exception e)
        {
            System.err.println("Error reading word file, exiting.");
            System.exit(ERROR);
        }
        finally
        {
            scanner.close();
            final PictionaryServer server = new PictionaryServer(host, port, category, words);

            EventQueue.invokeLater(new Runnable()
            {
                public void run()
                {
                    server.setVisible(true);
                }
            });
        }
    }
}
TOP

Related Classes of pictionary.pictionaryserver.PictionaryServer$ClientConnection$SendThread

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.