package nettext.client; import java.util.List; import java.util.Vector; import nettext.messaging.MessageFactory; import nettext.messaging.MessageSettings; import nettext.messaging.AbstractMessage; import nettext.client.networking.ClientNetworking; import nettext.client.gui.ClientUI; import nettext.document.Document; import nettext.file.ASCIIDocumentReader; import nettext.file.HTMLDocumentReader; import nettext.file.ASCIIOutputHandler; import nettext.file.HTMLOutputHandler; /** * Class Client: This singleton class will tie everything together - * the networking, the ui, etc. * *
 * Revision History:
 *     v1.0 (Feb. 20, 2004) - Created the Client class
 * 
* * @author Vladimir Urazov * @version Version 1.0, Feb. 20, 2004 */ public final class Client { /** * YASLI: Yet Another SingLeton Instance. */ private static Client instance; /** * This is the name under which the user is connected to the * server. If no name was provided, a generic name will be used. */ private String userName; /** * The object that encapsulates the networking functionality for the * client. */ private ClientNetworking network; /** * This guy will be used to handle all of the message processing for * the client. */ private MessageProcessor processor; /** * Creates a new Client instance. */ private Client() { userName = null; network = new ClientNetworking(); processor = new MessageProcessor(); } /** * That's right... Another singleton! God, am I getting sick of * reimplementing them over and over! Why? Why doesn't java 1.4 have * templates, so I could just make ONE bloody singleton class and * inherit from a templated copy of it? :( * * @return a Client value */ public static Client getInstance() { if (instance == null) { instance = new Client(); } return instance; } /** * Returns the name under which the user is connected to the server. * * @return a String value */ public String getUsername() { return userName; } /** * Gives the user a new name. * * @param name a String value */ protected void setUsername(final String name) { this.userName = name; } /** * Attempts to connect to the server specified in the parameters. * * @param host The hostname of the server to connect to. * @param port The port at which we want to connect to the server. * @param username The username that we want to use for this connection. * @return True if the connection was successful, and false if it failed. */ public boolean connectToServer(final String host, final int port, final String username) { boolean result = false; List data = new Vector(); AbstractMessage message = null; if (username != null) { setUsername(username); } //Connect to the server result = network.connect(host, port); if (!result) { //Could not connect to the server... //Tell ClientUI to issue a warning saying the connection failed. ClientUI.getInstance().showWarning("Connection Failed", "Could not connect to the server."); return false; } //Issue a helo message data.add(getUsername()); message = MessageFactory.getInstance() .makeMessage(MessageSettings.JOIN_TYPE, data); result = sendMessage(message); if (!result) { //Failed to send the HELO message if (ClientSettings.VERBOSE) { System.out.println("Client: Could not send HELO message..."); } //Tell ClientUI to issue a warning ClientUI.getInstance().showWarning("Connection Failed", "Could not send a join message to" + " the server."); network.shutDown(); return false; } return true; } /** * This function will issue a QUIT message to the server and then * tell client networking to shut down. * @param clean Specifies whether or not a QUIT message should be * issued. If this parameter is false, the client will just close * the socket. */ public void disconnectFromServer(final boolean clean) { List data = new Vector(); AbstractMessage message = null; if (!network.isConnected()) { return; } if (clean) { //Issue a quit message: data.add(getUsername()); message = MessageFactory.getInstance() .makeMessage(MessageSettings.QUIT_TYPE, data); sendMessage(message); } //Shut down networking: network.shutDown(); ClientUI.getInstance().hideDocumentListFrame(); } /** * Returns true if the client is currrently connected to the server, * and false if he is not. * * @return a boolean value */ public boolean isConnected() { return network.isConnected(); } /** * Sends a message to the server. If the send succeeds, returns * true. Otherwise returns false. * * @param message an AbstractMessage value * @return a boolean value */ public boolean sendMessage(final AbstractMessage message) { if (message == null) { return false; } if (!network.isConnected()) { return false; } network.sendMessage(message); return true; } /** * This will be called when the client wishes to create a new * document. */ public void createDocument() { //See if we are connected if (!isConnected()) { return; } //Ask the user for a document name String name = ClientUI.getInstance() .showInputDialog("Choose Document Name", "Please choose the name for your new document:", "Document1"); if (name == null) { return; } //Tell the server we have created a new document. It should either //tell us that the document has been added by sending us a DCMT //message, or that one with the same name already exists. List data = new Vector(); Document doc = new Document(); doc.setDocumentName(name); doc.setDocumentLoaded(true); doc.updateDocument(); data.add(doc); sendMessage(MessageFactory.getInstance() .makeMessage(MessageSettings.DOC_TRANSFER_TYPE, data)); } /** * Shows the open dialog first and then performs the loading of the * document, after which, this document is send over to the server * for approval. */ public void importDocument() { //written by Jose Caban //Check for connection if (!isConnected()) { return; } //Pop up the thingamabob to select the file String fileName = ClientUI.getInstance().browseLoadFileName(null); if (fileName == null) { return; } //Check the file type if (fileName.endsWith(".txt")) { /* Load ASCII */ ASCIIDocumentReader asciiDocReader = new ASCIIDocumentReader(); if (!asciiDocReader.initialize(fileName)) { System.err.println("Error Loading Document"); System.err.flush(); ClientUI.getInstance() .showError("File I/O Error", "Error accessing the File"); return; } Document docImportMe = asciiDocReader.readDocument(); if (docImportMe == null) { System.err.println("Error loading the document"); return; } asciiDocReader.cleanUp(); docImportMe.updateDocument(); List v = new Vector(); v.add(docImportMe); sendMessage(MessageFactory.getInstance() .makeMessage(MessageSettings.DOC_TRANSFER_TYPE, v)); } else if (fileName.endsWith(".html") || fileName.endsWith(".htm")) { /* Load HTML */ HTMLDocumentReader htmlDocReader = new HTMLDocumentReader(); if (!htmlDocReader.initialize(fileName)) { System.err.println("Error Loading Document"); System.err.flush(); ClientUI.getInstance() .showError("File I/O Error", "Error accessing the File"); return; } Document docImportMe = htmlDocReader.readDocument(); if (docImportMe == null) { System.err.println("Error loading the document"); return; } htmlDocReader.cleanUp(); List v = new Vector(); v.add(docImportMe); sendMessage(MessageFactory.getInstance() .makeMessage(MessageSettings.DOC_TRANSFER_TYPE, v)); } else { ClientUI.getInstance() .showError("File Type Unsupported", "The file you selected is not Supported"); return; } } /** * Export a Document * @param docExportMe the Document to export */ public void exportDocument(Document docExportMe) { String fileName = ClientUI.getInstance().browseSaveFileName(null); if (fileName == null) { return; } fileName = fileName.substring(0, fileName.length() - 4); if (ClientSettings.VERBOSE) { System.out.println("Export file: " + fileName); } //Check the file type if (fileName.endsWith(".html") || fileName.endsWith(".htm")) { HTMLOutputHandler htmlOutputHandler = new HTMLOutputHandler(); htmlOutputHandler.initialize(fileName); if (!htmlOutputHandler.writeToDisk(docExportMe)) { ClientUI.getInstance().showError("Error Writing File", "The system encountered an error writing the file to disk." + " This is most likely Linux's fault"); } } else { ASCIIOutputHandler asciiOutputHandler = new ASCIIOutputHandler(); asciiOutputHandler.initialize(fileName); if (!asciiOutputHandler.writeToDisk(docExportMe)) { ClientUI.getInstance().showError("Error Writing File", "The system encountered an error writing the file to disk." + " This is most likely Linux's fault"); } asciiOutputHandler.cleanUp(); } } /** * This function receives the message from the server. It needs to * check the type of message first. Then, if the message is a * graphics message, this should send it to the message list, and * tell the graphics panel to rerender. If it is a chat message, it * should be sent to the message list, and then to the chat * panel. Etc. * * @param message an AbstractMessage value */ public void processMessage(final AbstractMessage message) { processor.processMessage(message); } /** * This function will be called by the server listener when the * server drops the connection. It will take appropriate steps to * shut down the connection and notify the user of the problem. */ public void serverQuit() { ClientUI.getInstance().showWarning("Server Lost", "The connection to the server has " + "been lost..."); network.shutDown(); } /** * Shuts down the client. */ public void shutDown() { //FIXME: Implement a clean shutdown. System.exit(0); } }