Skip to content

Commit a75a2ed

Browse files
committed
Refactor execMultipleCommands method to accept parameters directly and improve error handling for command execution. Updated JSON response structure for better clarity on command results.
1 parent 9c4d0c2 commit a75a2ed

File tree

1 file changed

+69
-83
lines changed

1 file changed

+69
-83
lines changed

src/main/java/com/shweit/serverapi/endpoints/v1/ServerAPI.java

Lines changed: 69 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
import org.bukkit.plugin.Plugin;
1313
import org.bukkit.scheduler.BukkitRunnable;
1414
import org.bukkit.scheduler.BukkitTask;
15-
import org.json.JSONArray; // Add this import
15+
import org.json.JSONArray;
1616
import org.json.JSONObject;
1717

1818
import java.io.File;
@@ -25,7 +25,7 @@
2525
import java.nio.file.FileSystems;
2626
import java.nio.file.Files;
2727
import java.util.Base64;
28-
import java.util.HashMap; // For session.parseBody()
28+
import java.util.HashMap;
2929
import java.util.Map;
3030
import java.util.Properties;
3131
import java.util.concurrent.atomic.AtomicBoolean;
@@ -251,102 +251,88 @@ public NanoHTTPD.Response execCommand(final Map<String, String> params) {
251251
return NanoHTTPD.newFixedLengthResponse(NanoHTTPD.Response.Status.OK, "application/json", jsonResponse.toString());
252252
}
253253

254-
public NanoHTTPD.Response execMultipleCommands(final NanoHTTPD.IHTTPSession session) {
255-
Map<String, String> files = new HashMap<>();
256-
try {
257-
session.parseBody(files);
258-
} catch (IOException | NanoHTTPD.ResponseException e) {
259-
Logger.error("Error parsing request body: " + e.getMessage());
260-
return NanoHTTPD.newFixedLengthResponse(NanoHTTPD.Response.Status.INTERNAL_ERROR, "application/json", "{\"error\":\"Error parsing request body\"}");
261-
}
262-
263-
String postBody = files.get("postData");
264-
if (postBody == null) {
265-
return NanoHTTPD.newFixedLengthResponse(NanoHTTPD.Response.Status.BAD_REQUEST, "application/json", "{\"error\":\"Missing request body\"}");
266-
}
267-
268-
JSONObject requestJson;
269-
try {
270-
requestJson = new JSONObject(postBody);
271-
} catch (Exception e) {
272-
Logger.error("Error parsing JSON request body: " + e.getMessage());
273-
return NanoHTTPD.newFixedLengthResponse(NanoHTTPD.Response.Status.BAD_REQUEST, "application/json", "{\"error\":\"Invalid JSON format\"}");
274-
}
275-
276-
if (!requestJson.has("commands")) {
277-
return NanoHTTPD.newFixedLengthResponse(NanoHTTPD.Response.Status.BAD_REQUEST, "application/json", "{\"error\":\"Missing 'commands' field in JSON payload\"}");
278-
}
254+
public NanoHTTPD.Response execMultipleCommands(final Map<String, String> params) {
255+
String commandsParam = params.get("commands");
256+
if (commandsParam == null) {
257+
return NanoHTTPD.newFixedLengthResponse(
258+
NanoHTTPD.Response.Status.BAD_REQUEST,
259+
"application/json",
260+
"{\"error\":\"Missing 'commands' parameter\"}"
261+
);
262+
}
279263

280-
JSONArray commandsJsonArray;
281-
try {
282-
commandsJsonArray = requestJson.getJSONArray("commands");
283-
} catch (Exception e) {
284-
Logger.error("Error parsing 'commands' array: " + e.getMessage());
285-
return NanoHTTPD.newFixedLengthResponse(NanoHTTPD.Response.Status.BAD_REQUEST, "application/json", "{\"error\":\"'commands' field must be a JSON array\"}");
286-
}
264+
JSONArray commandsJsonArray;
265+
try {
266+
commandsJsonArray = new JSONArray(commandsParam);
267+
} catch (Exception e) {
268+
Logger.error("Error parsing 'commands' array: " + e.getMessage());
269+
return NanoHTTPD.newFixedLengthResponse(
270+
NanoHTTPD.Response.Status.BAD_REQUEST,
271+
"application/json",
272+
"{\"error\":\"'commands' parameter must be a valid JSON array\"}"
273+
);
274+
}
287275

288-
JSONArray resultsArray = new JSONArray();
276+
JSONArray resultsArray = new JSONArray();
277+
278+
for (int i = 0; i < commandsJsonArray.length(); i++) {
279+
String command = commandsJsonArray.optString(i);
280+
if (command == null || command.trim().isEmpty()) {
281+
JSONObject result = new JSONObject();
282+
result.put("command", JSONObject.NULL);
283+
result.put("success", false);
284+
result.put("output", "Empty command string provided.");
285+
resultsArray.put(result);
286+
continue;
287+
}
289288

290-
for (int i = 0; i < commandsJsonArray.length(); i++) {
291-
String command = commandsJsonArray.optString(i);
292-
if (command == null || command.trim().isEmpty()) {
289+
AtomicBoolean success = new AtomicBoolean(false);
290+
CommandOutputCapture outputCapture = new CommandOutputCapture();
293291
JSONObject result = new JSONObject();
294-
result.put("command", JSONObject.NULL);
295-
result.put("success", false);
296-
result.put("output", "Empty command string provided.");
297-
resultsArray.put(result);
298-
continue;
299-
}
292+
result.put("command", command);
300293

301-
AtomicBoolean success = new AtomicBoolean(false);
302-
CommandOutputCapture outputCapture = new CommandOutputCapture();
303-
JSONObject result = new JSONObject();
304-
result.put("command", command);
305-
306-
try {
307-
BukkitTask task = Bukkit.getScheduler().runTask(MinecraftServerAPI.getInstance(), () -> {
308-
success.set(Bukkit.getServer().dispatchCommand(outputCapture, command));
309-
});
310-
311-
// Wait for the command to complete
312-
while (!task.isCancelled() && (Bukkit.getScheduler().isCurrentlyRunning(task.getTaskId()) || Bukkit.getScheduler().isQueued(task.getTaskId()))) {
313-
try {
314-
Thread.sleep(50); // Check every 50ms
315-
} catch (InterruptedException e) {
316-
Thread.currentThread().interrupt();
294+
try {
295+
BukkitTask task = Bukkit.getScheduler().runTask(MinecraftServerAPI.getInstance(), () -> {
296+
success.set(Bukkit.getServer().dispatchCommand(outputCapture, command));
297+
});
298+
299+
while (!task.isCancelled() && (Bukkit.getScheduler().isCurrentlyRunning(task.getTaskId()) || Bukkit.getScheduler().isQueued(task.getTaskId()))) {
300+
try {
301+
Thread.sleep(50);
302+
} catch (InterruptedException e) {
303+
Thread.currentThread().interrupt();
304+
Logger.error("Command execution interrupted: " + command);
305+
result.put("success", false);
306+
result.put("output", "Command execution was interrupted.");
307+
break;
308+
}
309+
}
310+
311+
if (Thread.currentThread().isInterrupted()){
317312
Logger.error("Command execution interrupted: " + command);
318313
result.put("success", false);
319314
result.put("output", "Command execution was interrupted.");
320-
break;
321315
}
322-
}
323-
if (Thread.currentThread().isInterrupted()){
324-
// If the thread was interrupted outside the sleep.
325-
Logger.error("Command execution interrupted: " + command);
326-
result.put("success", false);
327-
result.put("output", "Command execution was interrupted.");
328-
}
329316

317+
} catch (Exception e) {
318+
Logger.error("Error executing command '" + command + "': " + e.getMessage());
319+
result.put("success", false);
320+
result.put("output", "Error executing command: " + e.getMessage());
321+
}
330322

331-
} catch (Exception e) {
332-
Logger.error("Error executing command '" + command + "': " + e.getMessage());
333-
result.put("success", false);
334-
result.put("output", "Error executing command: " + e.getMessage());
323+
if (!result.has("success")) {
324+
result.put("success", success.get());
325+
result.put("output", outputCapture.getOutputMessages());
326+
}
327+
resultsArray.put(result);
335328
}
336329

337-
// Ensure result is populated even if interruption occurred before outputCapture could be populated.
338-
if (!result.has("success")) { // if not already set by interruption logic
339-
result.put("success", success.get());
340-
result.put("output", outputCapture.getOutputMessages());
341-
}
342-
resultsArray.put(result);
343-
}
330+
JSONObject responseJson = new JSONObject();
331+
responseJson.put("results", resultsArray);
344332

345-
JSONObject responseJson = new JSONObject();
346-
responseJson.put("results", resultsArray);
333+
return NanoHTTPD.newFixedLengthResponse(NanoHTTPD.Response.Status.OK, "application/json", responseJson.toString());
334+
}
347335

348-
return NanoHTTPD.newFixedLengthResponse(NanoHTTPD.Response.Status.OK, "application/json", responseJson.toString());
349-
}
350336

351337
public NanoHTTPD.Response reload(final Map<String, String> ignoredParams) {
352338
NanoHTTPD.Response response = NanoHTTPD.newFixedLengthResponse(NanoHTTPD.Response.Status.OK, "application/json", "{}");

0 commit comments

Comments
 (0)