first commit
This commit is contained in:
418
CS2335/lab5/src/nettext/client/Client.java
Normal file
418
CS2335/lab5/src/nettext/client/Client.java
Normal file
@@ -0,0 +1,418 @@
|
||||
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.
|
||||
*
|
||||
* <PRE>
|
||||
* Revision History:
|
||||
* v1.0 (Feb. 20, 2004) - Created the Client class
|
||||
* </PRE>
|
||||
*
|
||||
* @author <A HREF="mailto:gtg308i@mail.gatech.edu">Vladimir Urazov</A>
|
||||
* @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 <code>Client</code> 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 <code>Client</code> 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 <code>String</code> value
|
||||
*/
|
||||
public String getUsername() {
|
||||
return userName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gives the user a new name.
|
||||
*
|
||||
* @param name a <code>String</code> 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 <code>boolean</code> 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 <code>AbstractMessage</code> value
|
||||
* @return a <code>boolean</code> 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 <code>AbstractMessage</code> 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);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user