Bug 1154277

Summary: [rfe] follow xdg base dir
Product: [Fedora] Fedora Reporter: Rahul Sundaram <metherid>
Component: java-1.8.0-openjdkAssignee: Andrew John Hughes <ahughes>
Status: ASSIGNED --- QA Contact: Fedora Extras Quality Assurance <extras-qa>
Severity: unspecified Docs Contact:
Priority: unspecified    
Version: rawhideCC: ahughes, dbhole, fedora, jvanek, mamedesigor, omajid, wsxy162
Target Milestone: ---   
Target Release: ---   
Hardware: Unspecified   
OS: Unspecified   
Whiteboard:
Fixed In Version: Doc Type: Bug Fix
Doc Text:
Story Points: ---
Clone Of: Environment:
Last Closed: Type: Bug
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Embargoed:

Description Rahul Sundaram 2014-10-18 09:48:26 UTC
Description of problem:

I see Java places some configuration files in .java.  In my system, I have

.java/fonts/1.8.0_25/fcinfo-1-mether-RedHat-21-en.properties

Please fix Java to follow xdg base dir spec.  IcedTea has already adopted it (based on my earlier bug report)

References:

http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html

A non spec rationale

http://ploum.net/207-modify-your-application-to-use-xdg-folders/

The relevant API's (glib specific but equivalents are available in other places as well)

https://developer.gnome.org/glib/stable/glib-Miscellaneous-Utility-Functions.html#g-get-user-cache-dir
https://developer.gnome.org/glib/stable/glib-Miscellaneous-Utility-Functions.html#g-get-user-config-dir
https://developer.gnome.org/glib/stable/glib-Miscellaneous-Utility-Functions.html#g-get-user-data-dir

Comment 1 jiri vanek 2014-10-21 09:32:51 UTC
No meeter how I sympathize eith xdg,  this is nearly impossible to fix. Openjdk is supposed to run on windows. I can not simply  forward any patch which will move windows to free desktop specification.  Also I feel quite uneasy to add any spec-only patch for this. Icedtea is linux-only, so it can do such a things without problems.

Comment 2 Rahul Sundaram 2014-10-21 11:34:48 UTC
The glib API I references already handles Windows vs Linux by placing files in the appropriate location.  The configuration paths are already different between these platforms anyway

Comment 3 Andrew John Hughes 2014-10-21 14:39:22 UTC
I'm not aware of any change for this in IcedTea either, and it's certainly not "linux-only". We've had people build it on both *BSD and Windows in the past.

Comment 4 Rahul Sundaram 2014-10-21 14:51:56 UTC
IcedTea did change based on my earlier bug report.  C.f.

https://bugzilla.redhat.com/show_bug.cgi?id=947647

Also,  I don't see why the xdg spec wouldn't apply to any Linux, BSD etc.  Windows already has a very different path and the glib API handles those differences just fine.

Comment 5 Andrew John Hughes 2017-10-13 17:32:15 UTC
That's IcedTea-Web, not IcedTea.

The Windows argument is spurious in the case of these .fcinfo files that I wasn't aware of until this bug report. These are fontconfig configuration files and are created in POSIX-specific code. The directories are also specific to each update of OpenJDK, so moving it doesn't really need to be backwards-compatible either.

So I think it's possible to clean this up. However, it should be noted that '.java' is used elsewhere as the default for the user preference root. This can be overridden manually by setting java.util.prefs.userRoot but the default should really be fixed there too.

The solution is probably to obtain a user preference directory from native code, and fall back on the old version if this is unavailable. There is precedent for using GLib already in the POSIX code.

Comment 6 Rahul Sundaram 2020-04-14 23:35:58 UTC
I still see this with the latest version of OpenJDK

Users could override it: export _JAVA_OPTIONS=-Djava.util.prefs.userRoot="$XDG_CONFIG_HOME"/java but I am hoping we can update the default handling

Comment 7 igrmm 2020-06-18 02:04:29 UTC
(In reply to Rahul Sundaram from comment #6)
> I still see this with the latest version of OpenJDK
> 
> Users could override it: export
> _JAVA_OPTIONS=-Djava.util.prefs.userRoot="$XDG_CONFIG_HOME"/java but I am
> hoping we can update the default handling

This doesnt work for me. The ".userPrefs" is created in "$XDG_CONFIG_HOME"/java, but java still creates $HOME/.java/fonts

Comment 8 Zephyr Lykos 2025-06-17 18:40:06 UTC
I found a patch from <https://github.com/noahvogt/java-openjdk-xdg-aur>:

diff --git a/src/java.desktop/unix/classes/sun/font/FcFontConfiguration.java b/src/java.desktop/unix/classes/sun/font/FcFontConfiguration.java
index 328e2454842..db50244c095 100644
--- a/src/java.desktop/unix/classes/sun/font/FcFontConfiguration.java
+++ b/src/java.desktop/unix/classes/sun/font/FcFontConfiguration.java
@@ -372,7 +372,29 @@ private File getFcInfoFile() {
             String userDir = System.getProperty("user.home");
             String version = System.getProperty("java.version");
             String fs = File.separator;
-            String dir = userDir+fs+".java"+fs+"fonts"+fs+version;
+            String dir;
+
+            /* On Linux systems, put the font config into 
+             * ${XDG_CONFIG_HOME:-$HOME/.config}/java/fonts to follow
+             * the XDG Base Directory Specification.
+             */
+            if (System.getProperty("os.name").equals("Linux")) {
+                /* assume homedir can be found, which the jvm already does */
+                String xdgDefaultConfigHome = System.getenv("HOME")+"/.config";
+                String xdgConfigHomeEnvVar = "XDG_CONFIG_HOME";
+                String xdgConfigDir;
+
+                String xdgSetConfigDir = System.getenv(xdgConfigHomeEnvVar);
+
+                if (xdgSetConfigDir == null)
+                    xdgConfigDir = xdgDefaultConfigHome;
+                else
+                    xdgConfigDir = xdgSetConfigDir;
+
+                dir = xdgConfigDir+"/java/fonts/"+version;
+            } else {
+                dir = userDir+fs+".java"+fs+"fonts"+fs+version;
+            }
             Locale locale = SunToolkit.getStartupLocale();
             String lang = locale.getLanguage();
             String country = locale.getCountry();

I asked the author to clarify the copyright info so it could be submitted to upstream: <https://github.com/noahvogt/java-openjdk-xdg-aur/issues/1>

We could apply this to Fedora's OpenJDK build first, and wait for the author's copyright clarification & upstream comment in the meanwhile.

Comment 9 Zephyr Lykos 2025-06-17 18:56:35 UTC
PATCH v2: adjusted to OpenJDK code style, apply to all Unix platforms, handle invalid paths

diff --git a/src/java.desktop/unix/classes/sun/font/FcFontConfiguration.java b/src/java.desktop/unix/classes/sun/font/FcFontConfiguration.java
index 328e2454842..d2e2d383235 100644
--- a/src/java.desktop/unix/classes/sun/font/FcFontConfiguration.java
+++ b/src/java.desktop/unix/classes/sun/font/FcFontConfiguration.java
@@ -372,7 +372,18 @@ private File getFcInfoFile() {
             String userDir = System.getProperty("user.home");
             String version = System.getProperty("java.version");
             String fs = File.separator;
-            String dir = userDir+fs+".java"+fs+"fonts"+fs+version;
+
+            // https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html
+            String xdgConfigDir;
+            String xdgSetConfigDir = System.getenv("XDG_CONFIG_HOME");
+
+            if (xdgSetConfigDir == null || !xdgSetConfigDir.startsWith("/")) {
+                xdgConfigDir = userDir+fs+".config";
+            } else {
+                xdgConfigDir = xdgSetConfigDir;
+            }
+
+            String dir = xdgConfigDir+fs+"java"+fs+"fonts"+fs+version;
             Locale locale = SunToolkit.getStartupLocale();
             String lang = locale.getLanguage();
             String country = locale.getCountry();
diff --git a/src/java.prefs/unix/classes/java/util/prefs/FileSystemPreferences.java b/src/java.prefs/unix/classes/java/util/prefs/FileSystemPreferences.java
index 681abec46c3..65dcf677150 100644
--- a/src/java.prefs/unix/classes/java/util/prefs/FileSystemPreferences.java
+++ b/src/java.prefs/unix/classes/java/util/prefs/FileSystemPreferences.java
@@ -109,9 +109,19 @@ static Preferences getUserRoot() {
     }
 
     private static void setupUserRoot() {
+        String xdgConfigDir;
+
+        // https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html
+        String xdgSetConfigDir = System.getenv("XDG_CONFIG_HOME");
+        if (xdgSetConfigDir == null || !xdgSetConfigDir.startsWith("/")) {
+            xdgConfigDir = System.getProperty("user.home") + "/.config";
+        } else {
+            xdgConfigDir = xdgSetConfigDir;
+        }
+
         userRootDir =
-              new File(System.getProperty("java.util.prefs.userRoot",
-                      System.getProperty("user.home")), ".java/.userPrefs");
+            new File(System.getProperty("java.util.prefs.userRoot",
+            xdgConfigDir), "java/userPrefs");
         // Attempt to create root dir if it does not yet exist.
         if (!userRootDir.exists()) {
             if (userRootDir.mkdirs()) {