diff --git a/jabsrv/src/main/java/module-info.java b/jabsrv/src/main/java/module-info.java index 5f9b180b771..8e6b31ba958 100644 --- a/jabsrv/src/main/java/module-info.java +++ b/jabsrv/src/main/java/module-info.java @@ -5,12 +5,13 @@ exports org.jabref.http.dto to com.google.gson, org.glassfish.hk2.locator; exports org.jabref.http.dto.cayw to com.google.gson; - opens org.jabref.http.server to org.glassfish.hk2.utilities, org.glassfish.hk2.locator; + opens org.jabref.http.dto to com.google.gson; + opens org.jabref.http.server to com.google.gson, org.glassfish.hk2.utilities, org.glassfish.hk2.locator; + opens org.jabref.http.server.cayw to com.google.gson, org.glassfish.hk2.locator, org.glassfish.hk2.utilities; exports org.jabref.http.server.cayw to jersey.server; + opens org.jabref.http.server.command to , com.fasterxml.jackson.databind, com.google.gson, org.glassfish.hk2.locator, org.glassfish.hk2.utilities; exports org.jabref.http.server.command to jersey.server; - opens org.jabref.http.server.cayw to com.google.gson, org.glassfish.hk2.locator, org.glassfish.hk2.utilities; - opens org.jabref.http.dto to com.google.gson; - opens org.jabref.http.server.command to com.google.gson, org.glassfish.hk2.locator, org.glassfish.hk2.utilities, com.fasterxml.jackson.databind; + exports org.jabref.http.server.services; exports org.jabref.http; diff --git a/jabsrv/src/main/java/org/jabref/http/dto/AddEntryDTO.java b/jabsrv/src/main/java/org/jabref/http/dto/AddEntryDTO.java new file mode 100644 index 00000000000..15d85e5130b --- /dev/null +++ b/jabsrv/src/main/java/org/jabref/http/dto/AddEntryDTO.java @@ -0,0 +1,19 @@ +package org.jabref.http.dto; + +public class AddEntryDTO { + private String text; + + public AddEntryDTO() {} + + public AddEntryDTO(String text) { + this.text = text; + } + + public String getText() { + return text; + } + + public void setText(String text) { + this.text = text; + } +} diff --git a/jabsrv/src/main/java/org/jabref/http/server/LatestLibraryResource.java b/jabsrv/src/main/java/org/jabref/http/server/LatestLibraryResource.java new file mode 100644 index 00000000000..a5c61b431a1 --- /dev/null +++ b/jabsrv/src/main/java/org/jabref/http/server/LatestLibraryResource.java @@ -0,0 +1,123 @@ +package org.jabref.http.server; + +import java.util.Optional; + +import org.jabref.http.SrvStateManager; +import org.jabref.http.dto.AddEntryDTO; +import org.jabref.http.dto.BibEntryDTO; +import org.jabref.http.server.services.FilesToServe; +import org.jabref.logic.importer.ParseException; +import org.jabref.logic.importer.fileformat.BibtexParser; +import org.jabref.logic.preferences.CliPreferences; +import org.jabref.model.database.BibDatabaseContext; +import org.jabref.model.entry.BibEntry; +import org.jabref.model.entry.BibEntryTypesManager; +import org.jabref.model.entry.event.EntriesEventSource; + +import com.airhacks.afterburner.injection.Injector; +import com.google.gson.Gson; +import com.google.gson.JsonSyntaxException; +import jakarta.inject.Inject; +import jakarta.ws.rs.POST; +import jakarta.ws.rs.Path; +import jakarta.ws.rs.core.MediaType; +import jakarta.ws.rs.core.Response; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +@Path("libraries/latest") +public class LatestLibraryResource { + + private static final Logger LOGGER = LoggerFactory.getLogger(LatestLibraryResource.class); + + @Inject + private SrvStateManager srvStateManager; + + @Inject + private FilesToServe filesToServe; + + @Inject + private CliPreferences preferences; + + @Inject + private Gson gson; + + @POST + @Path("entries") + public Response addEntry(String jsonInput) { + // Manual JSON parsing with gson.fromJson + AddEntryDTO request; + try { + if (jsonInput == null || jsonInput.trim().isEmpty()) { + return Response.status(Response.Status.BAD_REQUEST) + .entity(gson.toJson(new ErrorResponse("Missing JSON input"))) + .type(MediaType.APPLICATION_JSON) + .build(); + } + + request = gson.fromJson(jsonInput, AddEntryDTO.class); + } catch (JsonSyntaxException e) { + return Response.status(Response.Status.BAD_REQUEST) + .entity(gson.toJson(new ErrorResponse("Invalid JSON format: " + e.getMessage()))) + .type(MediaType.APPLICATION_JSON) + .build(); + } + + if (request == null || request.getText() == null || request.getText().trim().isEmpty()) { + return Response.status(Response.Status.BAD_REQUEST) + .entity(gson.toJson(new ErrorResponse("Missing or empty 'text' field"))) + .type(MediaType.APPLICATION_JSON) + .build(); + } + + Optional activeDb = srvStateManager.getActiveDatabase(); + if (activeDb.isEmpty()) { + return Response.status(Response.Status.BAD_REQUEST) + .entity(gson.toJson(new ErrorResponse("No active library. Please open a library first."))) + .type(MediaType.APPLICATION_JSON) + .build(); + } + + String bibtexSource = request.getText(); + + BibtexParser parser = new BibtexParser(preferences.getImportFormatPreferences()); + + try { + Optional entry = parser.parseSingleEntry(bibtexSource); + if (entry.isEmpty()) { + return Response.status(Response.Status.BAD_REQUEST) + .entity(gson.toJson(new ErrorResponse("No valid BibTeX entry found"))) + .type(MediaType.APPLICATION_JSON) + .build(); + } + + activeDb.get().getDatabase().insertEntry(entry.get(), EntriesEventSource.SHARED); + + BibEntryTypesManager entryTypesManager = Injector.instantiateModelOrService(BibEntryTypesManager.class); + BibEntryDTO dto = new BibEntryDTO(entry.get(), activeDb.get().getMode(), preferences.getFieldPreferences(), entryTypesManager); + + // Manual JSON serialization with gson.toJson + return Response.ok(gson.toJson(dto)) + .type(MediaType.APPLICATION_JSON) + .build(); + } catch (ParseException e) { + return Response.status(Response.Status.BAD_REQUEST) + .entity(gson.toJson(new ErrorResponse("Error parsing BibTeX entry: " + e.getMessage()))) + .type(MediaType.APPLICATION_JSON) + .build(); + } + } + + // Helper class for error responses + private static class ErrorResponse { + private final String error; + + public ErrorResponse(String error) { + this.error = error; + } + + public String getError() { + return error; + } + } +} diff --git a/jabsrv/src/main/java/org/jabref/http/server/Server.java b/jabsrv/src/main/java/org/jabref/http/server/Server.java index 72a79fd707a..df52b503f9d 100644 --- a/jabsrv/src/main/java/org/jabref/http/server/Server.java +++ b/jabsrv/src/main/java/org/jabref/http/server/Server.java @@ -99,6 +99,7 @@ private HttpServer startServer(ServiceLocator serviceLocator, URI uri) { resourceConfig.register(CommandResource.class); resourceConfig.register(CORSFilter.class); resourceConfig.register(GlobalExceptionMapper.class); + resourceConfig.register(LatestLibraryResource.class); LOGGER.debug("Starting HTTP server..."); final HttpServer httpServer =