Implement DMAP communication with MailboxServer
This commit is contained in:
parent
909c4af4e9
commit
fcd00674c2
@ -9,8 +9,8 @@ import java.util.stream.Collectors;
|
|||||||
public class Message {
|
public class Message {
|
||||||
private ArrayList<Email> to = new ArrayList<>();
|
private ArrayList<Email> to = new ArrayList<>();
|
||||||
private Email from;
|
private Email from;
|
||||||
private String subject;
|
private String subject = "";
|
||||||
private String data;
|
private String data = "";
|
||||||
private Integer id;
|
private Integer id;
|
||||||
|
|
||||||
public Message() {
|
public Message() {
|
||||||
@ -80,6 +80,10 @@ public class Message {
|
|||||||
this.id = id;
|
this.id = id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String listMessage() {
|
||||||
|
return getId() + " " + getFrom() + " " + getSubject();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "from " + getFrom().toString() + "\n" +
|
return "from " + getFrom().toString() + "\n" +
|
||||||
|
|||||||
@ -0,0 +1,7 @@
|
|||||||
|
package dslab.exception;
|
||||||
|
|
||||||
|
public class MessageNotFoundException extends Exception {
|
||||||
|
public MessageNotFoundException(String errorMessage) {
|
||||||
|
super(errorMessage);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,4 +1,187 @@
|
|||||||
package dslab.mailbox;
|
package dslab.mailbox;
|
||||||
|
|
||||||
public class DMAPConnection {
|
import dslab.Email;
|
||||||
|
import dslab.Message;
|
||||||
|
import dslab.exception.MessageNotFoundException;
|
||||||
|
|
||||||
|
import java.io.*;
|
||||||
|
import java.net.Socket;
|
||||||
|
import java.net.SocketException;
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
|
public class DMAPConnection implements Runnable {
|
||||||
|
Logger logger = Logger.getLogger(DMAPConnection.class.getName());
|
||||||
|
private final Socket socket;
|
||||||
|
private PrintWriter out;
|
||||||
|
private BufferedReader in;
|
||||||
|
private Email currentUser = null;
|
||||||
|
private final ConcurrentHashMap<Email, LinkedList<Message>> storage;
|
||||||
|
private final ConcurrentHashMap<String, String> userStorage;
|
||||||
|
|
||||||
|
public DMAPConnection(Socket connection, ConcurrentHashMap<Email, LinkedList<Message>> storage, ConcurrentHashMap<String, String> userStorage) {
|
||||||
|
this.socket = connection;
|
||||||
|
this.storage = storage;
|
||||||
|
this.userStorage = userStorage;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
logger.finer("Preparing for DMAP communication in " + this.toString());
|
||||||
|
try {
|
||||||
|
this.out = new PrintWriter(socket.getOutputStream(), true);
|
||||||
|
this.in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
|
||||||
|
out.println("ok DMAP");
|
||||||
|
loginLoop();
|
||||||
|
out.println("ok");
|
||||||
|
|
||||||
|
String userInput;
|
||||||
|
while (!Thread.currentThread().isInterrupted() && (userInput = in.readLine()) != null) {
|
||||||
|
if ("quit".equals(userInput)) {
|
||||||
|
out.println("ok bye");
|
||||||
|
shutdown();
|
||||||
|
} else if ("logout".equals(userInput)) {
|
||||||
|
out.println("ok");
|
||||||
|
currentUser = null;
|
||||||
|
loginLoop();
|
||||||
|
} else if ("list".equals(userInput)) {
|
||||||
|
listMessages();
|
||||||
|
} else if ("delete".equals(userInput.split("\\s+")[0])) {
|
||||||
|
if (userInput.split("\\s+").length == 2) {
|
||||||
|
deleteMessage(userInput.split("\\s+")[1]);
|
||||||
|
} else {
|
||||||
|
out.println("Please supply a message id to delete!");
|
||||||
|
}
|
||||||
|
} else if ("show".equals(userInput.split("\\s+")[0])) {
|
||||||
|
if (userInput.split("\\s+").length == 2) {
|
||||||
|
showMessage(userInput.split("\\s+")[1]);
|
||||||
|
} else {
|
||||||
|
out.println("Please supply a message id to show!");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
out.println("error protocol error");
|
||||||
|
shutdown();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (InterruptedIOException ioe) {
|
||||||
|
logger.info("Received interrupt from parent. Shutting down...");
|
||||||
|
shutdown();
|
||||||
|
} catch (IOException e) {
|
||||||
|
logger.severe("Failed to get IO-Stream");
|
||||||
|
e.printStackTrace();
|
||||||
|
shutdown();
|
||||||
|
} catch (MessageNotFoundException e) {
|
||||||
|
out.println(e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void loginLoop() {
|
||||||
|
String userInput;
|
||||||
|
|
||||||
|
try {
|
||||||
|
while (!Thread.currentThread().isInterrupted()) {
|
||||||
|
userInput = in.readLine();
|
||||||
|
if ("quit".equals(userInput.split("\\s+")[0])) {
|
||||||
|
out.println("ok bye");
|
||||||
|
shutdown();
|
||||||
|
} else if ("login".equals(userInput.split("\\s+")[0])) {
|
||||||
|
String[] args = userInput.split("\\s+");
|
||||||
|
if (args.length != 3)
|
||||||
|
out.println("Please specify a username and password to login!");
|
||||||
|
if (this.userStorage.containsKey(args[1])) {
|
||||||
|
// Check if username exists
|
||||||
|
if (args[2].equals(this.userStorage.get(args[1]))) {
|
||||||
|
// Check if password matches
|
||||||
|
for (Email email : this.storage.keySet()) {
|
||||||
|
if (args[1].equals(email.getUsername())) {
|
||||||
|
// Set current user if login successful
|
||||||
|
currentUser = email;
|
||||||
|
logger.info("User successfully logged in: " + currentUser.toString());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
out.println("error wrong password");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
out.println("error unknown user");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
out.println("error not logged in");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (InterruptedIOException ioe) {
|
||||||
|
logger.info("Received interrupt from parent. Shutting down...");
|
||||||
|
shutdown();
|
||||||
|
} catch (SocketException e) {
|
||||||
|
logger.finer("Received interrupt. Exiting " + this.toString());
|
||||||
|
shutdown();
|
||||||
|
} catch (IOException e) {
|
||||||
|
logger.severe("Failed to get IO-Stream");
|
||||||
|
e.printStackTrace();
|
||||||
|
shutdown();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void showMessage(String id) throws MessageNotFoundException {
|
||||||
|
int i;
|
||||||
|
try {
|
||||||
|
i = Integer.parseInt(id);
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
|
throw new MessageNotFoundException("error unknown message id");
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Message m : storage.get(currentUser)) {
|
||||||
|
if (m.getId() == i) {
|
||||||
|
out.println(m);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new MessageNotFoundException("error unknown message id");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void listMessages() {
|
||||||
|
if (storage.get(currentUser).isEmpty()) {
|
||||||
|
out.println("You do not have any messages at the moment!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Message m : storage.get(currentUser)) {
|
||||||
|
out.println(m.listMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void deleteMessage (String id) throws MessageNotFoundException {
|
||||||
|
int i;
|
||||||
|
try {
|
||||||
|
i = Integer.parseInt(id);
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
|
throw new MessageNotFoundException("error unknown message id");
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Message m : storage.get(currentUser)) {
|
||||||
|
if (m.getId() == i) {
|
||||||
|
storage.get(currentUser).remove(m);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new MessageNotFoundException("error unknown message id");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void shutdown() {
|
||||||
|
logger.info("Shutting down client connection " + this.toString());
|
||||||
|
try {
|
||||||
|
if (socket != null)
|
||||||
|
socket.close();
|
||||||
|
in.close();
|
||||||
|
out.close();
|
||||||
|
} catch (IOException e) {
|
||||||
|
logger.severe("Error closing socket and/or IO-streams");
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
Thread.currentThread().interrupt();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,12 +1,76 @@
|
|||||||
package dslab.mailbox;
|
package dslab.mailbox;
|
||||||
|
|
||||||
|
import dslab.Email;
|
||||||
import dslab.Message;
|
import dslab.Message;
|
||||||
import dslab.transfer.ClientConnection;
|
import dslab.transfer.ClientConnection;
|
||||||
|
|
||||||
import java.io.BufferedReader;
|
import java.io.BufferedReader;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InterruptedIOException;
|
||||||
import java.io.PrintWriter;
|
import java.io.PrintWriter;
|
||||||
|
import java.net.ServerSocket;
|
||||||
import java.net.Socket;
|
import java.net.Socket;
|
||||||
|
import java.net.SocketException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
import java.util.concurrent.ExecutorService;
|
||||||
|
import java.util.concurrent.Executors;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
public class DMAPListener {
|
public class DMAPListener extends Thread {
|
||||||
|
private final ServerSocket serverSocket;
|
||||||
|
private final Logger logger = Logger.getLogger(DMAPListener.class.getName());
|
||||||
|
private final ConcurrentHashMap<Email, LinkedList<Message>> storage;
|
||||||
|
private final ConcurrentHashMap<String, String> userStorage;
|
||||||
|
private final ArrayList<DMAPConnection> clients = new ArrayList<>();
|
||||||
|
private final ExecutorService executorService = Executors.newCachedThreadPool();
|
||||||
|
|
||||||
|
public DMAPListener(ServerSocket serverSocket, ConcurrentHashMap<Email, LinkedList<Message>> storage, ConcurrentHashMap<String, String> userStorage) {
|
||||||
|
this.serverSocket = serverSocket;
|
||||||
|
this.storage = storage;
|
||||||
|
this.userStorage = userStorage;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
while (!Thread.currentThread().isInterrupted()) {
|
||||||
|
logger.finer("Waiting for request on serverSocket " + serverSocket.toString());
|
||||||
|
try {
|
||||||
|
Socket s = serverSocket.accept();
|
||||||
|
logger.fine("Processing incoming socket " + s.toString());
|
||||||
|
DMAPConnection dmapConnection = new DMAPConnection(s, storage, userStorage);
|
||||||
|
clients.add(dmapConnection);
|
||||||
|
executorService.submit(dmapConnection);
|
||||||
|
} catch (InterruptedIOException | SocketException e) {
|
||||||
|
logger.finer("Received interrupt. Exiting " + this.toString());
|
||||||
|
this.shutdown();
|
||||||
|
} catch (IOException e) {
|
||||||
|
logger.severe("Error starting serverSocket " + serverSocket.toString());
|
||||||
|
e.printStackTrace();
|
||||||
|
this.shutdown();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void shutdown() {
|
||||||
|
logger.finer("Shutting down DMAPListener " + this.toString());
|
||||||
|
for (DMAPConnection client : clients) {
|
||||||
|
if (client != null)
|
||||||
|
client.shutdown();
|
||||||
|
}
|
||||||
|
executorService.shutdown();
|
||||||
|
try {
|
||||||
|
if (!executorService.awaitTermination(60, TimeUnit.SECONDS)) {
|
||||||
|
executorService.shutdownNow();
|
||||||
|
if (!executorService.awaitTermination(60, TimeUnit.SECONDS))
|
||||||
|
System.err.println("Pool did not terminate");
|
||||||
|
}
|
||||||
|
} catch (InterruptedException ie) {
|
||||||
|
executorService.shutdownNow();
|
||||||
|
Thread.currentThread().interrupt();
|
||||||
|
}
|
||||||
|
this.interrupt();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -75,7 +75,8 @@ public class MailboxServer implements IMailboxServer, Runnable {
|
|||||||
}
|
}
|
||||||
this.dmtpListener = new DMTPListener(this.dmtpServerSocket, this.messageStorage);
|
this.dmtpListener = new DMTPListener(this.dmtpServerSocket, this.messageStorage);
|
||||||
this.dmtpListener.start();
|
this.dmtpListener.start();
|
||||||
// TODO spawn listener for user clients (DMAPListener)
|
this.dmapListener = new DMAPListener(this.dmapServerSocket, this.messageStorage, this.userStorage);
|
||||||
|
this.dmapListener.start();
|
||||||
this.shell.run();
|
this.shell.run();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -95,6 +96,7 @@ public class MailboxServer implements IMailboxServer, Runnable {
|
|||||||
try {
|
try {
|
||||||
if (dmapServerSocket != null)
|
if (dmapServerSocket != null)
|
||||||
dmapServerSocket.close();
|
dmapServerSocket.close();
|
||||||
|
this.dmapListener.interrupt();
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
logger.severe("Error closing DMTP serverSocket " + dmapServerSocket.toString());
|
logger.severe("Error closing DMTP serverSocket " + dmapServerSocket.toString());
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user