coder-client/src/com/coder/client/CoderClient.java

453 lines
14 KiB
Java
Raw Normal View History

2015-10-09 13:37:45 +00:00
package com.coder.client;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.Properties;
2015-10-09 13:37:45 +00:00
import java.util.logging.Level;
import java.util.logging.Logger;
import com.coder.client.gui.GuiWindow;
2015-10-20 14:26:58 +00:00
import com.coder.client.gui.editor.EditorWindow;
import com.coder.client.gui.editor.EditorWindowListener;
import com.coder.client.gui.login.LoginDialog;
import com.coder.client.gui.login.LoginDialogListener;
import com.coder.client.gui.newProject.NewProjectDialog;
import com.coder.client.gui.newProject.NewProjectDialogListener;
import com.coder.client.gui.selectProject.SelectProjectDialog;
import com.coder.client.gui.selectProject.SelectProjectDialogListener;
import com.coder.client.gui.selectServer.SelectServerDialog;
import com.coder.client.gui.selectServer.SelectServerDialogListener;
2015-11-04 23:37:54 +01:00
import com.coder.server.message.*;
2015-10-09 13:37:45 +00:00
import zutil.log.CompactLogFormatter;
2015-10-09 13:37:45 +00:00
import zutil.log.LogUtil;
import zutil.net.ssdp.SSDPClient;
import zutil.net.ssdp.SSDPClient.SSDPServiceListener;
import zutil.net.ssdp.StandardSSDPInfo;
2015-10-20 14:26:58 +00:00
import javafx.application.Application;
import javafx.application.Platform;
2015-10-20 14:26:58 +00:00
import javafx.stage.Stage;
2015-10-09 13:37:45 +00:00
2015-10-20 14:26:58 +00:00
public class CoderClient extends Application{
2015-10-09 13:37:45 +00:00
public static final Logger logger = LogUtil.getLogger();
2015-10-09 13:37:45 +00:00
private Session session;
2015-10-20 14:26:58 +00:00
private Stage mainStage;
//GUI elements
2015-10-20 14:26:58 +00:00
private EditorWindow editorWindow;
private LoginDialog loginDialog;
private SelectProjectDialog selectProjectDialog;
private SelectServerDialog selectServerDialog;
private NewProjectDialog newProjectDialog;
//state variables
private GuiWindow projectSelectionWindow = null; //points to the GUI that selected a project for the editor. If any error occurs while creating/loading the project, this is the window we will go back to.
//services
SSDPClient ssdpClient;
2015-10-20 14:26:58 +00:00
public static void main(String[] args) {
Application.launch(args);
}
2015-10-20 14:26:58 +00:00
@Override
public void start(Stage mainStage) throws Exception {
2015-10-20 14:26:58 +00:00
//setup logging
2015-10-28 12:56:22 +01:00
CompactLogFormatter formatter = new CompactLogFormatter();
2015-10-29 12:52:11 +01:00
LogUtil.setLevel("com.coder", Level.FINEST);
2015-10-28 12:56:22 +01:00
LogUtil.setFormatter("com.coder", formatter);
2015-10-29 12:52:11 +01:00
LogUtil.setLevel("zutil", Level.FINEST);
LogUtil.setFormatter("zutil", formatter);
LogUtil.setGlobalFormatter(formatter);
//setup GUI elements
this.mainStage = mainStage;
mainStage.setTitle("CoderClient");
try{
setupSelectServerDialog();
setupLoginDialog();
setupSelectProjectDialog();
setupEditWindow();
setupNewProjectDialog();
}catch(IOException e){
logger.log(Level.SEVERE, "could not load all GUI elements", e);
System.exit(1);
}
2015-10-20 14:26:58 +00:00
//parse program arguments
Map<String, String> params = this.getParameters().getNamed();
for(String key : params.keySet()){
String value = params.get(key);
if(key.equals("username")){
loginDialog.setUsername(value);
2015-10-20 14:26:58 +00:00
}else if(key.equals("password")){
loginDialog.setPassword(value.toCharArray());
}else if(key.equals("url")){
selectServerDialog.setServerAddress(value);
}else if(key.equals("port")){
try{
selectServerDialog.setServerPort(Integer.parseInt(value));
}catch(NumberFormatException e){
logger.warning("port argument to program is not of a integer type");
selectServerDialog.setServerPort(-1);
}
}else if(key.equals("project")){
selectProjectDialog.setProject(value);
2015-10-20 14:26:58 +00:00
}
}
//setup SSDP client
try{
setupSSDPClient();
}catch(IOException e){
logger.log(Level.SEVERE, "could not setup SSDP client", e);
System.exit(1);
}
2015-10-20 14:26:58 +00:00
//start program logic
selectServerDialog.setServerPort(-1);
selectServerDialog.showOnStage(mainStage);
2015-10-09 13:37:45 +00:00
}
private void setupSelectServerDialog() throws IOException{
this.selectServerDialog = new SelectServerDialog();
this.selectServerDialog.addSelectProjectDialogListener(new SelectServerDialogListener() {
@Override
public void willShow() {
logger.fine("about to show select server dialog on main stage");
closeCurrentSession();
selectServerDialog.clearServerList();
if(ssdpClient != null){
ssdpClient.requestService("coder:discover");
2015-10-29 20:40:27 +01:00
for(StandardSSDPInfo server : ssdpClient.getServices("coder:discover"))
selectServerDialog.addServerToList(server.getInetAddress().getHostAddress(), 1337);
}else{
logger.severe("could not send a SSDP request since the client is not setup");
}
}
@Override
public void exit() {
logger.info("terminating");
Platform.exit();
}
@Override
public void connect(String address, int port) {
//connect session
session = Session.setupConnection(address, port);
if(session == null){
logger.warning("Could not setup a connection to " + address + ":" + port);
selectServerDialog.setServerAddress(null);
selectServerDialog.setErrorMessage("ERROR: Unable to connect to remote host");
loginDialog.setErrorMessage("");
selectServerDialog.showOnStage(mainStage);
}else{
selectServerDialog.setErrorMessage("");
loginDialog.showOnStage(mainStage);
}
}
});
}
private void setupLoginDialog() throws IOException {
this.loginDialog = new LoginDialog();
this.loginDialog.addLoginDialogListener(new LoginDialogListener(){
@Override
public void willShow() {
logger.fine("about to show login dialog on main stage");
}
@Override
public void cancel() {
loginDialog.setErrorMessage("");
selectServerDialog.setServerAddress(null);
selectServerDialog.showOnStage(mainStage);
}
@Override
public void login(String username, char[] password) {
//authenticate session
boolean authenticated = session.authenticate(username, password);
if(!authenticated){
logger.severe("Authentication failed: wrong username or password");
loginDialog.setPassword(null);
loginDialog.setErrorMessage("Wrong username or password");
selectServerDialog.showOnStage(mainStage);
return;
}else{
loginDialog.setErrorMessage("");
setupSessionListener(); //resister a message listener to the session
session.start(); //start receiving traffic from the server
selectProjectDialog.showOnStage(mainStage);
}
}
});
}
/**
* To be called after a session has been connected and authenticated
*/
private void setupSessionListener(){
if(session == null){
logger.warning("Cannot setup session listeners for null instance. ignoring call.");
return;
}
if(!session.isAuthenticated()){
logger.warning("Cannot setup session listeners for a non-authenticated session. ignoring call.");
return;
}
// create a guard for when the session is closed
new Thread(new Runnable(){
@Override
public void run() {
logger.fine("starting a session guard");
while(true){
if(session == null || !session.isConnected()){
logger.fine("session guard: no connection");
Platform.runLater(new Runnable() {
@Override
public void run() {
selectServerDialog.setErrorMessage("The current session was disconnected");
closeCurrentSession();
selectServerDialog.showOnStage(mainStage);
}
});
break;
}
Thread.yield();
}
logger.fine("terminating session guard");
}}).start();
session.addCoderMessageReceivedListener(new CoderMessageReceivedListener() {
@Override
2015-11-04 23:37:54 +01:00
public void projectListRspReceived(final ProjectListRspMsg projectListRsp) {
logger.fine("a ProjectListRsp received");
Platform.runLater(new Runnable() {
@Override
public void run() {
for(String projectName : projectListRsp.keySet()){
ProjectListData projectData = projectListRsp.get(projectName);
selectProjectDialog.addProjectToList(projectName, projectData);
}
}
});
}
@Override
public void projectRspReceived(final ProjectRspMsg projectRspMsg) {
logger.fine("a ProjectRspMsg received");
Platform.runLater(new Runnable() {
@Override
public void run() {
if(projectRspMsg.error != null){
logger.severe("Server responded on the project request with the following error message: " + projectRspMsg.error);
selectProjectDialog.setProject(null);
if(projectSelectionWindow != null){
projectSelectionWindow.setErrorMessage("ERROR: " + projectRspMsg.error);
projectSelectionWindow.showOnStage(mainStage);
return;
}else{
selectProjectDialog.setErrorMessage("ERROR: " + projectRspMsg.error);
selectProjectDialog.showOnStage(mainStage);
return;
}
}else{
if(projectSelectionWindow != null){
projectSelectionWindow.setErrorMessage("");
}
editorWindow.setProjectName(projectRspMsg.name);
Properties projectConfig = projectRspMsg.config;
String projectDescription = projectRspMsg.description;
List<String> projectFileList = projectRspMsg.fileList;
String projectName = projectRspMsg.name;
String projectType = projectRspMsg.type;
//TODO: handle msg
}
}
});
}
@Override
2015-11-04 23:37:54 +01:00
public void projectTypeRspReceived(final ProjectTypeRspMsg projectTypeRsp) {
logger.fine("a ProjectTypeRspMsg received");
Platform.runLater(new Runnable() {
@Override
public void run() {
for(String typeName : projectTypeRsp.keySet()){
2015-11-04 23:37:54 +01:00
SupportedProperties typeData = projectTypeRsp.get(typeName);
newProjectDialog.addProjectTypeToList(typeName, typeData);
}
}
});
}
});
}
private void setupSelectProjectDialog() throws IOException {
this.selectProjectDialog = new SelectProjectDialog();
2015-10-20 14:26:58 +00:00
this.selectProjectDialog.addSelectProjectDialogListener(new SelectProjectDialogListener() {
@Override
public void willShow() {
logger.fine("about to show select project dialog on main stage");
2015-10-20 14:26:58 +00:00
selectProjectDialog.clearProjectList();
if(!selectProjectDialog.isProjectSelected()){
sendProjectListReq();
}
}
@Override
public void open(String selectedProjectName) {
projectSelectionWindow = selectProjectDialog;
editorWindow.showOnStage(mainStage);
}
@Override
public void newProject() {
selectProjectDialog.setProject(null);
newProjectDialog.showOnStage(mainStage);
}
@Override
public void cancel() {
loginDialog.setPassword(null);
selectServerDialog.setServerAddress(null);
selectServerDialog.showOnStage(mainStage);
}
@Override
public void refresh() {
selectProjectDialog.clearProjectList();
sendProjectListReq();
}
private void sendProjectListReq(){
2015-10-20 14:26:58 +00:00
//send a request for a new list of projects
CoderMessage msg = new CoderMessage();
msg.ProjectListReq = new ProjectListReqMsg();
try {
session.send(msg);
} catch (IOException e) {
logger.log(Level.SEVERE, "Unable to send ProjectListReqMsg", e);
closeCurrentSession();
}
}
});
}
private void setupNewProjectDialog() throws IOException {
this.newProjectDialog = new NewProjectDialog();
this.newProjectDialog.addNewProjectDialogListener(new NewProjectDialogListener(){
@Override
public void willShow() {
logger.fine("about to show new project dialog on main stage");
newProjectDialog.clearProjectTypeList();
sendProjectTypeReqMsg();
}
@Override
public void create(String newProjectName, String projectType, String projectDescription) {
projectSelectionWindow = newProjectDialog;
sendProjectCreateReqMsg(newProjectName, projectType, projectDescription);
selectProjectDialog.setProject(newProjectName);
editorWindow.showOnStage(mainStage);
}
private void sendProjectTypeReqMsg(){
CoderMessage msg = new CoderMessage();
msg.ProjectTypeReq = new ProjectTypeReqMsg();
try {
session.send(msg);
} catch (IOException e) {
logger.log(Level.SEVERE, "Unable to send ProjectTypeReq", e);
closeCurrentSession();
}
}
private void sendProjectCreateReqMsg(String projectName, String projectType, String projectDescription){
CoderMessage msg = new CoderMessage();
msg.ProjectCreateReq = new ProjectCreateReqMsg();
msg.ProjectCreateReq.name = projectName;
msg.ProjectCreateReq.type = projectType;
msg.ProjectCreateReq.description = projectDescription;
try {
session.send(msg);
} catch (IOException e) {
logger.log(Level.SEVERE, "Unable to send ProjectCreateReq", e);
closeCurrentSession();
}
}
@Override
public void cancel() {
selectProjectDialog.setProject(null);
selectProjectDialog.showOnStage(mainStage);
}
});
}
private void setupEditWindow() throws IOException {
this.editorWindow = new EditorWindow();
this.editorWindow.addEditorWindowListener(new EditorWindowListener() {
2015-10-20 14:26:58 +00:00
@Override
public void willShow() {
logger.fine("about to show edit window on main stage");
sendProjectReqMsg();
2015-10-20 14:26:58 +00:00
}
@Override
public void compile() {
2015-10-20 14:26:58 +00:00
//TODO
}
@Override
public void run() {
//TODO
2015-10-20 14:26:58 +00:00
}
private void sendProjectReqMsg(){
if(!selectProjectDialog.isProjectSelected()){
logger.severe("Cannot send a project request when no project is selected");
return;
}
CoderMessage msg = new CoderMessage();
msg.ProjectReq = new ProjectReqMsg();
msg.ProjectReq.name = selectProjectDialog.getSelectedProject();
try {
session.send(msg);
} catch (IOException e) {
logger.log(Level.SEVERE, "Unable to send ProjectReqMsg", e);
closeCurrentSession();
}
}
@Override
public void changeProject() {
selectProjectDialog.setProject(null);
selectProjectDialog.showOnStage(mainStage);
}
@Override
public void exit() {
closeCurrentSession();
Platform.exit();
}
2015-10-20 14:26:58 +00:00
});
}
private void setupSSDPClient() throws IOException{
this.ssdpClient = new SSDPClient();
ssdpClient.setListener(new SSDPServiceListener() {
@Override
public void newService(final StandardSSDPInfo service) {
if(selectServerDialog != null){
Platform.runLater(new Runnable() {
@Override
public void run() {
String ip = service.getInetAddress().getHostAddress();
selectServerDialog.addServerToList(ip, 1337);
}
});
2015-10-28 12:56:22 +01:00
} else {
logger.warning("New Service found ("+service.getLocation()+") when stage closed.");
}
}
});
ssdpClient.start();
}
2015-10-20 14:26:58 +00:00
private void closeCurrentSession(){
if(this.session != null){
logger.info("disconnecting from server");
2015-10-20 14:26:58 +00:00
session.close();
session = null;
}
}
2015-10-09 13:37:45 +00:00
}