private void loadHistory() { StringBuilder jsonArrayString = new StringBuilder(); try (BufferedReader reader = new BufferedReader(new FileReader(DEFAULT_PERSISTENCE_FILE))) { while (reader.ready()) { jsonArrayString.append(reader.readLine()); } } catch (IOException e) { logger.error("Could not parse message.", e); } JSONArray jsonArray = new JSONArray(); if (jsonArrayString.length() == 0) { return; } try { jsonArray = (JSONArray) MessageHelper.getJsonParser().parse(jsonArrayString.toString()); } catch (ParseException e) { logger.error("Could not parse message.", e); } for (int i = 0; i < jsonArray.size(); i++) { JSONObject jsonObject = (JSONObject) jsonArray.get(i); Message message = MessageHelper.jsonObjectToMessage(jsonObject); messages.add(message); } }
// +++++++ private Response doPost(HttpExchange httpExchange) { try { Message message = MessageHelper.getClientMessage(httpExchange.getRequestBody()); logger.info(String.format("Received new message from user: %s", message)); messageStorage.addMessage(message); return Response.ok(); } catch (ParseException e) { logger.error("Could not parse message.", e); return new Response(Constants.RESPONSE_CODE_BAD_REQUEST, "Incorrect request body"); } catch (MessageExistException e) { logger.error("Message with same id exist.", e); return new Response(Constants.RESPONSE_CODE_BAD_REQUEST, "Message with same id exist"); } }
public void connect() { URL url = null; try { url = new URL(Constants.PROTOCOL, host, port, Constants.CONTEXT_PATH); url.openConnection(); // try connect to server connected = true; startListening(); startMessageSending(); } catch (MalformedURLException e) { logger.error("Could not build URL to server", e); throw new RuntimeException(e); } catch (IOException e) { logger.error(String.format("Could not connect to server on %s", url.toString()), e); } }
private void startListening() { // if listener thread is alive and listening now, no need to recreate. Just reuse it. if (listenerThread != null && listenerThread.isAlive()) { return; } Runnable listeningAction = () -> { boolean running = true; while (connected && running) { List<String> list = getMessages(); localHistory.addAll(list); try { Thread.sleep(POLLING_PERIOD_MILLIS); } catch (InterruptedException e) { logger.error("The message listening thread was interrupted", e); running = false; } } }; listenerThread = new Thread(listeningAction); listenerThread.start(); }
private void checkConnected() { if (!connected) { RuntimeException notConnectedError = new RuntimeException("No connection to server"); logger.error("No connection to server", notConnectedError); throw notConnectedError; } }
public void sendMessage(String message) { checkConnected(); HttpURLConnection outcomeConnection = null; try { CLIENT_LOGGER.info("start sending message \"" + message + "\""); outcomeConnection = prepareOutputConnection(); byte[] buffer = MessageHelper.buildSendMessageRequestBody(message).getBytes(); OutputStream outputStream = outcomeConnection.getOutputStream(); outputStream.write(buffer, 0, buffer.length); outputStream.close(); outcomeConnection.getInputStream(); // to send data to server CLIENT_LOGGER.info("message sent"); } catch (ConnectException e) { logger.error("Connection error. Disconnecting...", e); CLIENT_LOGGER.error("connection error", e); disconnect(); } catch (IOException e) { CLIENT_LOGGER.error("IOException", e); logger.error("IOException occurred while sending message", e); } finally { if (outcomeConnection != null) { outcomeConnection.disconnect(); } CLIENT_LOGGER.info("stop sending message \"" + message + "\""); } }
private boolean rewriteHistory() { try (Writer writer = new OutputStreamWriter(new FileOutputStream(DEFAULT_PERSISTENCE_FILE), "UTF-8")) { JSONArray array = MessageHelper.getJsonArrayOfMessages(messages); writer.write(array.toString()); return true; } catch (IOException e) { logger.error("Could not parse message.", e); return false; } }
/** * Parses token and extract encoded amount of messages (typically - index) * * @param token the token to be parsed * @return decoded amount messages (index) */ public static int parseToken(String token) { if (!token.matches(TOKEN_FORMAT)) { throw new InvalidTokenException("Incorrect format of token"); } String encodedIndex = token.substring(2, token.length() - 2); try { int stateCode = Integer.valueOf(encodedIndex); return decodeIndex(stateCode); } catch (NumberFormatException e) { logger.error("Could not parse token", e); throw new InvalidTokenException("Invalid encoded value: " + encodedIndex); } }
public static String inputStreamToString(InputStream in) { byte[] buffer = new byte[1024]; int length = 0; try (ByteArrayOutputStream outStream = new ByteArrayOutputStream()) { while ((length = in.read(buffer)) != -1) { outStream.write(buffer, 0, length); } return outStream.toString(); } catch (IOException e) { logger.error("An error occurred while reading input stream", e); throw new RuntimeException(e); } }
// ++++++ private Response doPut(HttpExchange httpExchange) { try { JSONObject jsonObject = stringToJsonObject(inputStreamToString(httpExchange.getRequestBody())); Message message = new Message(); message.setId(((String) jsonObject.get(Constants.Message.FIELD_ID))); message.setText(((String) jsonObject.get(Constants.Message.FIELD_TEXT))); // System.out.println(((long)jsonObject.get(Constants.Message.FIELD_TIMESTAMP_MODIFIED))); message.setTimestampModified( ((long) jsonObject.get(Constants.Message.FIELD_TIMESTAMP_MODIFIED))); logger.info(String.format("Received updated message from user: %s", message)); if (messageStorage.updateMessage(message)) { return Response.ok(); } return Response.badRequest("This message does not exist"); } catch (ParseException e) { logger.error("Could not parse message.", e); return new Response(Constants.RESPONSE_CODE_BAD_REQUEST, "Incorrect request body"); } }
@Override public void handle(HttpExchange httpExchange) throws IOException { Response response; try { response = dispatch(httpExchange); } catch (Throwable e) { // WARNING! It's not a good practice to catch all exceptions via Throwable // or Exception classes. But if you want to handle and you know // how to handle them correctly, you may use such approach. // Useful when you use thread pool and don't want to corrupt a thread logger.error("An error occurred when dispatching request.", e); response = new Response( Constants.RESPONSE_CODE_INTERNAL_SERVER_ERROR, "Error while dispatching message"); } sendResponse(httpExchange, response); }
private void sendResponse(HttpExchange httpExchange, Response response) { try (OutputStream os = httpExchange.getResponseBody()) { byte[] bytes = response.getBody().getBytes(); Headers headers = httpExchange.getResponseHeaders(); headers.add(Constants.REQUEST_HEADER_ACCESS_CONTROL_ORIGIN, "*"); httpExchange.sendResponseHeaders(response.getStatusCode(), bytes.length); os.write(bytes); // there is no need to close stream manually // as try-catch with auto-closable is used /** * {@see http://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html} */ } catch (IOException e) { logger.error("Could not send response", e); } }
public List<String> getMessages() { CLIENT_LOGGER.info("start receiving messages"); checkConnected(); List<String> list = new ArrayList<>(); HttpURLConnection incomeConnection = null; try { CLIENT_LOGGER.info("send request for receive messages"); String query = String.format( "%s?%s=%s", Constants.CONTEXT_PATH, Constants.REQUEST_PARAM_TOKEN, MessageHelper.buildToken(localHistory.size())); URL url = new URL(Constants.PROTOCOL, host, port, query); incomeConnection = prepareInputConnection(url); CLIENT_LOGGER.info("response is received"); String response = MessageHelper.inputStreamToString(incomeConnection.getInputStream()); JSONObject jsonObject = MessageHelper.stringToJsonObject(response); JSONArray jsonArray = (JSONArray) jsonObject.get("messages"); CLIENT_LOGGER.info("received " + jsonArray.size() + " messages"); for (Object o : jsonArray) { logger.info(String.format("Message from server: %s", o)); CLIENT_LOGGER.info("message from server: " + o); list.add(o.toString()); } /** Here is an example how for cycle can be replaced with Java 8 Stream API */ // jsonArray.forEach(System.out::println); // list = (List<String>) // jsonArray.stream().map(Object::toString).collect(Collectors.toList()); } catch (ParseException e) { logger.error("Could not parse message", e); CLIENT_LOGGER.error("could not parse message", e); } catch (ConnectException e) { logger.error("Connection error. Disconnecting...", e); CLIENT_LOGGER.error("connection error", e); disconnect(); } catch (IOException e) { logger.error("IOException occured while reading input message", e); CLIENT_LOGGER.error("IOException occured while reading input message", e); } finally { if (incomeConnection != null) { incomeConnection.disconnect(); } } CLIENT_LOGGER.info("stop receiving messages"); return list; }