package krasa.grepconsole.tail.remotecall.notifier;
import com.google.common.io.Closeables;
import com.intellij.openapi.diagnostic.Logger;
import krasa.grepconsole.tail.remotecall.handler.MessageHandler;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.*;
import static java.net.URLDecoder.decode;
public class SocketMessageNotifier implements MessageNotifier {
private static final Logger log = Logger.getInstance(SocketMessageNotifier.class);
private static final String CRLF = "\r\n";
private static final String NL = "\n";
private final Collection<MessageHandler> messageHandlers = new HashSet<>();
private final ServerSocket serverSocket;
public SocketMessageNotifier(ServerSocket serverSocket) {
this.serverSocket = serverSocket;
}
private static Map<String, String> getParametersFromUrl(String url) {
String parametersString = url.substring(url.indexOf('?') + 1);
Map<String, String> parameters = new HashMap<>();
StringTokenizer tokenizer = new StringTokenizer(parametersString, "&");
while (tokenizer.hasMoreElements()) {
String[] parametersPair = tokenizer.nextToken().split("=", 2);
if (parametersPair.length > 1) {
parameters.put(parametersPair[0], parametersPair[1]);
}
}
return parameters;
}
@Override
public void addMessageHandler(MessageHandler handler) {
messageHandlers.add(handler);
}
@Override
public void run() {
while (true) {
Socket clientSocket;
try {
// noinspection SocketOpenedButNotSafelyClosed
clientSocket = serverSocket.accept();
} catch (IOException e) {
if (serverSocket.isClosed()) {
break;
} else {
log.error("Error while accepting", e);
continue;
}
}
InputStream inputStream = null;
try {
inputStream = clientSocket.getInputStream();
} catch (IOException e) {
log.error(e);
}
if (inputStream != null) {
BufferedReader in = new BufferedReader(new InputStreamReader(inputStream));
try {
String inputLine, requestString = "";
while ((inputLine = in.readLine()) != null && !inputLine.equals(CRLF) && !inputLine.equals(NL)
&& !inputLine.isEmpty()) {
requestString += inputLine;
}
clientSocket.getOutputStream().write(("HTTP/1.1 200 OK" + CRLF + CRLF).getBytes());
clientSocket.close();
StringTokenizer tokenizer = new StringTokenizer(requestString);
String method = tokenizer.hasMoreElements() ? tokenizer.nextToken() : "";
if (!method.equals("GET")) {
log.warn("Only GET requests allowed");
continue;
}
log.info("Received request " + requestString);
Map<String, String> parameters = getParametersFromUrl(tokenizer.nextToken());
String message = parameters.get("message") != null ? decode(parameters.get("message").trim(),
"UTF-8") : "";
log.info("Received message " + message);
handleMessage(message);
} catch (IOException e) {
log.error("Error", e);
} finally {
// noinspection deprecation
Closeables.closeQuietly(in);
}
}
}
}
private void handleMessage(String message) {
for (MessageHandler handler : messageHandlers) {
handler.handleMessage(message);
}
}
}