Skip to content

Commit ee7e643

Browse files
tobiasdiezcalixtusSiedlerchr
authored andcommitted
Removed swing from default file dir detection (JabRef#9222)
* Save files again relative to bib file * Reworded * Reintroduced default file chooser directory without swing * Update CHANGELOG.md * Update CHANGELOG.md * Update NativeDesktop.java * Reworked ADR * Added mac directory * Removed comments * Added linux support * Revert "Save files again relative to bib file" This reverts commit 3e640f5. # Conflicts: # CHANGELOG.md # src/main/java/org/jabref/preferences/FilePreferences.java # src/main/java/org/jabref/preferences/JabRefPreferences.java # src/test/java/org/jabref/model/database/BibDatabaseContextTest.java * Update src/main/java/org/jabref/gui/desktop/os/Windows.java * fix merge errors * fix wrong method call * remove defautl fix checkstyle * reintroduce method to avoid calling get two times * Introduced getPath method * Update src/main/java/org/jabref/gui/desktop/os/Linux.java fix env var Co-authored-by: Carl Christian Snethlage <[email protected]> Co-authored-by: Siedlerchr <[email protected]>
1 parent 4b73d9a commit ee7e643

File tree

15 files changed

+79
-50
lines changed

15 files changed

+79
-50
lines changed

CHANGELOG.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ Note that this project **does not** adhere to [Semantic Versioning](http://semve
3838
- A user can now add arbitrary data into `study.yml`. JabRef just ignores this data. [#9124](https://github.com/JabRef/jabref/pull/9124)
3939
- We reworked the External Changes Resolver dialog. [#9021](https://github.com/JabRef/jabref/pull/9021)
4040
- The fallback directory of the file folder now is the general file directory. In case there was a directory configured for a library and this directory was not found, JabRef placed the PDF next to the .bib file and not into the general file directory.
41-
- The global default directory for storing PDFs is now the subdirectory "JabRef" in the user's home.
41+
- The global default directory for storing PDFs is now the documents folder in the user's home.
4242
- We reworked the Define study parameters dialog. [#9123](https://github.com/JabRef/jabref/pull/9123)
4343
- We simplified the actions to fast-resolve duplicates to 'Keep Left', 'Keep Right', 'Keep Both' and 'Keep Merged'. [#9056](https://github.com/JabRef/jabref/issues/9056)
4444
- We fixed an issue where a message about changed metadata would occur on saving although nothing changed. [#9159](https://github.com/JabRef/jabref/issues/9159)

docs/decisions/0026-use-swings-file-chooser-to-determine-default-directory.md renamed to docs/decisions/0026-use-jna-to-determine-default-directory.md

+10-4
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
nav_order: 26
33
parent: Decision Records
44
---
5-
# Use Swing's FileChooser to Determine Default Directory
5+
# Use Java Native Access to Determine Default Directory
66

77
## Context and Problem Statement
88

@@ -20,11 +20,11 @@ How to determine the "best" directory native for the OS the user runs.
2020
* Use Swing's FileChooser to Determine Default Directory
2121
* Use `user.home`
2222
* [AppDirs](https://github.com/harawata/appdirs)
23+
* [Java Native Access](https://github.com/java-native-access/jna)
2324

2425
## Decision Outcome
2526

26-
Chosen option: "Use Swing's FileChooser to Determine Default Directory", because
27-
comes out best (see below).
27+
Chosen option: "Java Native Access", because comes out best (see below).
2828

2929
## Pros and Cons of the Options
3030

@@ -51,7 +51,13 @@ There is `System.getProperty("user.home");`.
5151
> AppDirs is a small java library which provides a path to the platform dependent special folder/directory.
5252
5353
* Good, because already used in JabRef
54-
* Bad, because does not use "MyDocuments" on Windows, but rather `C:\Users\<Account>\AppData\<AppAuthor>\<AppName>` as basis
54+
* Bad, because does not use `Documents` on Windows, but rather `C:\Users\<Account>\AppData\<AppAuthor>\<AppName>` as basis
55+
56+
### Java Native Access
57+
58+
* Good, because no additional dependency required, as it is already loaded by AppDirs
59+
* Good, because it is well maintained and widely used
60+
* Good, because it provides direct access to `Documents` and other system variables
5561

5662
## More Information
5763

src/main/java/module-info.java

+1
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,7 @@
114114
requires com.fasterxml.jackson.dataformat.yaml;
115115
requires com.fasterxml.jackson.datatype.jsr310;
116116
requires net.harawata.appdirs;
117+
requires com.sun.jna.platform;
117118

118119
requires org.eclipse.jgit;
119120
requires com.jthemedetector;

src/main/java/org/jabref/gui/desktop/JabRefDesktop.java

-19
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,6 @@
1010
import java.util.Optional;
1111
import java.util.regex.Pattern;
1212

13-
import javax.swing.filechooser.FileSystemView;
14-
15-
import org.jabref.architecture.AllowedToUseSwing;
1613
import org.jabref.gui.DialogService;
1714
import org.jabref.gui.Globals;
1815
import org.jabref.gui.desktop.os.DefaultDesktop;
@@ -40,7 +37,6 @@
4037
* TODO: Replace by http://docs.oracle.com/javase/7/docs/api/java/awt/Desktop.html
4138
* http://stackoverflow.com/questions/18004150/desktop-api-is-not-supported-on-the-current-platform
4239
*/
43-
@AllowedToUseSwing("Needs access to swing for the user's os dependent file chooser path")
4440
public class JabRefDesktop {
4541

4642
private static final Logger LOGGER = LoggerFactory.getLogger(JabRefDesktop.class);
@@ -292,21 +288,6 @@ public static void openConsole(File file, PreferencesService preferencesService,
292288
}
293289
}
294290

295-
/**
296-
* Get the user's default file chooser directory
297-
*
298-
* @return The path to the directory
299-
*/
300-
public static String getDefaultFileChooserDirectory() {
301-
// Implementation: ADR-0026
302-
303-
// We do not return a subdirectory "JabRef", because
304-
// - the directory might not exist at this point of the method
305-
// - we might not have the rights to create a directory
306-
// - getters should not have any side effect
307-
return FileSystemView.getFileSystemView().getDefaultDirectory().getPath();
308-
}
309-
310291
// TODO: Move to OS.java
311292
public static NativeDesktop getNativeDesktop() {
312293
if (OS.WINDOWS) {

src/main/java/org/jabref/gui/desktop/os/DefaultDesktop.java

+5
Original file line numberDiff line numberDiff line change
@@ -45,4 +45,9 @@ public String detectProgramPath(String programName, String directoryName) {
4545
public Path getApplicationDirectory() {
4646
return getUserDirectory();
4747
}
48+
49+
@Override
50+
public Path getDefaultFileChooserDirectory() {
51+
return Path.of(System.getProperty("user.home"));
52+
}
4853
}

src/main/java/org/jabref/gui/desktop/os/Linux.java

+10-1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import java.nio.file.Files;
99
import java.nio.file.Path;
1010
import java.util.Locale;
11+
import java.util.Objects;
1112
import java.util.Optional;
1213

1314
import org.jabref.architecture.AllowedToUseAwt;
@@ -134,7 +135,7 @@ public void openConsole(String absolutePath, DialogService dialogService) throws
134135
if (emulatorName != null) {
135136
emulatorName = emulatorName.substring(emulatorName.lastIndexOf(File.separator) + 1);
136137

137-
String[] cmd = {};
138+
String[] cmd;
138139
if (emulatorName.contains("gnome")) {
139140
cmd = new String[] {"gnome-terminal", "--working-directory=", absolutePath};
140141
} else if (emulatorName.contains("xfce4")) {
@@ -167,4 +168,12 @@ public String detectProgramPath(String programName, String directoryName) {
167168
public Path getApplicationDirectory() {
168169
return Path.of("/usr/lib/");
169170
}
171+
172+
@Override
173+
public Path getDefaultFileChooserDirectory() {
174+
return Path.of(Objects.requireNonNullElse(
175+
System.getenv("XDG_DOCUMENTS_DIR"),
176+
System.getProperty("user.home") + "/Documents")
177+
);
178+
}
170179
}

src/main/java/org/jabref/gui/desktop/os/NativeDesktop.java

+7-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ public interface NativeDesktop {
1414
*
1515
* @param filePath The filename.
1616
* @param application Link to the app that opens the file.
17-
* @throws IOException
1817
*/
1918
void openFileWithApplication(String filePath, String application) throws IOException;
2019

@@ -31,6 +30,13 @@ public interface NativeDesktop {
3130
*/
3231
Path getApplicationDirectory();
3332

33+
/**
34+
* Get the user's default file chooser directory
35+
*
36+
* @return The path to the directory
37+
*/
38+
Path getDefaultFileChooserDirectory();
39+
3440
/**
3541
* Returns the path to the system's user directory.
3642
*

src/main/java/org/jabref/gui/desktop/os/OSX.java

+5
Original file line numberDiff line numberDiff line change
@@ -52,4 +52,9 @@ public String detectProgramPath(String programName, String directoryName) {
5252
public Path getApplicationDirectory() {
5353
return Path.of("/Applications");
5454
}
55+
56+
@Override
57+
public Path getDefaultFileChooserDirectory() {
58+
return Path.of(System.getProperty("user.home") + "/Documents");
59+
}
5560
}

src/main/java/org/jabref/gui/desktop/os/Windows.java

+24
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,16 @@
1111
import org.jabref.gui.externalfiletype.ExternalFileType;
1212
import org.jabref.gui.externalfiletype.ExternalFileTypes;
1313

14+
import com.sun.jna.platform.win32.KnownFolders;
15+
import com.sun.jna.platform.win32.Shell32Util;
16+
import com.sun.jna.platform.win32.ShlObj;
17+
import com.sun.jna.platform.win32.Win32Exception;
18+
import org.slf4j.Logger;
19+
import org.slf4j.LoggerFactory;
20+
1421
public class Windows implements NativeDesktop {
22+
private static final Logger LOGGER = LoggerFactory.getLogger(Windows.class);
23+
1524
private static final String DEFAULT_EXECUTABLE_EXTENSION = ".exe";
1625

1726
@Override
@@ -70,6 +79,21 @@ public Path getApplicationDirectory() {
7079
return getUserDirectory();
7180
}
7281

82+
@Override
83+
public Path getDefaultFileChooserDirectory() {
84+
try {
85+
try {
86+
return Path.of(Shell32Util.getKnownFolderPath(KnownFolders.FOLDERID_Documents));
87+
} catch (UnsatisfiedLinkError e) {
88+
// Windows Vista or earlier
89+
return Path.of(Shell32Util.getFolderPath(ShlObj.CSIDL_MYDOCUMENTS));
90+
}
91+
} catch (Win32Exception e) {
92+
LOGGER.error("Error accessing folder", e);
93+
return Path.of(System.getProperty("user.home"));
94+
}
95+
}
96+
7397
@Override
7498
public void openFileWithApplication(String filePath, String application) throws IOException {
7599
new ProcessBuilder(Path.of(application).toString(), Path.of(filePath).toString()).start();

src/main/java/org/jabref/gui/preferences/linkedfiles/LinkedFilesTabViewModel.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ public LinkedFilesTabViewModel(DialogService dialogService, PreferencesService p
7474
@Override
7575
public void setValues() {
7676
// External files preferences / Attached files preferences / File preferences
77-
mainFileDirectoryProperty.setValue(filePreferences.getFileDirectory().orElse(Path.of("")).toString());
77+
mainFileDirectoryProperty.setValue(filePreferences.getMainFileDirectory().orElse(Path.of("")).toString());
7878
useMainFileDirectoryProperty.setValue(!filePreferences.shouldStoreFilesRelativeToBibFile());
7979
useBibLocationAsPrimaryProperty.setValue(filePreferences.shouldStoreFilesRelativeToBibFile());
8080
fulltextIndex.setValue(filePreferences.shouldFulltextIndexLinkedFiles());

src/main/java/org/jabref/model/database/BibDatabaseContext.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,7 @@ public List<Path> getFileDirectories(FilePreferences preferences) {
171171
});
172172
} else {
173173
// Main file directory
174-
preferences.getFileDirectory().ifPresent(fileDirs::add);
174+
preferences.getMainFileDirectory().ifPresent(fileDirs::add);
175175
}
176176

177177
return fileDirs.stream().map(Path::toAbsolutePath).collect(Collectors.toList());

src/main/java/org/jabref/preferences/FilePreferences.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ public String getUser() {
5656
return user.getValue();
5757
}
5858

59-
public Optional<Path> getFileDirectory() {
59+
public Optional<Path> getMainFileDirectory() {
6060
if (StringUtil.isBlank(mainFileDirectory.getValue())) {
6161
return Optional.empty();
6262
} else {

src/main/java/org/jabref/preferences/JabRefPreferences.java

+9-15
Original file line numberDiff line numberDiff line change
@@ -949,6 +949,14 @@ public List<String> getStringList(String key) {
949949
return convertStringToList(get(key));
950950
}
951951

952+
/**
953+
* Returns a Path
954+
*/
955+
private Path getPath(String key, Path defaultValue) {
956+
String rawPath = get(key);
957+
return StringUtil.isNotBlank(rawPath) ? Path.of(rawPath) : defaultValue;
958+
}
959+
952960
/**
953961
* Clear all preferences.
954962
*
@@ -2186,20 +2194,6 @@ public FieldWriterPreferences getFieldWriterPreferences() {
21862194
getFieldContentParserPreferences());
21872195
}
21882196

2189-
/**
2190-
* Ensures that the main file directory is a non-empty String.
2191-
* The directory is <emph>NOT</emph> created, because creation of the directory is the task of the respective methods.
2192-
*
2193-
* @param originalDirectory the directory as configured
2194-
*/
2195-
private String determineMainFileDirectory(String originalDirectory) {
2196-
if ((originalDirectory != null) && !originalDirectory.isEmpty()) {
2197-
// A non-empty directory is kept
2198-
return originalDirectory;
2199-
}
2200-
return JabRefDesktop.getDefaultFileChooserDirectory();
2201-
}
2202-
22032197
@Override
22042198
public FilePreferences getFilePreferences() {
22052199
if (Objects.nonNull(filePreferences)) {
@@ -2208,7 +2202,7 @@ public FilePreferences getFilePreferences() {
22082202

22092203
filePreferences = new FilePreferences(
22102204
getInternalPreferences().getUser(),
2211-
determineMainFileDirectory(get(MAIN_FILE_DIRECTORY)),
2205+
getPath(MAIN_FILE_DIRECTORY, JabRefDesktop.getNativeDesktop().getDefaultFileChooserDirectory()).toString(),
22122206
getBoolean(STORE_RELATIVE_TO_BIB),
22132207
get(IMPORT_FILENAMEPATTERN),
22142208
get(IMPORT_FILEDIRPATTERN),

src/test/java/org/jabref/logic/pdf/search/indexing/DocumentReaderTest.java

+2-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
package org.jabref.logic.pdf.search.indexing;
22

3-
import java.io.IOException;
43
import java.nio.file.Path;
54
import java.util.Collections;
65
import java.util.List;
@@ -35,12 +34,12 @@ public void setup() {
3534
when(databaseContext.getFileDirectories(Mockito.any())).thenReturn(Collections.singletonList(Path.of("src/test/resources/pdfs")));
3635
this.filePreferences = mock(FilePreferences.class);
3736
when(filePreferences.getUser()).thenReturn("test");
38-
when(filePreferences.getFileDirectory()).thenReturn(Optional.empty());
37+
when(filePreferences.getMainFileDirectory()).thenReturn(Optional.empty());
3938
when(filePreferences.shouldStoreFilesRelativeToBibFile()).thenReturn(true);
4039
}
4140

4241
@Test
43-
public void unknownFileTestShouldReturnEmptyList() throws IOException {
42+
public void unknownFileTestShouldReturnEmptyList() {
4443
// given
4544
BibEntry entry = new BibEntry();
4645
entry.setFiles(Collections.singletonList(new LinkedFile("Wrong path", "NOT_PRESENT.pdf", "Type")));

src/test/java/org/jabref/model/database/BibDatabaseContextTest.java

+2-3
Original file line numberDiff line numberDiff line change
@@ -94,10 +94,9 @@ void getFileDirectoriesWithMetadata() {
9494
@Test
9595
void getUserFileDirectoryIfAllAreEmpty() {
9696
when(fileDirPrefs.shouldStoreFilesRelativeToBibFile()).thenReturn(false);
97+
Path userDirJabRef = JabRefDesktop.getNativeDesktop().getDefaultFileChooserDirectory();
9798

98-
Path userDirJabRef = Path.of(JabRefDesktop.getDefaultFileChooserDirectory(), "JabRef");
99-
100-
when(fileDirPrefs.getFileDirectory()).thenReturn(Optional.of(userDirJabRef));
99+
when(fileDirPrefs.getMainFileDirectory()).thenReturn(Optional.of(userDirJabRef));
101100
BibDatabaseContext database = new BibDatabaseContext();
102101
database.setDatabasePath(Path.of("biblio.bib"));
103102
assertEquals(Collections.singletonList(userDirJabRef), database.getFileDirectories(fileDirPrefs));

0 commit comments

Comments
 (0)