Skip to content

Commit 9656cf1

Browse files
authored
Add http sever to GUI (#13457)
* Remove remoteThread from HeadlessExecutorService * Initial HttpServerManager * Remove duplicate code * Make http server available in the GUI Signed-off-by: Oliver Kopp <kopp.dev@gmail.com> * Fix class name * Add to preferences * Fix JabSrv CLI startup * Fix port in rest-api.http * Fix CLI start * Add some debug for shutdown * Fix libraries for GUI * Enable start of http server on JabRef start * Proper shutdown * Fix checkstyle * Fix tests --------- Signed-off-by: Oliver Kopp <kopp.dev@gmail.com>
1 parent ef9fef3 commit 9656cf1

File tree

27 files changed

+368
-108
lines changed

27 files changed

+368
-108
lines changed

jabgui/build.gradle.kts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ dependencies {
2323
implementation("org.openjfx:javafx-swing")
2424
implementation("org.openjfx:javafx-web")
2525

26+
implementation(project(":jabsrv"))
27+
2628
implementation("com.pixelduke:fxthemes")
2729

2830
// From JavaFX25 onwards

jabgui/src/main/java/module-info.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
open module org.jabref {
22
requires org.jabref.jablib;
33

4+
requires org.jabref.jabsrv;
5+
46
// Swing
57
requires java.desktop;
68

jabgui/src/main/java/org/jabref/gui/JabRefGUI.java

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
import org.jabref.gui.util.DirectoryMonitor;
2929
import org.jabref.gui.util.UiTaskExecutor;
3030
import org.jabref.gui.util.WebViewStore;
31+
import org.jabref.http.manager.HttpServerManager;
3132
import org.jabref.logic.UiCommand;
3233
import org.jabref.logic.ai.AiService;
3334
import org.jabref.logic.citation.SearchCitationsRelationsService;
@@ -80,6 +81,7 @@ public class JabRefGUI extends Application {
8081
private static JabRefFrame mainFrame;
8182

8283
private static RemoteListenerServerManager remoteListenerServerManager;
84+
private static HttpServerManager httpServerManager;
8385

8486
private Stage mainStage;
8587

@@ -157,7 +159,10 @@ public void initialize() {
157159
IndexManager.clearOldSearchIndices();
158160

159161
JabRefGUI.remoteListenerServerManager = new RemoteListenerServerManager();
160-
Injector.setModelOrService(RemoteListenerServerManager.class, remoteListenerServerManager);
162+
Injector.setModelOrService(RemoteListenerServerManager.class, JabRefGUI.remoteListenerServerManager);
163+
164+
JabRefGUI.httpServerManager = new HttpServerManager();
165+
Injector.setModelOrService(HttpServerManager.class, JabRefGUI.httpServerManager);
161166

162167
JabRefGUI.stateManager = new StateManager();
163168
Injector.setModelOrService(StateManager.class, stateManager);
@@ -396,13 +401,18 @@ private boolean upperRightIsInBounds(CoreGuiPreferences coreGuiPreferences) {
396401
// Background tasks
397402
public void startBackgroundTasks() {
398403
RemotePreferences remotePreferences = preferences.getRemotePreferences();
404+
399405
if (remotePreferences.useRemoteServer()) {
400406
remoteListenerServerManager.openAndStart(
401407
new CLIMessageHandler(
402408
mainFrame,
403409
preferences),
404410
remotePreferences.getPort());
405411
}
412+
413+
if (remotePreferences.enableHttpServer()) {
414+
httpServerManager.start(stateManager.getOpenDatabases(), remotePreferences.getHttpServerUri());
415+
}
406416
}
407417

408418
@Override
@@ -413,14 +423,25 @@ public void stop() {
413423
} catch (Exception e) {
414424
LOGGER.error("Unable to close AI service", e);
415425
}
426+
416427
LOGGER.trace("Closing OpenOffice connection");
417428
OOBibBaseConnect.closeOfficeConnection();
429+
430+
LOGGER.trace("Shutting down remote server manager");
431+
remoteListenerServerManager.stop();
432+
433+
LOGGER.trace("Shutting down http server manager");
434+
httpServerManager.stop();
435+
418436
LOGGER.trace("Stopping background tasks");
419437
stopBackgroundTasks();
438+
420439
LOGGER.trace("Shutting down thread pools");
421440
shutdownThreadPools();
441+
422442
LOGGER.trace("Closing citations and relations search service");
423443
citationsAndRelationsSearchService.close();
444+
424445
LOGGER.trace("Finished stop");
425446
}
426447

jabgui/src/main/java/org/jabref/gui/preferences/general/GeneralTab.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ public class GeneralTab extends AbstractPreferenceTabView<GeneralTabViewModel> i
5757
@FXML private TextField backupDirectory;
5858
@FXML private CheckBox remoteServer;
5959
@FXML private TextField remotePort;
60+
@FXML private CheckBox enableHttpServer;
6061
@FXML private Button remoteHelp;
6162
@Inject private FileUpdateMonitor fileUpdateMonitor;
6263
@Inject private BibEntryTypesManager entryTypesManager;
@@ -149,6 +150,8 @@ public void initialize() {
149150
remoteServer.selectedProperty().bindBidirectional(viewModel.remoteServerProperty());
150151
remotePort.textProperty().bindBidirectional(viewModel.remotePortProperty());
151152
remotePort.disableProperty().bind(remoteServer.selectedProperty().not());
153+
154+
enableHttpServer.selectedProperty().bindBidirectional(viewModel.enableHttpServerProperty());
152155
}
153156

154157
@FXML

jabgui/src/main/java/org/jabref/gui/preferences/general/GeneralTabViewModel.java

Lines changed: 32 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package org.jabref.gui.preferences.general;
22

33
import java.io.IOException;
4+
import java.net.URI;
45
import java.nio.file.Path;
56
import java.util.ArrayList;
67
import java.util.List;
@@ -17,9 +18,11 @@
1718
import javafx.beans.property.SimpleStringProperty;
1819
import javafx.beans.property.StringProperty;
1920
import javafx.collections.FXCollections;
21+
import javafx.collections.ObservableList;
2022
import javafx.scene.control.SpinnerValueFactory;
2123

2224
import org.jabref.gui.DialogService;
25+
import org.jabref.gui.StateManager;
2326
import org.jabref.gui.WorkspacePreferences;
2427
import org.jabref.gui.desktop.os.NativeDesktop;
2528
import org.jabref.gui.frame.UiMessageHandler;
@@ -30,6 +33,7 @@
3033
import org.jabref.gui.theme.ThemeTypes;
3134
import org.jabref.gui.util.DirectoryDialogConfiguration;
3235
import org.jabref.gui.util.FileDialogConfiguration;
36+
import org.jabref.http.manager.HttpServerManager;
3337
import org.jabref.logic.FilePreferences;
3438
import org.jabref.logic.LibraryPreferences;
3539
import org.jabref.logic.l10n.Language;
@@ -39,6 +43,7 @@
3943
import org.jabref.logic.remote.RemoteUtil;
4044
import org.jabref.logic.remote.server.RemoteListenerServerManager;
4145
import org.jabref.logic.util.StandardFileType;
46+
import org.jabref.model.database.BibDatabaseContext;
4247
import org.jabref.model.database.BibDatabaseMode;
4348
import org.jabref.model.strings.StringUtil;
4449
import org.jabref.model.util.FileUpdateMonitor;
@@ -49,12 +54,16 @@
4954
import de.saxsys.mvvmfx.utils.validation.ValidationMessage;
5055
import de.saxsys.mvvmfx.utils.validation.ValidationStatus;
5156
import de.saxsys.mvvmfx.utils.validation.Validator;
57+
import org.slf4j.Logger;
58+
import org.slf4j.LoggerFactory;
5259

5360
public class GeneralTabViewModel implements PreferenceTabViewModel {
5461

5562
protected static SpinnerValueFactory<Integer> fontSizeValueFactory =
5663
new SpinnerValueFactory.IntegerSpinnerValueFactory(9, Integer.MAX_VALUE);
5764

65+
private static final Logger LOGGER = LoggerFactory.getLogger(GeneralTabViewModel.class);
66+
5867
private final ReadOnlyListProperty<Language> languagesListProperty =
5968
new ReadOnlyListWrapper<>(FXCollections.observableArrayList(Language.getSorted()));
6069
private final ObjectProperty<Language> selectedLanguageProperty = new SimpleObjectProperty<>();
@@ -101,9 +110,11 @@ public class GeneralTabViewModel implements PreferenceTabViewModel {
101110
private final BooleanProperty remoteServerProperty = new SimpleBooleanProperty();
102111
private final StringProperty remotePortProperty = new SimpleStringProperty("");
103112
private final Validator remotePortValidator;
104-
private final FileUpdateMonitor fileUpdateMonitor;
113+
private final BooleanProperty enableHttpServerProperty = new SimpleBooleanProperty();
105114
private final TrustStoreManager trustStoreManager;
106115

116+
private final FileUpdateMonitor fileUpdateMonitor;
117+
107118
public GeneralTabViewModel(DialogService dialogService, GuiPreferences preferences, FileUpdateMonitor fileUpdateMonitor) {
108119
this.dialogService = dialogService;
109120
this.preferences = preferences;
@@ -197,6 +208,8 @@ public void setValues() {
197208

198209
remoteServerProperty.setValue(remotePreferences.useRemoteServer());
199210
remotePortProperty.setValue(String.valueOf(remotePreferences.getPort()));
211+
212+
enableHttpServerProperty.setValue(remotePreferences.enableHttpServer());
200213
}
201214

202215
@Override
@@ -251,27 +264,31 @@ public void storeSettings() {
251264

252265
UiMessageHandler uiMessageHandler = Injector.instantiateModelOrService(UiMessageHandler.class);
253266
RemoteListenerServerManager remoteListenerServerManager = Injector.instantiateModelOrService(RemoteListenerServerManager.class);
254-
remoteListenerServerManager.stop(); // stop in all cases, because the port might have changed
255-
267+
// stop in all cases, because the port might have changed
268+
remoteListenerServerManager.stop();
256269
if (remoteServerProperty.getValue()) {
257270
remotePreferences.setUseRemoteServer(true);
258271
remoteListenerServerManager.openAndStart(
259272
new CLIMessageHandler(uiMessageHandler, preferences),
260273
remotePreferences.getPort());
261274
} else {
262275
remotePreferences.setUseRemoteServer(false);
276+
remoteListenerServerManager.stop();
263277
}
264-
trustStoreManager.flush();
265278

266-
if (remoteServerProperty.getValue()) {
267-
remotePreferences.setUseRemoteServer(true);
268-
remoteListenerServerManager.openAndStart(
269-
new CLIMessageHandler(uiMessageHandler, preferences),
270-
remotePreferences.getPort());
279+
HttpServerManager httpServerManager = Injector.instantiateModelOrService(HttpServerManager.class);
280+
// stop in all cases, because the port might have changed
281+
httpServerManager.stop();
282+
if (enableHttpServerProperty.getValue()) {
283+
remotePreferences.setEnableHttpServer(true);
284+
ObservableList<BibDatabaseContext> openDatabases = Injector.instantiateModelOrService(StateManager.class).getOpenDatabases();
285+
URI uri = remotePreferences.getHttpServerUri();
286+
httpServerManager.start(openDatabases, uri);
271287
} else {
272-
remotePreferences.setUseRemoteServer(false);
273-
remoteListenerServerManager.stop();
288+
remotePreferences.setEnableHttpServer(false);
289+
httpServerManager.stop();
274290
}
291+
275292
trustStoreManager.flush();
276293
}
277294

@@ -421,6 +438,10 @@ public StringProperty remotePortProperty() {
421438
return remotePortProperty;
422439
}
423440

441+
public BooleanProperty enableHttpServerProperty() {
442+
return enableHttpServerProperty;
443+
}
444+
424445
public void openBrowser() {
425446
String url = "https://themes.jabref.org";
426447
try {

jabgui/src/main/resources/org/jabref/gui/preferences/general/GeneralTab.fxml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,9 @@
8282
<Button fx:id="remoteHelp" prefWidth="20.0" />
8383
</HBox>
8484

85+
<Label styleClass="sectionHeader" text="%HTTP Server" />
86+
<CheckBox fx:id="enableHttpServer" text="%Enable HTTP Server (e.g., for JabMap)" />
87+
8588
<Label styleClass="sectionHeader" text="%Libraries"/>
8689
<GridPane hgap="10.0" vgap="4.0">
8790
<columnConstraints>

jablib/src/main/java/org/jabref/logic/preferences/JabRefCliPreferences.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -365,6 +365,7 @@ public class JabRefCliPreferences implements CliPreferences {
365365
// Remote
366366
private static final String USE_REMOTE_SERVER = "useRemoteServer";
367367
private static final String REMOTE_SERVER_PORT = "remoteServerPort";
368+
private static final String ENABLE_HTTP_SERVER = "enableHttpServer";
368369

369370
private static final String AI_ENABLED = "aiEnabled";
370371
private static final String AI_AUTO_GENERATE_EMBEDDINGS = "aiAutoGenerateEmbeddings";
@@ -637,6 +638,7 @@ public JabRefCliPreferences() {
637638

638639
defaults.put(USE_REMOTE_SERVER, Boolean.TRUE);
639640
defaults.put(REMOTE_SERVER_PORT, 6050);
641+
defaults.put(ENABLE_HTTP_SERVER, Boolean.FALSE);
640642

641643
defaults.put(EXTERNAL_JOURNAL_LISTS, "");
642644
defaults.put(USE_AMS_FJOURNAL, true);
@@ -1247,10 +1249,12 @@ public RemotePreferences getRemotePreferences() {
12471249

12481250
remotePreferences = new RemotePreferences(
12491251
getInt(REMOTE_SERVER_PORT),
1250-
getBoolean(USE_REMOTE_SERVER));
1252+
getBoolean(USE_REMOTE_SERVER),
1253+
getBoolean(ENABLE_HTTP_SERVER));
12511254

12521255
EasyBind.listen(remotePreferences.portProperty(), (_, _, newValue) -> putInt(REMOTE_SERVER_PORT, newValue));
12531256
EasyBind.listen(remotePreferences.useRemoteServerProperty(), (_, _, newValue) -> putBoolean(USE_REMOTE_SERVER, newValue));
1257+
EasyBind.listen(remotePreferences.enableHttpServerProperty(), (_, _, newValue) -> putBoolean(ENABLE_HTTP_SERVER, newValue));
12541258

12551259
return remotePreferences;
12561260
}

jablib/src/main/java/org/jabref/logic/remote/RemotePreferences.java

Lines changed: 34 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,33 @@
11
package org.jabref.logic.remote;
22

33
import java.net.InetAddress;
4+
import java.net.URI;
45
import java.net.UnknownHostException;
56

67
import javafx.beans.property.BooleanProperty;
78
import javafx.beans.property.IntegerProperty;
89
import javafx.beans.property.SimpleBooleanProperty;
910
import javafx.beans.property.SimpleIntegerProperty;
1011

12+
import org.slf4j.Logger;
13+
import org.slf4j.LoggerFactory;
14+
1115
/**
1216
* Place for handling the preferences for the remote communication
1317
*/
1418
public class RemotePreferences {
1519

20+
private static final Logger LOGGER = LoggerFactory.getLogger(RemotePreferences.class);
21+
1622
private final IntegerProperty port;
1723
private final BooleanProperty useRemoteServer;
1824

19-
public RemotePreferences(int port, boolean useRemoteServer) {
25+
private final BooleanProperty enableHttpServer;
26+
27+
public RemotePreferences(int port, boolean useRemoteServer, boolean enableHttpServer) {
2028
this.port = new SimpleIntegerProperty(port);
2129
this.useRemoteServer = new SimpleBooleanProperty(useRemoteServer);
30+
this.enableHttpServer = new SimpleBooleanProperty(enableHttpServer);
2231
}
2332

2433
public int getPort() {
@@ -33,6 +42,10 @@ public void setPort(int port) {
3342
this.port.setValue(port);
3443
}
3544

45+
public boolean isDifferentPort(int otherPort) {
46+
return getPort() != otherPort;
47+
}
48+
3649
public boolean useRemoteServer() {
3750
return useRemoteServer.getValue();
3851
}
@@ -45,14 +58,29 @@ public void setUseRemoteServer(boolean useRemoteServer) {
4558
this.useRemoteServer.setValue(useRemoteServer);
4659
}
4760

48-
public boolean isDifferentPort(int otherPort) {
49-
return getPort() != otherPort;
61+
public boolean enableHttpServer() {
62+
return enableHttpServer.getValue();
63+
}
64+
65+
public BooleanProperty enableHttpServerProperty() {
66+
return enableHttpServer;
5067
}
5168

52-
/**
53-
* Gets the IP address where the remote server is listening.
54-
*/
69+
public void setEnableHttpServer(boolean enableHttpServer) {
70+
this.enableHttpServer.setValue(enableHttpServer);
71+
}
72+
73+
/// Gets the IP address where both the remote server and the http server are listening.
5574
public static InetAddress getIpAddress() throws UnknownHostException {
5675
return InetAddress.getByName("localhost");
5776
}
77+
78+
public URI getHttpServerUri() {
79+
try {
80+
return URI.create("http://" + RemotePreferences.getIpAddress().getHostAddress() + ":23119");
81+
} catch (UnknownHostException e) {
82+
LOGGER.error("Could not create HTTP server URI. Falling back to default.", e);
83+
return URI.create("http://localhost:23119");
84+
}
85+
}
5886
}

0 commit comments

Comments
 (0)