package com.kritsit.casetracker.server.domain.services;
import com.kritsit.casetracker.server.datalayer.ICaseRepository;
import com.kritsit.casetracker.server.datalayer.IPersonRepository;
import com.kritsit.casetracker.server.datalayer.IUserRepository;
import com.kritsit.casetracker.server.datalayer.RepositoryFactory;
import com.kritsit.casetracker.server.datalayer.RowToModelParseException;
import com.kritsit.casetracker.server.domain.model.AuthenticationException;
import com.kritsit.casetracker.shared.domain.Request;
import com.kritsit.casetracker.shared.domain.Response;
import com.kritsit.casetracker.shared.domain.model.Case;
import com.kritsit.casetracker.shared.domain.model.Staff;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
import java.util.List;
public class ClientConnectionThread implements Runnable, IClientConnectionService {
private final Logger logger = LoggerFactory.getLogger(ClientConnectionThread.class);
private Socket socket = null;
private String connectedClient;
private ObjectInputStream in;
private ObjectOutputStream out;
public ClientConnectionThread(Socket socket) {
this.socket = socket;
}
public void run() {
try {
logger.debug("Connection thread started");
in = new ObjectInputStream(socket.getInputStream());
out = new ObjectOutputStream(socket.getOutputStream());
Request request;
while ((request = (Request) in.readObject()) != null) {
switch (request.getCommand()) {
case "connect" : {
setConnectedClient(request.getArguments().get(0).toString());
logger.info("{} has connected", connectedClient);
break;
}
case "login" : {
try {
logger.debug("Login requested");
IUserRepository repository = RepositoryFactory.getUserRepository();
ILoginService login = new Login(repository);
Staff user = login.login(request.getArguments().get(0).toString(),
Integer.parseInt(request.getArguments().get(1).toString()));
Response dto = new Response(200, user);
writeResponse(dto);
} catch (AuthenticationException ex){
Response dto = new Response(401, null);
writeResponse(dto);
}
break;
}
case "getCases" : {
ICaseRepository caseRepo = RepositoryFactory.getCaseRepository();
List<Case> cases;
if (request.getArguments().size() == 0) {
logger.debug("All cases requested");
cases = caseRepo.getCases();
} else {
Staff user = (Staff) request.getArguments().get(0);
logger.debug("Cases requested for user {}", user);
cases = caseRepo.getCases(user);
}
Response dto = new Response(200, cases);
writeResponse(dto);
break;
}
case "getInspectors" : {
logger.debug("Inspectors requested");
IUserRepository userRepo = RepositoryFactory.getUserRepository();
List<Staff> inspectors = userRepo.getInspectors();
Response dto = new Response(200, inspectors);
writeResponse(dto);
break;
}
case "getStaff" : {
logger.debug("Staff requested");
IUserRepository userRepo = RepositoryFactory.getUserRepository();
List<Staff> staff = userRepo.getStaff();
Response dto = new Response(200, staff);
writeResponse(dto);
break;
}
case "getLastCaseNumber" : {
logger.debug("Last case number requested");
ICaseRepository caseRepo = RepositoryFactory.getCaseRepository();
String caseNumber = caseRepo.getLastCaseNumber();
Response dto = new Response(200, caseNumber);
writeResponse(dto);
break;
}
case "addCase" : {
Case c = (Case) request.getArguments().get(0);
logger.debug("Requested to add case: {}", c);
ICaseRepository caseRepo = RepositoryFactory.getCaseRepository();
caseRepo.insertCase(c);
Response dto = new Response(200, "Case added");
writeResponse(dto);
break;
}
case "addUser" : {
Staff user = (Staff) request.getArguments().get(0);
logger.debug("Requested to add user: {}", user);
IUserRepository userRepo = RepositoryFactory.getUserRepository();
userRepo.insertUser(user);
Response dto = new Response(200, "User added");
writeResponse(dto);
break;
}
case "editCase" : {
Case c = (Case) request.getArguments().get(0);
logger.debug("Edit case requested for: {}", c.toString());
ICaseRepository caseRepo = RepositoryFactory.getCaseRepository();
caseRepo.updateCase(c);
Response dto = new Response(200, "Case edited");
writeResponse(dto);
break;
}
case "editUser" : {
Staff user = (Staff) request.getArguments().get(0);
logger.debug("Edit user requested for: {}", user.toString());
IUserRepository userRepo = RepositoryFactory.getUserRepository();
userRepo.updateUser(user);
Response dto = new Response(200, "User edited");
writeResponse(dto);
break;
}
case "deleteUser" : {
String username = (String) request.getArguments().get(0);
logger.debug("Requested to delete user: {}", username);
IUserRepository userRepo = RepositoryFactory.getUserRepository();
userRepo.deleteUser(username);
Response dto = new Response(200, "User deleted");
writeResponse(dto);
break;
}
case "changePassword" : {
String username = (String) request.getArguments().get(0);
int passHash = (int) request.getArguments().get(1);
logger.debug("Requested to change password for {}", username);
IUserRepository userRepo = RepositoryFactory.getUserRepository();
userRepo.setPassword(username, passHash);
Response dto = new Response(200, "Password changed");
writeResponse(dto);
break;
}
case "checkForUpdate" : {
try {
String currentVersion = (String) request.getArguments().get(0);
logger.debug("Checking for update to client version {}", currentVersion);
IUpdateService updater = new Updater();
boolean updateRequired = updater.isUpdateRequired(currentVersion);
Response dto = new Response(200, updateRequired);
writeResponse(dto);
} catch (IOException ex) {
logger.error("Error occurred checking for update to client", ex);
Response dto = new Response(404, "Client archive not found");
writeResponse(dto);
}
break;
}
case "getUpdate" : {
try {
IUpdateService updater = new Updater();
byte[] update = updater.getUpdate();
Response dto = new Response(200, update);
writeResponse(dto);
} catch (IOException ex) {
logger.error("Error occurred getting update to client", ex);
Response dto = new Response(500,
"Client archive cannot be serialized");
writeResponse(dto);
}
break;
}
case "close" : {
close();
logger.info("{} has disconnected", connectedClient);
return;
}
default : {
Response dto = new Response(404, "Request not found");
writeResponse(dto);
break;
}
}
}
} catch (IOException | RowToModelParseException | ClassNotFoundException ex) {
logger.error("An error occured", ex);
Response dto = new Response(500, ex.getMessage());
try {
writeResponse(dto);
} catch (IOException e) {
logger.error("Unable to write to client", e);
}
}
}
public void setConnectedClient(String connectedClient) {
this.connectedClient = connectedClient;
}
public String getConnectedClient() {
return connectedClient;
}
public void close() throws IOException {
try {
logger.info("Closing connection");
in.close();
out.close();
socket.close();
} catch (NullPointerException ex) {
logger.error("Socket is not connected");
}
}
private void writeResponse(Response dto) throws IOException {
out.writeObject(dto);
out.flush();
}
}