Skip to content
Draft
Show file tree
Hide file tree
Changes from 8 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
2 changes: 2 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ gradlew text eol=lf

# .bib files have to be written using OS specific line endings to enable our tests working
*.bib text !eol
# Exception: The files used for the http server test - they should have linux line endings
src/test/resources/org/jabref/http/server/*.bib text eol=lf

# Citavi needs to be LF line ending
# This overwrites the setting of "*.bib"
Expand Down
28 changes: 28 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,8 @@ dependencies {
implementation "org.tinylog:tinylog-api:2.6.1"
implementation "org.tinylog:slf4j-tinylog:2.6.1"
implementation "org.tinylog:tinylog-impl:2.6.1"
// route all requests to java.util.logging to SLF4J (which in turn routes to tinylog)
implementation 'org.slf4j:jul-to-slf4j:2.0.7'

implementation 'de.undercouch:citeproc-java:3.0.0-beta.2'

Expand All @@ -200,6 +202,26 @@ dependencies {

implementation group: 'net.harawata', name: 'appdirs', version: '1.2.1'

// JAX-RS implemented by Jersey
// API
implementation 'jakarta.ws.rs:jakarta.ws.rs-api:3.1.0'
// Implementation of the API
implementation 'org.glassfish.jersey.core:jersey-server:3.1.1'
// injection framework
implementation 'org.glassfish.jersey.inject:jersey-hk2:3.1.1'
implementation 'org.glassfish.hk2:hk2-api:2.6.1'
// testImplementation 'org.glassfish.hk2:hk2-testing:3.0.4'
// implementation 'org.glassfish.hk2:hk2-testing-jersey:3.0.4'
// testImplementation 'org.glassfish.hk2:hk2-junitrunner:3.0.4'
// HTTP server
// implementation 'org.glassfish.jersey.containers:jersey-container-netty-http:3.1.1'
implementation 'org.glassfish.jersey.containers:jersey-container-grizzly2-http:3.1.1'
testImplementation 'org.glassfish.jersey.test-framework.providers:jersey-test-framework-provider-grizzly2:3.1.1'
// OpenAPI generation
implementation 'io.swagger.core.v3:swagger-jaxrs2-jakarta:2.2.9'
// Allow objects "magically" to be mapped to JSON using GSON
// implementation 'org.glassfish.jersey.media:jersey-media-json-gson:3.1.1'

testImplementation 'io.github.classgraph:classgraph:4.8.157'
testImplementation 'org.junit.jupiter:junit-jupiter:5.9.2'
testImplementation 'org.junit.platform:junit-platform-launcher:1.9.2'
Expand Down Expand Up @@ -381,6 +403,12 @@ run {
'javafx.base/com.sun.javafx.event' : 'com.jfoenix'
]
}

if (project.hasProperty('application')){
if (application == 'httpserver'){
main = 'org.jabref.http.server.Server'
}
}
}

javadoc {
Expand Down
16 changes: 16 additions & 0 deletions docs/code-howtos/http-server.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
---
parent: Code Howtos
---
# HTTP Server

## Get SSL Working

(Based on <https://stackoverflow.com/a/57511038/873282>)

Howto vor Windows - other operating systems work similar:

1. As admin `choco install mkcert`
2. As admin: `mkcert -install`
3. `cd %APPDATA%\..\local\org.jabref\jabref\ssl`
4. `mkcert -pkcs12 jabref.desktop jabref localhost 127.0.0.1 ::1`
5. Rename the file to `server.p12`
53 changes: 53 additions & 0 deletions docs/decisions/0027-http-return-bibtex-string.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
---
nav_order: 27
parent: Decision Records
---
<!-- we need to disable MD025, because we use the different heading "ADR Template" in the homepage (see above) than it is foreseen in the template -->
<!-- markdownlint-disable-next-line MD025 -->
# Return BibTeX string and CSL Item JSON in the API

## Context and Problem Statement

In the context of an http server, when a http client `GETs` a JSON data structure containing BibTeX data, which format should that have?

## Considered Options

* Offer both, BibTeX string and CSL JSON
* Return BibTeX as is as string
* Convert BibTeX to JSON

## Decision Outcome

Chosen option: "Offer both, BibTeX string and CSL JSON", because there are many browser libraries out there being able to parse BibTeX. Thus, we don't need to convert it.

## Pros and Cons of the Options

### Offer both, BibTeX string and CSL JSON

- Good, because this follows "Backend for Frontend"
- Good, because Word Addin works seamless with the data provided (and does not need another dependency)
- Good, because other clients can work with BibTeX data
- Bad, because two serializations have to be kept

### Return BibTeX as is as string

- Good, because we don't need to think about any conversion
- Bad, because it is unclear how to ship BibTeX data where the entry is dependent on
- Bad, because client needs add additional parsing logic

### Convert BibTeX to JSON

More thought has to be done when converting to JSON.
There seems to be a JSON format from [@citation-js/plugin-bibtex](https://www.npmjs.com/package/@citation-js/plugin-bibtex).
We could do an additional self-made JSON format, but this increases the number of available JSON serializations for BibTeX.

- Good, because it could flatten BibTeX data (example: `author = first # " and " # second`)
- Bad, because conversion is difficult in BibTeX special cases. For instance, if Strings are used (example: `author = first # " and " # second`) and one doesn't want to flatten ("normalize") this.

## More Information

Existing JavaScript BibTeX libraries:

* [bibtex-js](https://github.com/digitalheir/bibtex-js)
* [bibtexParseJS](https://github.com/ORCID/bibtexParseJs)
* [@citation-js/plugin-bibtex](https://www.npmjs.com/package/@citation-js/plugin-bibtex)
77 changes: 50 additions & 27 deletions src/main/java/module-info.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@
requires afterburner.fx;
requires com.jfoenix;
requires de.saxsys.mvvmfx;
requires reactfx;
requires de.saxsys.mvvmfx.validation;
requires org.fxmisc.flowless;

requires org.kordamp.ikonli.core;
requires org.kordamp.ikonli.javafx;
Expand All @@ -39,6 +42,7 @@

// Logging
requires org.slf4j;
requires jul.to.slf4j;
requires org.tinylog.api;
requires org.tinylog.api.slf4j;
requires org.tinylog.impl;
Expand All @@ -47,47 +51,64 @@
with org.jabref.gui.logging.GuiWriter,
org.jabref.gui.logging.ApplicationInsightsWriter;

// Preferences and XML
requires java.prefs;

// Annotations (@PostConstruct)
requires jakarta.annotation;
requires jakarta.inject;

// http server and client exchange
requires java.net.http;
requires jakarta.ws.rs;
requires grizzly.framework;

// OpenAPI generation
requires io.swagger.v3.core;
requires io.swagger.v3.oas.models;
requires io.swagger.v3.oas.integration;
requires io.swagger.v3.jaxrs2;

// data mapping
requires jakarta.xml.bind;
requires jdk.xml.dom;
requires com.google.gson;
requires com.fasterxml.jackson.databind;
requires com.fasterxml.jackson.dataformat.yaml;
requires com.fasterxml.jackson.datatype.jsr310;
// needs to be loaded here as it's otherwise not found at runtime
requires org.glassfish.jaxb.runtime;
requires jdk.xml.dom;

// Annotations (@PostConstruct)
requires jakarta.annotation;
// dependency injection using HK2
requires org.glassfish.hk2.api;

// Microsoft application insights
requires applicationinsights.core;
requires applicationinsights.logging.log4j2;

// Libre Office
requires org.libreoffice.uno;

// Other modules
requires com.google.common;
requires jakarta.inject;
requires reactfx;
requires commons.cli;
requires com.github.tomtung.latex2unicode;
requires fastparse;
requires jbibtex;
requires citeproc.java;
requires de.saxsys.mvvmfx.validation;
requires com.google.gson;
// http clients
requires unirest.java;
requires org.apache.httpcomponents.httpclient;
requires org.jsoup;
requires org.apache.commons.csv;
requires io.github.javadiffutils;
requires java.string.similarity;

// SQL databases
requires ojdbc10;
requires org.postgresql.jdbc;
requires org.mariadb.jdbc;
uses org.mariadb.jdbc.credential.CredentialPlugin;

// Apache Commons and other (similar) helper libraries
requires commons.cli;
requires org.apache.commons.csv;
requires org.apache.commons.lang3;
requires org.antlr.antlr4.runtime;
requires org.fxmisc.flowless;
requires com.google.common;
requires io.github.javadiffutils;
requires java.string.similarity;

requires com.github.tomtung.latex2unicode;
requires fastparse;

requires jbibtex;
requires citeproc.java;

requires pdfbox;
requires xmpbox;
Expand All @@ -96,7 +117,6 @@
requires flexmark;
requires flexmark.util.ast;
requires flexmark.util.data;
requires com.h2database.mvstore;

// fulltext search
requires org.apache.lucene.core;
Expand All @@ -108,14 +128,17 @@
requires org.apache.lucene.analysis.common;
requires org.apache.lucene.highlighter;

requires com.fasterxml.jackson.databind;
requires com.fasterxml.jackson.dataformat.yaml;
requires com.fasterxml.jackson.datatype.jsr310;
requires net.harawata.appdirs;
requires com.sun.jna;
requires com.sun.jna.platform;

requires org.eclipse.jgit;
uses org.eclipse.jgit.transport.SshSessionFactory;
uses org.eclipse.jgit.lib.GpgSigner;

// other libraries
requires com.h2database.mvstore;
requires org.antlr.antlr4.runtime;
requires org.libreoffice.uno;

}
21 changes: 14 additions & 7 deletions src/main/java/org/jabref/cli/Launcher.java
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
import org.apache.commons.cli.ParseException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.bridge.SLF4JBridgeHandler;
import org.tinylog.configuration.Configuration;

/**
Expand All @@ -46,6 +47,7 @@ public class Launcher {
private static String[] ARGUMENTS;

public static void main(String[] args) {
routeLoggingToSlf4J();
ARGUMENTS = args;
addLogToDisk();
try {
Expand Down Expand Up @@ -84,6 +86,11 @@ public static void main(String[] args) {
}
}

private static void routeLoggingToSlf4J() {
SLF4JBridgeHandler.removeHandlersForRootLogger();
SLF4JBridgeHandler.install();
}

/**
* This needs to be called as early as possible. After the first log write, it
* is not possible to alter
Expand All @@ -92,10 +99,10 @@ public static void main(String[] args) {
private static void addLogToDisk() {
Path directory = Path.of(AppDirsFactory.getInstance()
.getUserDataDir(
OS.APP_DIR_APP_NAME,
"logs",
OS.APP_DIR_APP_AUTHOR))
.resolve(new BuildInfo().version.toString());
OS.APP_DIR_APP_NAME,
"logs",
OS.APP_DIR_APP_AUTHOR))
.resolve(new BuildInfo().version.toString());
try {
Files.createDirectories(directory);
} catch (IOException e) {
Expand Down Expand Up @@ -183,9 +190,9 @@ private static void clearOldSearchIndices() {
&& !path.equals(currentIndexPath)) {
LOGGER.info("Deleting out-of-date fulltext search index at {}.", path);
Files.walk(path)
.sorted(Comparator.reverseOrder())
.map(Path::toFile)
.forEach(File::delete);
.sorted(Comparator.reverseOrder())
.map(Path::toFile)
.forEach(File::delete);
}
}
} catch (IOException e) {
Expand Down
6 changes: 6 additions & 0 deletions src/main/java/org/jabref/http/MediaType.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package org.jabref.http;

public class MediaType {
public static final String BIBTEX = "application/x-bibtex";
public static final String JSON_CSL_ITEM = "application/x-bibtex-library-csl+json";
}
53 changes: 53 additions & 0 deletions src/main/java/org/jabref/http/client/SyncClient.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package org.jabref.http.client;

import java.io.IOException;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.util.List;

import org.jabref.model.database.BibDatabaseContext;
import org.jabref.http.dto.BibEntryDTO;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚫 [reviewdog] <com.puppycrawl.tools.checkstyle.checks.imports.ImportOrderCheck> reported by reviewdog 🐶
Wrong order for 'org.jabref.http.dto.BibEntryDTO' import.


public class SyncClient {

private final BibDatabaseContext bibDatabaseContext;
private Long lastSynchronizedGlobalRevision = -1L;

private HttpClient httpClient = HttpClient.newHttpClient();

/**
* Initializes a client for the given context
*/
public SyncClient(BibDatabaseContext bibDatabaseContext) throws IllegalArgumentException {
if (bibDatabaseContext.getDatabasePath().isEmpty()) {
throw new IllegalArgumentException("Unsaved libraries not yet supported.");
}
this.bibDatabaseContext = bibDatabaseContext;
}

/**
* Client needs to store the state of Id and entry locally to be able to handle external changes.
* This is done using the "dirty" flag.
*/
private void synchronizeWithLocalView() {
}

public List<BibEntryDTO> getChanges() throws IOException, InterruptedException {
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("http://localhost:8080/updates?lastUpdate=0"))
.GET()
.build();
HttpResponse<String> response = httpClient.send(request, HttpResponse.BodyHandlers.ofString());
return null;
}

/**
* Synchronizes the given library with the server.
* <p>
* Pre-condition: Connection with server works
*/
public void synchronize(BibDatabaseContext bibDatabaseContext) {
}
}
Loading