package org.jetbrains.ruby.runtime.signature.server; import com.google.gson.Gson; import com.google.gson.JsonParseException; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.ruby.codeInsight.types.signature.*; import org.jetbrains.ruby.runtime.signature.RawSignature; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.net.ServerSocket; import java.net.Socket; import java.nio.file.Path; import java.nio.file.Paths; import java.util.List; import java.util.logging.Logger; public class SignatureServer { private static final Logger LOGGER = Logger.getLogger("SignatureServer"); RSignatureContractContainer mainContainer = new RSignatureContractContainer(); @Nullable private static SignatureServer ourInstance; @NotNull public static SignatureServer getInstance() { if (ourInstance == null) { ourInstance = new SignatureServer(); } return ourInstance; } @Nullable public RSignatureContract getContract(@NotNull MethodInfo info) { return mainContainer.getSignature(info); } @Nullable public RSignatureContract getContractByMethodName(@NotNull String methodName) { for (MethodInfo info : mainContainer.getKeySet()) { if (info.getName().equals(methodName)) { return mainContainer.getSignature(info); } } return null; } @Nullable public RSignatureContract getContractByMethodAndReceiverName(@NotNull String methodName, @NotNull String receiverName) { for (MethodInfo info : mainContainer.getKeySet()) { if (info.getName().equals(methodName) && info.getClassInfo().getClassFQN().equals(receiverName)) return mainContainer.getSignature(info); } return null; } @Nullable public RSignatureContract getContractByMethodInfo(@NotNull MethodInfo info) { return mainContainer.getSignature(info); } private static class SignatureHandler extends Thread { private Socket socket; private int handlerNumber; public SignatureHandler(Socket socket, int handlerNumber) { this.socket = socket; this.handlerNumber = handlerNumber; LOGGER.info("New connection with client# " + handlerNumber + " at " + socket); } public void run() { try { BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream())); String currString; while ((currString = br.readLine()) != null) { try { ServerResponseBean result = new Gson().fromJson(currString, ServerResponseBean.class); if (result != null) { RawSignature currRawSignature = new RawSignature(result); if (!result.call_info_mid.equals("")) { RSignatureFetcher fetcher = new RSignatureFetcher(currRawSignature.argc, currRawSignature.kwArgs); List<Boolean> flags = fetcher.fetch(currRawSignature.getArgsInfo()); for (int i = 0; i < flags.size(); i++) { Boolean flag = flags.get(i); if (!flag) currRawSignature.changeArgumentType(i, "-"); } } RSignature currRSignature = currRawSignature.getRSignature(); if (result.method_name.equals("initialize") || result.call_info_mid.equals("") || result.call_info_mid.equals(result.method_name)) { SignatureServer.getInstance().mainContainer.addSignature(currRSignature); } } } catch (JsonParseException e) { LOGGER.severe("!" + currString + "!\n" + e); e.printStackTrace(); } } } catch (IOException e) { LOGGER.severe("Error handling client# " + handlerNumber + ": " + e); } finally { try { socket.close(); } catch (IOException e) { LOGGER.severe("Can't close a socket"); } LOGGER.info("Connection with client# " + handlerNumber + " closed"); SignatureServer.getInstance().mainContainer.reduction(); } } } public void runServer() throws IOException { LOGGER.info("Starting server"); Path file = Paths.get("callStatLog.txt"); int handlersCounter = 0; ServerSocket listener = new ServerSocket(7777); try { while (true) { new SignatureHandler(listener.accept(), handlersCounter++).start(); } } finally { listener.close(); SignatureServer.getInstance().mainContainer.reduction(); } } public static void main(String[] args) throws IOException { getInstance().runServer(); } }