diff --git a/api/src/main/java/jakarta/activation/MailcapCommandMap.java b/api/src/main/java/jakarta/activation/MailcapCommandMap.java index 831cb31..041c3a5 100644 --- a/api/src/main/java/jakarta/activation/MailcapCommandMap.java +++ b/api/src/main/java/jakarta/activation/MailcapCommandMap.java @@ -27,26 +27,31 @@ /** * MailcapCommandMap extends the CommandMap * abstract class. It implements a CommandMap whose configuration - * is based on jakarta.mailcap files + * is based on mailcap configuration files * (RFC 1524). * The MailcapCommandMap can be configured both programmatically * and via configuration files. *

* Mailcap file search order:

* The MailcapCommandMap looks in various places in the user's - * system for jakarta.mailcap file entries. When requests are made + * system for mailcap file entries. When requests are made * to search for commands in the MailcapCommandMap, it searches - * jakarta.mailcap files in the following order: + * both legacy (mailcap) and Jakarta-prefixed + * (jakarta.mailcap) files in the following order: *

    - *
  1. Programatically added entries to the MailcapCommandMap instance. - *
  2. The file .jakarta.mailcap in the user's home directory. - *
  3. The file jakarta.mailcap in the Java runtime. - *
  4. The file or resources named META-INF/jakarta.mailcap. - *
  5. The file or resource named META-INF/jakarta.mailcap.default - * (usually found only in the activation.jar file). + *
  6. Programmatically added entries to the MailcapCommandMap instance. + *
  7. The file .mailcap or .jakarta.mailcap + * in the user's home directory. + *
  8. The file mailcap or jakarta.mailcap + * in the Java runtime. + *
  9. The file or resources named META-INF/mailcap or + * META-INF/jakarta.mailcap. + *
  10. The file or resource named META-INF/mailcap.default or + * META-INF/jakarta.mailcap.default + * (usually found only in the activation.jar file). *
*

- * (The current implementation looks for the jakarta.mailcap file + * (The current implementation looks for the mailcap file * in the Java runtime in the directory java.home/conf * if it exists, and otherwise in the directory * java.home/lib, where java.home is the value @@ -55,7 +60,7 @@ *

* Mailcap file format:

* - * Mailcap files must conform to the jakarta.mailcap + * Mailcap files must conform to the mailcap * file specification (RFC 1524, A User Agent Configuration Mechanism * For Multimedia Mail Format Information). * The file format consists of entries corresponding to @@ -63,10 +68,10 @@ * specifies applications for clients to use when they * themselves cannot operate on the specified MIME type. The * MailcapCommandMap extends this specification by using a parameter mechanism - * in jakarta.mailcap files that allows JavaBeans(tm) components to be specified as + * in mailcap files that allows JavaBeans(tm) components to be specified as * corresponding to particular commands for a MIME type.

* - * When a jakarta.mailcap file is + * When a mailcap file is * parsed, the MailcapCommandMap recognizes certain parameter signatures, * specifically those parameter names that begin with x-java-. * The MailcapCommandMap uses this signature to find @@ -92,7 +97,7 @@ * view command would only be used if a non-fallback view command for * the MIME type could not be found.

* - * MailcapCommandMap aware jakarta.mailcap files have the + * MailcapCommandMap aware mailcap files have the * following general form:

* * # Comments begin with a '#' and continue to the end of the line.
@@ -102,8 +107,8 @@ * # and a parameter list looks like:
* text/plain; ; x-java-view=com.sun.TextViewer; x-java-edit=com.sun.TextEdit *
- * # Note that jakarta.mailcap entries that do not contain 'x-java' parameters
- * # and comply to RFC 1524 are simply ignored:
+ * # Note that entries that do not contain 'x-java' parameters
+ * # and comply with RFC 1524 are simply ignored:
* image/gif; /usr/dt/bin/sdtimage %s
* *
@@ -149,12 +154,11 @@ public MailcapCommandMap() { String user_home = System.getProperty("user.home"); if (user_home != null) { - String[] paths = new String[] {user_home + File.separator + ".jakarta.mailcap", user_home + File.separator + ".mailcap"}; + String[] paths = new String[] {user_home + File.separator + ".mailcap", user_home + File.separator + ".jakarta.mailcap"}; for (String path : paths) { - mf = loadFile(path); + mf = loadFile(path); if (mf != null) { - dbv.add(mf); - break; + dbv.add(mf); } } } @@ -165,12 +169,11 @@ public MailcapCommandMap() { try { // check system's home if (confDir != null) { - String[] confs = new String[] {"jakarta.mailcap", "mailcap"}; + String[] confs = new String[] {"mailcap", "jakarta.mailcap"}; for (String conf : confs) { mf = loadFile(confDir + conf); if (mf != null) { - dbv.add(mf); - break; + dbv.add(mf); } } } @@ -179,13 +182,11 @@ public MailcapCommandMap() { LogSupport.log("MailcapCommandMap: load JAR"); // load from the app's jar file - loadAllResources(dbv, "META-INF/jakarta.mailcap", "META-INF/mailcap"); + loadAllResources(dbv, "META-INF/mailcap", "META-INF/jakarta.mailcap"); LogSupport.log("MailcapCommandMap: load DEF"); - mf = loadResource("/META-INF/jakarta.mailcap.default", "/META-INF/mailcap.default"); - if (mf != null) - dbv.add(mf); + dbv.addAll(loadResource("/META-INF/mailcap.default", "/META-INF/jakarta.mailcap.default")); DB = new MailcapRegistry[dbv.size()]; DB = dbv.toArray(DB); @@ -194,31 +195,32 @@ public MailcapCommandMap() { /** * Load from the named resource. */ - private MailcapRegistry loadResource(String ... names) { + private List loadResource(String ... names) { + List registry = new ArrayList<>(); for (String name : names) { - try (InputStream clis = this.getClass().getResourceAsStream(name)) { - if (clis != null) { - MailcapRegistry mf = getImplementation().getByInputStream(clis); - if (LogSupport.isLoggable()) - LogSupport.log("MailcapCommandMap: successfully loaded " + - "jakarta.mailcap file: " + name); - return mf; - } else { + try (InputStream clis = this.getClass().getResourceAsStream(name)) { + if (clis != null) { + MailcapRegistry mf = getImplementation().getByInputStream(clis); + if (LogSupport.isLoggable()) + LogSupport.log("MailcapCommandMap: successfully loaded " + + "mailcap file: " + name); + registry.add(mf); + } else { + if (LogSupport.isLoggable()) + LogSupport.log("MailcapCommandMap: not loading " + + "mailcap file: " + name); + } + } catch (IOException | SecurityException e) { if (LogSupport.isLoggable()) - LogSupport.log("MailcapCommandMap: not loading " + - "jakarta.mailcap file: " + name); - } - } catch (IOException | SecurityException e) { - if (LogSupport.isLoggable()) - LogSupport.log("MailcapCommandMap: can't load " + name, e); - } catch (NoSuchElementException | IllegalStateException | ServiceConfigurationError e) { - if (LogSupport.isLoggable()) { - LogSupport.log("Cannot find or load an implementation for MailcapRegistryProvider. " + - "MailcapRegistry: can't load " + name, e); + LogSupport.log("MailcapCommandMap: can't load " + name, e); + } catch (NoSuchElementException | IllegalStateException | ServiceConfigurationError e) { + if (LogSupport.isLoggable()) { + LogSupport.log("Cannot find or load an implementation for MailcapRegistryProvider. " + + "MailcapRegistry: can't load " + name, e); + } } } - } - return null; + return registry; } /** @@ -227,57 +229,55 @@ private MailcapRegistry loadResource(String ... names) { private void loadAllResources(List v, String ... names) { boolean anyLoaded = false; for (String name : names) { - try { - URL[] urls; - ClassLoader cld = null; - // First try the "application's" class loader. - cld = Thread.currentThread().getContextClassLoader(); - if (cld == null) - cld = this.getClass().getClassLoader(); - if (cld != null) - urls = SecuritySupport.getResources(cld, name); - else - urls = SecuritySupport.getSystemResources(name); - if (urls != null) { - if (LogSupport.isLoggable()) - LogSupport.log("MailcapCommandMap: getResources"); - for (int i = 0; i < urls.length; i++) { - URL url = urls[i]; + try { + URL[] urls; + ClassLoader cld = null; + // First try the "application's" class loader. + cld = Thread.currentThread().getContextClassLoader(); + if (cld == null) + cld = this.getClass().getClassLoader(); + if (cld != null) + urls = SecuritySupport.getResources(cld, name); + else + urls = SecuritySupport.getSystemResources(name); + if (urls != null) { if (LogSupport.isLoggable()) - LogSupport.log("MailcapCommandMap: URL " + url); - try (InputStream clis = url.openStream()) { - if (clis != null) { - v.add(getImplementation().getByInputStream(clis)); - anyLoaded = true; - if (LogSupport.isLoggable()) - LogSupport.log("MailcapCommandMap: " + - "successfully loaded " + - "jakarta.mailcap file from URL: " + - url); - } else { - if (LogSupport.isLoggable()) - LogSupport.log("MailcapCommandMap: " + - "not loading jakarta.mailcap " + - "file from URL: " + url); - } - } catch (IOException | SecurityException ioex) { + LogSupport.log("MailcapCommandMap: getResources"); + for (int i = 0; i < urls.length; i++) { + URL url = urls[i]; if (LogSupport.isLoggable()) - LogSupport.log("MailcapCommandMap: can't load " + - url, ioex); - } catch (NoSuchElementException | IllegalStateException | ServiceConfigurationError e) { - if (LogSupport.isLoggable()) { - LogSupport.log("Cannot find or load an implementation for MailcapRegistryProvider. " + - "MailcapRegistry: can't load " + name, e); + LogSupport.log("MailcapCommandMap: URL " + url); + try (InputStream clis = url.openStream()) { + if (clis != null) { + v.add(getImplementation().getByInputStream(clis)); + anyLoaded = true; + if (LogSupport.isLoggable()) + LogSupport.log("MailcapCommandMap: " + + "successfully loaded " + + "mailcap file from URL: " + + url); + } else { + if (LogSupport.isLoggable()) + LogSupport.log("MailcapCommandMap: " + + "not loading mailcap " + + "file from URL: " + url); + } + } catch (IOException | SecurityException ioex) { + if (LogSupport.isLoggable()) + LogSupport.log("MailcapCommandMap: can't load " + + url, ioex); + } catch (NoSuchElementException | IllegalStateException | ServiceConfigurationError e) { + if (LogSupport.isLoggable()) { + LogSupport.log("Cannot find or load an implementation for MailcapRegistryProvider. " + + "MailcapRegistry: can't load " + name, e); + } } } } - // Even if nothing was loaded, we stop it because resources were found. - break; + } catch (Exception ex) { + if (LogSupport.isLoggable()) + LogSupport.log("MailcapCommandMap: can't load " + name, ex); } - } catch (Exception ex) { - if (LogSupport.isLoggable()) - LogSupport.log("MailcapCommandMap: can't load " + name, ex); - } } // if failed to load anything, fall back to old technique, just in case @@ -288,9 +288,7 @@ private void loadAllResources(List v, String ... names) { for (int i = 0; i < names.length; i++) { resources[i] = "/" + names[i]; } - MailcapRegistry mf = loadResource(resources); - if (mf != null) - v.add(mf); + v.addAll(loadResource(resources)); } } diff --git a/api/src/main/java/jakarta/activation/MailcapRegistry.java b/api/src/main/java/jakarta/activation/MailcapRegistry.java index 29165f7..26c80ad 100644 --- a/api/src/main/java/jakarta/activation/MailcapRegistry.java +++ b/api/src/main/java/jakarta/activation/MailcapRegistry.java @@ -52,7 +52,7 @@ public interface MailcapRegistry { Map> getMailcapFallbackList(String mime_type); /** - * Return all the MIME types known to this jakarta.mailcap file. + * Return all the MIME types known to this mailcap file. * * @return a String array of the MIME types */ @@ -67,7 +67,7 @@ public interface MailcapRegistry { String[] getNativeCommands(String mime_type); /** - * appendToMailcap: Append to this Mailcap DB, use the jakarta.mailcap + * appendToMailcap: Append to this Mailcap DB, use the mailcap * format: * Comment == "# comment string" * Entry == "mimetype; javabeanclass" @@ -76,7 +76,7 @@ public interface MailcapRegistry { * # this is a comment * image/gif jaf.viewers.ImageViewer * - * @param mail_cap the jakarta.mailcap string + * @param mail_cap the mailcap string */ void appendToMailcap(String mail_cap); } diff --git a/api/src/main/java/jakarta/activation/MimeTypeRegistry.java b/api/src/main/java/jakarta/activation/MimeTypeRegistry.java index d2adf85..0438e1e 100644 --- a/api/src/main/java/jakarta/activation/MimeTypeRegistry.java +++ b/api/src/main/java/jakarta/activation/MimeTypeRegistry.java @@ -48,7 +48,7 @@ default String getMIMETypeString(String file_ext) { /** * Appends string of entries to the types registry * - * @param mime_types the jakarta.mime.types string + * @param mime_types the mime.types and jakarta.mime.types string */ void appendToRegistry(String mime_types); } \ No newline at end of file diff --git a/api/src/main/java/jakarta/activation/MimetypesFileTypeMap.java b/api/src/main/java/jakarta/activation/MimetypesFileTypeMap.java index ed86773..e5a2411 100644 --- a/api/src/main/java/jakarta/activation/MimetypesFileTypeMap.java +++ b/api/src/main/java/jakarta/activation/MimetypesFileTypeMap.java @@ -17,29 +17,36 @@ import java.io.InputStream; import java.net.URL; import java.nio.file.Path; +import java.util.ArrayList; +import java.util.List; import java.util.NoSuchElementException; import java.util.ServiceConfigurationError; import java.util.Vector; /** * This class extends FileTypeMap and provides data typing of files - * via their file extension. It uses the .jakarta.mime.types format.

+ * via their file extension. It uses the mime.types format.

* * MIME types file search order:

* The MimetypesFileTypeMap looks in various places in the user's * system for MIME types file entries. When requests are made * to search for MIME types in the MimetypesFileTypeMap, it searches - * MIME types files in the following order: + * both legacy (mime.types) and Jakarta-prefixed + * (jakarta.mime.types) files in the following order: *

    *
  1. Programmatically added entries to the MimetypesFileTypeMap instance. - *
  2. The file .jakarta.mime.types in the user's home directory. - *
  3. The file jakarta.mime.types in the Java runtime. - *
  4. The file or resources named META-INF/jakarta.mime.types. - *
  5. The file or resource named META-INF/jakarta.mimetypes.default - * (usually found only in the activation.jar file). + *
  6. The file .mime.types and .jakarta.mime.types + * in the user's home directory. + *
  7. The file mime.types and jakarta.mime.types + * in the Java runtime. + *
  8. The file or resources named META-INF/mime.types and + * META-INF/jakarta.mime.types. + *
  9. The file or resource named META-INF/mimetypes.default and + * META-INF/jakarta.mimetypes.default + * (usually found only in the activation.jar file). *
*

- * (The current implementation looks for the jakarta.mime.types file + * (The current implementation looks for the MIME types file * in the Java runtime in the directory java.home/conf * if it exists, and otherwise in the directory * java.home/lib, where java.home is the value @@ -99,13 +106,12 @@ public MimetypesFileTypeMap() { String user_home = System.getProperty("user.home"); if (user_home != null) { - String[] paths = new String[] {user_home + File.separator + ".jakarta.mime.types", user_home + File.separator + ".mime.types"}; + String[] paths = new String[] {user_home + File.separator + ".mime.types", user_home + File.separator + ".jakarta.mime.types"}; for (String path : paths) { - mf = loadFile(path); + mf = loadFile(path); if (mf != null) { - dbv.addElement(mf); - break; - } + dbv.addElement(mf); + } } } } catch (SecurityException ex) { @@ -117,14 +123,13 @@ public MimetypesFileTypeMap() { try { // check system's home if (confDir != null) { - String[] confs = new String[] {"jakarta.mime.types", "mime.types"}; + String[] confs = new String[] {"mime.types", "jakarta.mime.types"}; for (String conf : confs) { mf = loadFile(confDir + conf); if (mf != null) { - dbv.addElement(mf); - break; + dbv.addElement(mf); } - } + } } } catch (SecurityException ex) { if (LogSupport.isLoggable()) @@ -136,10 +141,7 @@ public MimetypesFileTypeMap() { loadAllResources(dbv, "META-INF/jakarta.mime.types", "META-INF/mime.types"); LogSupport.log("MimetypesFileTypeMap: load DEF"); - mf = loadResource("/META-INF/jakarta.mimetypes.default", "/META-INF/mimetypes.default"); - - if (mf != null) - dbv.addElement(mf); + dbv.addAll(loadResource("/META-INF/mimetypes.default", "/META-INF/jakarta.mimetypes.default")); DB = new MimeTypeRegistry[dbv.size()]; dbv.copyInto(DB); @@ -148,41 +150,42 @@ public MimetypesFileTypeMap() { /** * Load from the named resource. */ - private MimeTypeRegistry loadResource(String ... names) { + private List loadResource(String ... names) { + List registry = new ArrayList<>(); for (String name : names) { - InputStream clis = null; - try { - clis = this.getClass().getResourceAsStream(name); - if (clis != null) { - MimeTypeRegistry mf = getImplementation().getByInputStream(clis); - if (LogSupport.isLoggable()) - LogSupport.log("MimetypesFileTypeMap: successfully " + - "loaded mime types file: " + name); - return mf; - } else { - if (LogSupport.isLoggable()) - LogSupport.log("MimetypesFileTypeMap: not loading " + - "mime types file: " + name); - } - } catch (IOException | SecurityException e) { - if (LogSupport.isLoggable()) - LogSupport.log("MimetypesFileTypeMap: can't load " + name, e); - } catch (NoSuchElementException | IllegalStateException | ServiceConfigurationError e) { - if (LogSupport.isLoggable()) { - LogSupport.log("Cannot find or load an implementation for MimeTypeRegistryProvider." + - "MimeTypeRegistry: can't load " + name, e); - } - } finally { + InputStream clis = null; try { - if (clis != null) - clis.close(); - } catch (IOException ex) { + clis = this.getClass().getResourceAsStream(name); + if (clis != null) { + MimeTypeRegistry mf = getImplementation().getByInputStream(clis); + if (LogSupport.isLoggable()) + LogSupport.log("MimetypesFileTypeMap: successfully " + + "loaded mime types file: " + name); + registry.add(mf); + } else { + if (LogSupport.isLoggable()) + LogSupport.log("MimetypesFileTypeMap: not loading " + + "mime types file: " + name); + } + } catch (IOException | SecurityException e) { if (LogSupport.isLoggable()) - LogSupport.log("InputStream cannot be close for " + name, ex); + LogSupport.log("MimetypesFileTypeMap: can't load " + name, e); + } catch (NoSuchElementException | IllegalStateException | ServiceConfigurationError e) { + if (LogSupport.isLoggable()) { + LogSupport.log("Cannot find or load an implementation for MimeTypeRegistryProvider." + + "MimeTypeRegistry: can't load " + name, e); + } + } finally { + try { + if (clis != null) + clis.close(); + } catch (IOException ex) { + if (LogSupport.isLoggable()) + LogSupport.log("InputStream cannot be close for " + name, ex); + } } } - } - return null; + return registry; } /** @@ -191,68 +194,66 @@ private MimeTypeRegistry loadResource(String ... names) { private void loadAllResources(Vector v, String ... names) { boolean anyLoaded = false; for (String name : names) { - try { - URL[] urls; - ClassLoader cld = null; - // First try the "application's" class loader. - cld = Thread.currentThread().getContextClassLoader(); - if (cld == null) - cld = this.getClass().getClassLoader(); - if (cld != null) - urls = SecuritySupport.getResources(cld, name); - else - urls = SecuritySupport.getSystemResources(name); - if (urls != null) { - if (LogSupport.isLoggable()) - LogSupport.log("MimetypesFileTypeMap: getResources"); - for (int i = 0; i < urls.length; i++) { - URL url = urls[i]; - InputStream clis = null; + try { + URL[] urls; + ClassLoader cld = null; + // First try the "application's" class loader. + cld = Thread.currentThread().getContextClassLoader(); + if (cld == null) + cld = this.getClass().getClassLoader(); + if (cld != null) + urls = SecuritySupport.getResources(cld, name); + else + urls = SecuritySupport.getSystemResources(name); + if (urls != null) { if (LogSupport.isLoggable()) - LogSupport.log("MimetypesFileTypeMap: URL " + url); - try { - clis = url.openStream(); - if (clis != null) { - v.addElement( - getImplementation().getByInputStream(clis) - ); - anyLoaded = true; - if (LogSupport.isLoggable()) - LogSupport.log("MimetypesFileTypeMap: " + - "successfully loaded " + - "mime types from URL: " + url); - } else { - if (LogSupport.isLoggable()) - LogSupport.log("MimetypesFileTypeMap: " + - "not loading " + - "mime types from URL: " + url); - } - } catch (IOException | SecurityException ioex) { + LogSupport.log("MimetypesFileTypeMap: getResources"); + for (int i = 0; i < urls.length; i++) { + URL url = urls[i]; + InputStream clis = null; if (LogSupport.isLoggable()) - LogSupport.log("MimetypesFileTypeMap: can't load " + - url, ioex); - } catch (NoSuchElementException | IllegalStateException | ServiceConfigurationError e) { - if (LogSupport.isLoggable()) { - LogSupport.log("Cannot find or load an implementation for MimeTypeRegistryProvider." + - "MimeTypeRegistry: can't load " + url, e); - } - } finally { + LogSupport.log("MimetypesFileTypeMap: URL " + url); try { - if (clis != null) - clis.close(); - } catch (IOException cex) { + clis = url.openStream(); + if (clis != null) { + v.addElement( + getImplementation().getByInputStream(clis) + ); + anyLoaded = true; + if (LogSupport.isLoggable()) + LogSupport.log("MimetypesFileTypeMap: " + + "successfully loaded " + + "mime types from URL: " + url); + } else { + if (LogSupport.isLoggable()) + LogSupport.log("MimetypesFileTypeMap: " + + "not loading " + + "mime types from URL: " + url); + } + } catch (IOException | SecurityException ioex) { if (LogSupport.isLoggable()) - LogSupport.log("InputStream cannot be close for " + name, cex); + LogSupport.log("MimetypesFileTypeMap: can't load " + + url, ioex); + } catch (NoSuchElementException | IllegalStateException | ServiceConfigurationError e) { + if (LogSupport.isLoggable()) { + LogSupport.log("Cannot find or load an implementation for MimeTypeRegistryProvider." + + "MimeTypeRegistry: can't load " + url, e); + } + } finally { + try { + if (clis != null) + clis.close(); + } catch (IOException cex) { + if (LogSupport.isLoggable()) + LogSupport.log("InputStream cannot be close for " + name, cex); + } } } } + } catch (Exception ex) { + if (LogSupport.isLoggable()) + LogSupport.log("MimetypesFileTypeMap: can't load " + name, ex); } - // Even if nothing was loaded, we stop it because resources were found. - break; - } catch (Exception ex) { - if (LogSupport.isLoggable()) - LogSupport.log("MimetypesFileTypeMap: can't load " + name, ex); - } } // if failed to load anything, fall back to old technique, just in case if (!anyLoaded) { @@ -261,9 +262,7 @@ private void loadAllResources(Vector v, String ... names) { for (int i = 0; i < names.length; i++) { resources[i] = "/" + names[i]; } - MimeTypeRegistry mf = loadResource(resources); - if (mf != null) - v.addElement(mf); + v.addAll(loadResource(resources)); } } @@ -332,7 +331,7 @@ public MimetypesFileTypeMap(InputStream is) { /** * Prepend the MIME type values to the registry. * - * @param mime_types A .jakarta.mime.types formatted string of entries. + * @param mime_types A mime types formatted string of entries. */ public synchronized void addMimeTypes(String mime_types) { try { diff --git a/doc/spec/JAF-2.2-changes.txt b/doc/spec/JAF-2.2-changes.txt index 7f6316e..8d1cad0 100644 --- a/doc/spec/JAF-2.2-changes.txt +++ b/doc/spec/JAF-2.2-changes.txt @@ -12,4 +12,23 @@ find more information about the bug reports at: The Jakarta Activation 2.2 requires Java SE 11 or later. Jakarta Activation 2.2 is part of Jakarta EE 12. +=================================================================== +1. Resource Loading Order +---------------------------------------------------------------- + +To maintain backward compatibility while supporting Jakarta-prefixed resources, Jakarta Activation 2.2 now loads both legacy and Jakarta-prefixed resources when they are present in the classpath. + +Legacy resources (without the jakarta. prefix) are given precedence if both forms exist. + +Jakarta-prefixed resources (jakarta.*) are also loaded to support migration. + +For example: + +If both mailcap and jakarta.mailcap exist, the entries from mailcap are applied first. + +If both mime.types and jakarta.mime.types exist, the entries from mime.types are applied first. + +This ensures that existing applications using legacy resources continue to function correctly, while allowing Jakarta-prefixed resources to be used alongside them. + +Over time, the legacy resources may be removed, leaving only the Jakarta-prefixed variants.