Skip to content
Merged
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
19 changes: 19 additions & 0 deletions java-kanban.iml
Original file line number Diff line number Diff line change
Expand Up @@ -56,5 +56,24 @@
<SOURCES />
</library>
</orderEntry>
<orderEntry type="module-library">
<library>
<CLASSES>
<root url="jar://$MODULE_DIR$/../../dev/m1-t25-api/lib/gson-2.9.0.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</orderEntry>
<orderEntry type="module-library">
<library name="JUnit4">
<CLASSES>
<root url="jar://$MAVEN_REPOSITORY$/junit/junit/4.13.1/junit-4.13.1.jar!/" />
<root url="jar://$MAVEN_REPOSITORY$/org/hamcrest/hamcrest-core/1.3/hamcrest-core-1.3.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</orderEntry>
</component>
</module>
2 changes: 1 addition & 1 deletion src/managers/InMemoryTaskManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -233,4 +233,4 @@ public List<Task> getHistory() {
public List<Task> getPrioritizedTasks() {
return new ArrayList<>(prioritizedTasks);
}
}
}
7 changes: 7 additions & 0 deletions src/managers/NotFoundException.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package managers;

public class NotFoundException extends RuntimeException {
public NotFoundException(String message) {
super(message);
}
}
38 changes: 38 additions & 0 deletions src/server/BaseHttpHandler.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package server;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.sun.net.httpserver.HttpExchange;
import com.sun.net.httpserver.HttpHandler;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.time.Duration;

public abstract class BaseHttpHandler implements HttpHandler {
protected final Gson gson = new GsonBuilder()
.registerTypeAdapter(Duration.class, new DurationAdapter())
.create();

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

protected void sendNotFound(HttpExchange exchange) throws IOException {
sendText(exchange, "Not Found", 404);
}

protected void sendHasInteractions(HttpExchange exchange) throws IOException {
sendText(exchange, "Задача пересекается с существующими", 406);
}

protected void sendInternalError(HttpExchange exchange) throws IOException {
sendText(exchange, "Internal Server Error", 500);
}

@Override
public abstract void handle(HttpExchange exchange) throws IOException;
}
20 changes: 20 additions & 0 deletions src/server/DurationAdapter.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package server;

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 out, Duration duration) throws IOException {
out.value(duration != null ? duration.toString() : null);
}

@Override
public Duration read(JsonReader in) throws IOException {
String value = in.nextString();
return value != null ? Duration.parse(value) : null;
}
}
113 changes: 113 additions & 0 deletions src/server/EpicsHandler.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
package server;

import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.sun.net.httpserver.HttpExchange;
import managers.NotFoundException;
import managers.TaskManager;
import tasks.Epic;
import tasks.Status;
import tasks.Subtask;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.List;

public class EpicsHandler extends BaseHttpHandler {
private final TaskManager taskManager;

public EpicsHandler(TaskManager taskManager) {
this.taskManager = taskManager;
}

@Override
public void handle(HttpExchange exchange) throws IOException {
try {
String method = exchange.getRequestMethod();
String path = exchange.getRequestURI().getPath();
switch (method) {
case "GET":
handleGet(exchange, path);
break;
case "POST":
handlePost(exchange);
break;
case "DELETE":
handleDelete(exchange, path);
break;
default:
sendNotFound(exchange);
}
} catch (Exception e) {
sendInternalError(exchange);
}
}

private void handleGet(HttpExchange exchange, String path) throws IOException {
if (path.matches("/epics/\\d+/subtasks")) {
try {
int id = Integer.parseInt(path.split("/")[2]);
List<Subtask> subtasks = taskManager.getEpicSubtasks(id);
sendText(exchange, gson.toJson(subtasks), 200);
} catch (NotFoundException e) {
sendNotFound(exchange);
}
} else if (path.equals("/epics")) {
List<Epic> epics = taskManager.getAllEpic();
sendText(exchange, gson.toJson(epics), 200);
} else if (path.matches("/epics/\\d+")) {
try {
int id = Integer.parseInt(path.split("/")[2]);
Epic epic = taskManager.getAllEpic().stream()
.filter(e -> e.getId() == id)
.findFirst()
.orElseThrow(() -> new NotFoundException("Эпик с ID " + id + " не найден"));
sendText(exchange, gson.toJson(epic), 200);
} catch (NotFoundException e) {
sendNotFound(exchange);
}
} else {
sendNotFound(exchange);
}
}

private void handlePost(HttpExchange exchange) throws IOException {
try {
String body = new String(exchange.getRequestBody().readAllBytes(), StandardCharsets.UTF_8);
JsonObject json = JsonParser.parseString(body).getAsJsonObject();

String name = json.get("name").getAsString();
String description = json.get("description").getAsString();
Status status = Status.valueOf(json.get("status").getAsString());

Epic epic = new Epic(name, description, status);

if (json.has("id") && json.get("id").getAsInt() != 0) {
epic.setId(json.get("id").getAsInt());
taskManager.updateEpic(epic);
sendText(exchange, "Эпик обновлён", 200);
} else {
taskManager.addEpic(epic);
sendText(exchange, "Эпик создан", 201);
}
} catch (NotFoundException e) {
sendNotFound(exchange);
}
}

private void handleDelete(HttpExchange exchange, String path) throws IOException {
if (path.matches("/epics/\\d+")) {
try {
int id = Integer.parseInt(path.split("/")[2]);
taskManager.removeEpicById(id);
sendText(exchange, "Эпик удалён", 200);
} catch (NumberFormatException | NotFoundException e) {
sendNotFound(exchange);
}
} else if (path.equals("/epics")) {
taskManager.removeAllEpics();
sendText(exchange, "Все эпики удалены", 200);
} else {
sendNotFound(exchange);
}
}
}
29 changes: 29 additions & 0 deletions src/server/HistoryHandler.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package server;

import com.sun.net.httpserver.HttpExchange;
import managers.TaskManager;
import tasks.Task;
import java.io.IOException;
import java.util.List;

public class HistoryHandler extends BaseHttpHandler {
private final TaskManager taskManager;

public HistoryHandler(TaskManager taskManager) {
this.taskManager = taskManager;
}

@Override
public void handle(HttpExchange exchange) throws IOException {
try {
if (!exchange.getRequestMethod().equals("GET")) {
sendNotFound(exchange);
return;
}
List<Task> history = taskManager.getHistory();
sendText(exchange, gson.toJson(history), 200);
} catch (Exception e) {
sendInternalError(exchange);
}
}
}
43 changes: 43 additions & 0 deletions src/server/HttpTaskServer.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package server;

import com.sun.net.httpserver.HttpServer;
import managers.Managers;
import managers.TaskManager;
import java.io.IOException;
import java.net.InetSocketAddress;

public class HttpTaskServer {
private static final int PORT = 8080;
private final HttpServer server;
private final TaskManager taskManager;

public HttpTaskServer(TaskManager taskManager) throws IOException {
this.taskManager = taskManager;
server = HttpServer.create(new InetSocketAddress(PORT), 0);
registerHandlers();
}

private void registerHandlers() {
server.createContext("/tasks", new TasksHandler(taskManager));
server.createContext("/subtasks", new SubtasksHandler(taskManager));
server.createContext("/epics", new EpicsHandler(taskManager));
server.createContext("/history", new HistoryHandler(taskManager));
server.createContext("/prioritized", new PrioritizedHandler(taskManager));
}

public void start() {
server.start();
System.out.println("HTTP-сервер запущен на порту " + PORT);
}

public void stop() {
server.stop(0);
System.out.println("HTTP-сервер остановлен");
}

public static void main(String[] args) throws IOException {
TaskManager manager = Managers.getDefault();
HttpTaskServer server = new HttpTaskServer(manager);
server.start();
}
}
31 changes: 31 additions & 0 deletions src/server/PrioritizedHandler.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package server;

import com.sun.net.httpserver.HttpExchange;
import managers.InMemoryTaskManager;
import managers.TaskManager;
import tasks.Task;
import java.io.IOException;
import java.util.List;

public class PrioritizedHandler extends BaseHttpHandler {
private final TaskManager taskManager;

public PrioritizedHandler(TaskManager taskManager) {
this.taskManager = taskManager;
}

@Override
public void handle(HttpExchange exchange) throws IOException {
if (!exchange.getRequestMethod().equals("GET")) {
sendNotFound(exchange);
return;
}

if (taskManager instanceof InMemoryTaskManager) {
List<Task> prioritizedTasks = ((InMemoryTaskManager) taskManager).getPrioritizedTasks();
sendText(exchange, gson.toJson(prioritizedTasks), 200);
} else {
sendInternalError(exchange);
}
}
}
Loading