-
-
Notifications
You must be signed in to change notification settings - Fork 2.8k
refine-jabsrv #13044
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
refine-jabsrv #13044
Changes from all commits
fa9bb0d
39f9ff6
d1d4169
b2e0997
8260609
7ee2017
18450a4
9d53e7c
710b143
7ec9804
4639440
baf3538
da416d2
bbf8a7c
9d7479a
926f318
88874ef
f906f28
6a3e720
ba364d2
1d207c8
b5b4d8c
1cee088
c7266eb
d8198d0
68f2e91
bafa751
23df77a
548e0b5
2c7758c
b719a3a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
package org.jabref.http.dto; | ||
|
||
import jakarta.ws.rs.core.Response; | ||
import jakarta.ws.rs.ext.ExceptionMapper; | ||
import jakarta.ws.rs.ext.Provider; | ||
import org.slf4j.Logger; | ||
import org.slf4j.LoggerFactory; | ||
|
||
@Provider | ||
public class GlobalExceptionMapper implements ExceptionMapper<Throwable> { | ||
|
||
private static final Logger LOGGER = LoggerFactory.getLogger(GlobalExceptionMapper.class.getName()); | ||
|
||
@Override | ||
public Response toResponse(Throwable exception) { | ||
LOGGER.error("Unhandled exception on server", exception); | ||
return Response.serverError().entity("Internal Server Error").build(); | ||
} | ||
} |
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -7,6 +7,7 @@ | |
|
||
import org.jabref.http.JabrefMediaType; | ||
import org.jabref.http.dto.BibEntryDTO; | ||
import org.jabref.http.server.services.FilesToServe; | ||
import org.jabref.logic.citationstyle.JabRefItemDataProvider; | ||
import org.jabref.logic.importer.ParserResult; | ||
import org.jabref.logic.importer.fileformat.BibtexImporter; | ||
|
@@ -36,6 +37,9 @@ public class LibraryResource { | |
@Inject | ||
CliPreferences preferences; | ||
|
||
@Inject | ||
FilesToServe filesToServe; | ||
|
||
@Inject | ||
Gson gson; | ||
|
||
|
@@ -89,7 +93,7 @@ public Response getBibtex(@PathParam("id") String id) { | |
} | ||
|
||
private java.nio.file.Path getLibraryPath(String id) { | ||
return preferences.getLastFilesOpenedPreferences().getLastFilesOpened() | ||
return filesToServe.getFilesToServe() | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The method getLibraryPath uses a filter to find a file path, but it throws a NotFoundException if no match is found. This is using exceptions for control flow, which is not recommended. |
||
.stream() | ||
.filter(p -> (p.getFileName() + "-" + BackupFileUtil.getUniqueFilePrefix(p)).equals(id)) | ||
.findAny() | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,15 +6,24 @@ | |
import java.util.ArrayList; | ||
import java.util.Arrays; | ||
import java.util.List; | ||
import java.util.stream.Collectors; | ||
|
||
import javax.net.ssl.SSLContext; | ||
|
||
import org.jabref.architecture.AllowedToUseStandardStreams; | ||
import org.jabref.http.dto.GlobalExceptionMapper; | ||
import org.jabref.http.dto.GsonFactory; | ||
import org.jabref.http.server.services.FilesToServe; | ||
import org.jabref.logic.os.OS; | ||
import org.jabref.logic.preferences.JabRefCliPreferences; | ||
|
||
import jakarta.ws.rs.SeBootstrap; | ||
import net.harawata.appdirs.AppDirsFactory; | ||
import org.glassfish.grizzly.http.server.HttpServer; | ||
import org.glassfish.grizzly.ssl.SSLContextConfigurator; | ||
import org.glassfish.hk2.api.ServiceLocator; | ||
import org.glassfish.hk2.utilities.ServiceLocatorUtilities; | ||
import org.glassfish.jersey.grizzly2.httpserver.GrizzlyHttpServerFactory; | ||
import org.glassfish.jersey.server.ResourceConfig; | ||
import org.jspecify.annotations.NonNull; | ||
import org.slf4j.Logger; | ||
import org.slf4j.LoggerFactory; | ||
|
@@ -24,7 +33,7 @@ | |
public class Server { | ||
private static final Logger LOGGER = LoggerFactory.getLogger(Server.class); | ||
|
||
private static SeBootstrap.Instance serverInstance; | ||
private static final String BASE_URI = "http://localhost:6050/"; | ||
|
||
/** | ||
* Starts an http server serving the last files opened in JabRef<br> | ||
|
@@ -34,7 +43,7 @@ public static void main(final String[] args) throws InterruptedException { | |
SLF4JBridgeHandler.removeHandlersForRootLogger(); | ||
SLF4JBridgeHandler.install(); | ||
|
||
final List<Path> lastFilesOpened = new ArrayList<>(); // JabRefCliPreferences.getInstance().getGuiPreferences().getLastFilesOpened(); | ||
final List<Path> filesToServe = JabRefCliPreferences.getInstance().getLastFilesOpenedPreferences().getLastFilesOpened().stream().collect(Collectors.toCollection(ArrayList::new)); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The use of Collectors.toCollection(ArrayList::new) is unnecessary. The Stream API provides a simpler toList() method that should be used for better readability and maintainability. |
||
|
||
// The server serves the last opened files (see org.jabref.http.server.LibraryResource.getLibraryPath) | ||
// In a testing environment, this might be difficult to handle | ||
|
@@ -44,63 +53,80 @@ public static void main(final String[] args) throws InterruptedException { | |
List<Path> filesToAdd = Arrays.stream(args) | ||
.map(Path::of) | ||
.filter(Files::exists) | ||
.filter(path -> !lastFilesOpened.contains(path)) | ||
.filter(path -> !filesToServe.contains(path)) | ||
.toList(); | ||
|
||
LOGGER.debug("Adding following files to the list of opened libraries: {}", filesToAdd); | ||
|
||
// add the files in the front of the last opened libraries | ||
for (Path path : filesToAdd.reversed()) { | ||
lastFilesOpened.addFirst(path); | ||
filesToServe.addFirst(path); | ||
} | ||
} | ||
|
||
if (lastFilesOpened.isEmpty()) { | ||
LOGGER.debug("still no library available to serve, serve the demo library"); | ||
if (filesToServe.isEmpty()) { | ||
LOGGER.debug("Still no library available to serve, serving the demo library..."); | ||
// Server.class.getResource("...") is always null here, thus trying relative path | ||
// Path bibPath = Path.of(Server.class.getResource("http-server-demo.bib").toURI()); | ||
Path bibPath = Path.of("src/main/resources/org/jabref/http/server/http-server-demo.bib").toAbsolutePath(); | ||
LOGGER.debug("Location of demo library: {}", bibPath); | ||
lastFilesOpened.add(bibPath); | ||
filesToServe.add(bibPath); | ||
} | ||
|
||
LOGGER.debug("Libraries served: {}", lastFilesOpened); | ||
LOGGER.debug("Libraries to serve: {}", filesToServe); | ||
|
||
Server.startServer(); | ||
FilesToServe filesToServeService = new FilesToServe(); | ||
filesToServeService.setFilesToServe(filesToServe); | ||
|
||
Server.startServer(filesToServeService); | ||
|
||
// Keep the http server running until user kills the process (e.g., presses Ctrl+C) | ||
Thread.currentThread().join(); | ||
} | ||
|
||
private static void startServer() { | ||
SeBootstrap.Configuration configuration; | ||
if (!sslCertExists()) { | ||
LOGGER.info("SSL certificate not found. Server starts in non-SSL mode."); | ||
configuration = SeBootstrap.Configuration.builder() | ||
.protocol("HTTP") | ||
.port(6050) | ||
.build(); | ||
} else { | ||
LOGGER.info("SSL certificate found. Server starts in SSL mode."); | ||
SSLContext sslContext = getSslContext(); | ||
configuration = SeBootstrap.Configuration.builder() | ||
.sslContext(sslContext) | ||
.protocol("HTTPS") | ||
.port(6051) | ||
.build(); | ||
} | ||
public static HttpServer startServer(ServiceLocator serviceLocator) { | ||
// see https://stackoverflow.com/a/33794265/873282 | ||
final ResourceConfig resourceConfig = new ResourceConfig(); | ||
// TODO: Add SSL | ||
resourceConfig.register(LibrariesResource.class); | ||
resourceConfig.register(LibraryResource.class); | ||
resourceConfig.register(CORSFilter.class); | ||
resourceConfig.register(GlobalExceptionMapper.class); | ||
|
||
LOGGER.debug("Starting server..."); | ||
SeBootstrap.start(Application.class, configuration).thenAccept(instance -> { | ||
LOGGER.debug("Server started."); | ||
instance.stopOnShutdown(stopResult -> | ||
LOGGER.debug("Stop result: {} [Native stop result: {}].", stopResult, | ||
stopResult.unwrap(Object.class))); | ||
final URI uri = instance.configuration().baseUri(); | ||
LOGGER.debug("Instance {} running at {} [Native handle: {}].%n", instance, uri, | ||
instance.unwrap(Object.class)); | ||
LOGGER.debug("Send SIGKILL to shutdown."); | ||
serverInstance = instance; | ||
}); | ||
final HttpServer httpServer = | ||
GrizzlyHttpServerFactory | ||
.createHttpServer(URI.create(BASE_URI), resourceConfig, serviceLocator); | ||
return httpServer; | ||
} | ||
|
||
private static void startServer(FilesToServe filesToServe) { | ||
ServiceLocator serviceLocator = ServiceLocatorUtilities.createAndPopulateServiceLocator(); | ||
ServiceLocatorUtilities.addFactoryConstants(serviceLocator, new GsonFactory()); | ||
ServiceLocatorUtilities.addFactoryConstants(serviceLocator, new PreferencesFactory()); | ||
ServiceLocatorUtilities.addOneConstant(serviceLocator, filesToServe); | ||
|
||
try { | ||
final HttpServer httpServer = startServer(serviceLocator); | ||
|
||
// add jvm shutdown hook | ||
Runtime.getRuntime().addShutdownHook(new Thread(() -> { | ||
try { | ||
System.out.println("Shutting down jabsrv..."); | ||
httpServer.shutdownNow(); | ||
System.out.println("Done, exit."); | ||
} catch (Exception e) { | ||
LOGGER.error("Could not shut down server", e); | ||
} | ||
})); | ||
|
||
System.out.println("JabSrv started."); | ||
System.out.println("Stop JabSrv using Ctrl+C"); | ||
|
||
Thread.currentThread().join(); | ||
} catch (InterruptedException ex) { | ||
LOGGER.error("Could not start down server", ex); | ||
} | ||
} | ||
|
||
private static boolean sslCertExists() { | ||
|
@@ -132,6 +158,6 @@ private static Path getSslCert() { | |
} | ||
|
||
static void stopServer() { | ||
serverInstance.stop(); | ||
// serverInstance.stop(); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The 'opens' directive is reformatted without adding new statements. Reformatting should only occur with new statements to avoid unnecessary changes.