Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions java-kanban.iml
Original file line number Diff line number Diff line change
Expand Up @@ -24,5 +24,14 @@
<SOURCES />
</library>
</orderEntry>
<orderEntry type="module-library">
<library>
<CLASSES>
<root url="jar://$MODULE_DIR$/lib/gson-2.9.0.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</orderEntry>
</component>
</module>
96 changes: 96 additions & 0 deletions src/BaseHttpHandler.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
import com.google.gson.Gson;
import com.sun.net.httpserver.HttpExchange;
import com.sun.net.httpserver.HttpHandler;

import java.io.IOException;
import java.nio.charset.StandardCharsets;

public abstract class BaseHttpHandler implements HttpHandler {
protected final TaskManager taskManager;
protected final Gson gson;

protected BaseHttpHandler(TaskManager taskManager, Gson gson) {
this.taskManager = taskManager;
this.gson = gson;
}

public static void sendText(HttpExchange h, String text) throws IOException {
send(h, text, 200);
}

public static void sendSuccessfullyModified(HttpExchange h, String text) throws IOException {
send(h, text, 201);
}

public static void sendNotFound(HttpExchange h, String text) throws IOException {
send(h, text, 404);
}

public static void sendHasInteractions(HttpExchange h, String text) throws IOException {
send(h, text, 406);
}

public static void sendIntervalServerError(HttpExchange h, String text) throws IOException {
send(h, text, 500);
}

public Endpoint getEndpoint(String[] pathParts, String requestMethod) {
if (pathParts[1].equals("tasks") || pathParts[1].equals("subtasks") || pathParts[1].equals("epics") ||
pathParts[1].equals("history") || pathParts[1].equals("prioritized")) {
switch (requestMethod) {
case "GET": {
if (pathParts.length == 2) {
return Endpoint.GET;
}
if (pathParts.length == 3 && isInteger(pathParts[2])) {
return Endpoint.GET_ID;
}
if (pathParts.length == 4 && pathParts[1].equals("epics") &&
isInteger(pathParts[2]) && pathParts[3].equals("subtasks")) {
return Endpoint.GET_ID_EPIC_SUBTASKS;
}
return Endpoint.UNKNOWN;
}
case "POST": {
if (pathParts.length == 2) {
return Endpoint.POST;
}
if (pathParts.length == 3 && isInteger(pathParts[2])) {
return Endpoint.POST_ID;
}
return Endpoint.UNKNOWN;
}
case "DELETE": {
if (pathParts.length == 2) {
return Endpoint.DELETE;
}
if (pathParts.length == 3 && isInteger(pathParts[2])) {
return Endpoint.DELETE_ID;
}
return Endpoint.UNKNOWN;
}
default:
return Endpoint.UNKNOWN;
}
}
return Endpoint.UNKNOWN;
}

private static void send(HttpExchange h, String text, int code) throws IOException {
byte[] resp = text.getBytes(StandardCharsets.UTF_8);
h.getResponseHeaders().add("Content-Type", "application/json;charset=utf-8");
h.sendResponseHeaders(code, resp.length);
h.getResponseBody().write(resp);
h.close();
}

private boolean isInteger(String s) {
try {
Integer.parseInt(s);
return true;
} catch (NumberFormatException e) {
return false;
}
}

}
25 changes: 25 additions & 0 deletions src/DurationAdapter.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import com.google.gson.TypeAdapter;
import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonWriter;

import java.io.IOException;
import java.time.Duration;

public class DurationAdapter extends TypeAdapter<Duration> {
@Override
public void write(JsonWriter jsonWriter, Duration duration) throws IOException {
if (duration == null) {
jsonWriter.nullValue();
} else {
jsonWriter.value(duration.toString());
}
}

@Override
public Duration read(JsonReader jsonReader) throws IOException {
if (jsonReader == null) {
return null;
}
return Duration.parse(jsonReader.nextString());
}
}
10 changes: 10 additions & 0 deletions src/Endpoint.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
public enum Endpoint {
GET,
GET_ID,
GET_ID_EPIC_SUBTASKS,
POST,
POST_ID,
DELETE,
DELETE_ID,
UNKNOWN
}
27 changes: 27 additions & 0 deletions src/ExceptionHandler.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import com.sun.net.httpserver.Filter;
import com.sun.net.httpserver.HttpExchange;

import java.io.IOException;

public class ExceptionHandler extends Filter {
@Override
public void doFilter(HttpExchange exchange, Chain chain) throws IOException {
try {
chain.doFilter(exchange);
} catch (NotFoundException e) {
BaseHttpHandler.sendNotFound(exchange, e.getMessage());
} catch (TaskOverlapsException e) {
BaseHttpHandler.sendHasInteractions(exchange, e.getMessage());
} catch (Exception e) {
String message = "Внутренняя ошибка сервера: " + e.getClass().getSimpleName();
BaseHttpHandler.sendIntervalServerError(exchange, message);
e.printStackTrace();
}
}

@Override
public String description() {
return "Обработчик исключений";
}

}
53 changes: 53 additions & 0 deletions src/HttpEpicsController.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import com.google.gson.Gson;
import com.sun.net.httpserver.HttpExchange;

import java.io.IOException;
import java.nio.charset.StandardCharsets;

public class HttpEpicsController extends BaseHttpHandler {

public HttpEpicsController(TaskManager taskManager, Gson gson) {
super(taskManager, gson);
}

@Override
public void handle(HttpExchange exchange) throws IOException {
String[] pathParts = exchange.getRequestURI().getPath().split("/");
String requestMethod = exchange.getRequestMethod();

Endpoint endpoint = getEndpoint(pathParts, requestMethod);
switch (endpoint) {
case GET:
sendText(exchange, gson.toJson(taskManager.getAllEpics()));
case GET_ID:
sendText(exchange, gson.toJson(taskManager.getEpicByID(Integer.parseInt(pathParts[2]))));
case GET_ID_EPIC_SUBTASKS:
sendText(exchange, gson.toJson(taskManager.getSubtaskListByEpicId(Integer.parseInt(pathParts[2]))));
case POST: {
String body = new String(exchange.getRequestBody().readAllBytes(), StandardCharsets.UTF_8);
taskManager.addEpic(gson.fromJson(body, Epic.class));
sendSuccessfullyModified(exchange, "Эпик успешно добавлен");
break;
}
case POST_ID: {
String body = new String(exchange.getRequestBody().readAllBytes(), StandardCharsets.UTF_8);
taskManager.updateEpicByID(gson.fromJson(body, Epic.class));
sendSuccessfullyModified(exchange, "Эпик успешно обнолен");
break;
}
case DELETE: {
taskManager.deleteAllEpic();
sendText(exchange, "Все эпики удалены");
break;
}
case DELETE_ID: {
taskManager.deleteEpicByID(Integer.parseInt(pathParts[2]));
sendText(exchange, "Эпик с идентификатором " + Integer.parseInt(pathParts[2]) + " удален");
break;
}
default:
throw new RuntimeException("Эндпоинт не найден: " + requestMethod + " " + exchange.getRequestURI().getPath());
}
}

}
26 changes: 26 additions & 0 deletions src/HttpHistoryController.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import com.google.gson.Gson;
import com.sun.net.httpserver.HttpExchange;

import java.io.IOException;

public class HttpHistoryController extends BaseHttpHandler {

public HttpHistoryController(TaskManager taskManager, Gson gson) {
super(taskManager, gson);
}

@Override
public void handle(HttpExchange exchange) throws IOException {
String[] pathParts = exchange.getRequestURI().getPath().split("/");
String requestMethod = exchange.getRequestMethod();

Endpoint endpoint = getEndpoint(pathParts, requestMethod);
switch (endpoint) {
case GET:
sendText(exchange, gson.toJson(taskManager.getHistory()));
default:
throw new RuntimeException("Эндпоинт не найден: " + requestMethod + " " + exchange.getRequestURI().getPath());
}
}

}
26 changes: 26 additions & 0 deletions src/HttpPrioritizedController.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import com.google.gson.Gson;
import com.sun.net.httpserver.HttpExchange;

import java.io.IOException;

public class HttpPrioritizedController extends BaseHttpHandler {

public HttpPrioritizedController(TaskManager taskManager, Gson gson) {
super(taskManager, gson);
}

@Override
public void handle(HttpExchange exchange) throws IOException {
String[] pathParts = exchange.getRequestURI().getPath().split("/");
String requestMethod = exchange.getRequestMethod();

Endpoint endpoint = getEndpoint(pathParts, requestMethod);
switch (endpoint) {
case GET:
sendText(exchange, gson.toJson(taskManager.getPrioritizedTasks()));
default:
throw new RuntimeException("Эндпоинт не найден: " + requestMethod + " " + exchange.getRequestURI().getPath());
}
}

}
52 changes: 52 additions & 0 deletions src/HttpSubtasksController.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import com.google.gson.Gson;
import com.sun.net.httpserver.HttpExchange;

import java.io.IOException;
import java.nio.charset.StandardCharsets;

public class HttpSubtasksController extends BaseHttpHandler {

public HttpSubtasksController(TaskManager taskManager, Gson gson) {
super(taskManager, gson);
}

@Override
public void handle(HttpExchange exchange) throws IOException {
String[] pathParts = exchange.getRequestURI().getPath().split("/");
String requestMethod = exchange.getRequestMethod();

Endpoint endpoint = getEndpoint(pathParts, requestMethod);
switch (endpoint) {
case GET:
sendText(exchange, gson.toJson(taskManager.getAllSubtasks()));
case GET_ID:
sendText(exchange, gson.toJson(taskManager.getSubtaskByID(Integer.parseInt(pathParts[2]))));
case POST: {
String body = new String(exchange.getRequestBody().readAllBytes(), StandardCharsets.UTF_8);
Subtask subtask = gson.fromJson(body, Subtask.class);
taskManager.addSubtask(subtask.getEpicId(), subtask);
sendSuccessfullyModified(exchange, "Подзадача успешно добавлена");
break;
}
case POST_ID: {
String body = new String(exchange.getRequestBody().readAllBytes(), StandardCharsets.UTF_8);
taskManager.updateSubtaskByID(gson.fromJson(body, Subtask.class));
sendSuccessfullyModified(exchange, "Подзадача успешно обнолена");
break;
}
case DELETE: {
taskManager.deleteAllSubtasks();
sendText(exchange, "Все подзадачи удалены");
break;
}
case DELETE_ID: {
taskManager.deleteSubtaskByID(Integer.parseInt(pathParts[2]));
sendText(exchange, "Подзадача с идентификатором " + Integer.parseInt(pathParts[2]) + " удалена");
break;
}
default:
throw new RuntimeException("Эндпоинт не найден: " + requestMethod + " " + exchange.getRequestURI().getPath());
}
}

}
52 changes: 52 additions & 0 deletions src/HttpTaskServer.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import java.io.IOException;

import com.sun.net.httpserver.Filter;
import com.sun.net.httpserver.HttpServer;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;

import java.net.InetSocketAddress;
import java.time.Duration;
import java.time.LocalDateTime;

public class HttpTaskServer {

private final HttpServer httpServer;
private final TaskManager taskManager;
private final Gson gson;

public HttpTaskServer(TaskManager taskManager) throws IOException {
this.httpServer = HttpServer.create(new InetSocketAddress(8080), 0);
this.taskManager = taskManager;
this.gson = new GsonBuilder()
.registerTypeAdapter(LocalDateTime.class, new LocalDateTimeAdapter())
.registerTypeAdapter(Duration.class, new DurationAdapter())
.create();
}

public static void main(String[] args) throws IOException {
HttpTaskServer httpTaskServer = new HttpTaskServer(Managers.getDefault());
httpTaskServer.start();
}

public void start() {

Filter filter = new ExceptionHandler();
httpServer.createContext("/tasks", new HttpTasksController(taskManager, gson)).getFilters().add(filter);
httpServer.createContext("/subtasks", new HttpSubtasksController(taskManager, gson)).getFilters().add(filter);
httpServer.createContext("/epics", new HttpEpicsController(taskManager, gson)).getFilters().add(filter);
httpServer.createContext("/history", new HttpHistoryController(taskManager, gson)).getFilters().add(filter);
httpServer.createContext("/prioritized", new HttpPrioritizedController(taskManager, gson)).getFilters().add(filter);

httpServer.start();
}

public void stop() {
httpServer.stop(0);
}

public Gson getGson() {
return gson;
}

}
Loading