Skip to content

Commit 958fb97

Browse files
authored
services/jakarta.mail.Provider override not working #777 (#779)
Signed-off-by: Jorge Bescos Gascon <[email protected]>
1 parent 3446c94 commit 958fb97

File tree

11 files changed

+287
-115
lines changed

11 files changed

+287
-115
lines changed

api/src/main/java/jakarta/mail/Provider.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 1997, 2023 Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 1997, 2025 Oracle and/or its affiliates. All rights reserved.
33
*
44
* This program and the accompanying materials are made available under the
55
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -19,7 +19,7 @@
1919
/**
2020
* The Provider is a class that describes a protocol
2121
* implementation. The values typically come from the
22-
* javamail.providers and javamail.default.providers
22+
* jakarta.providers and jakarta.default.providers
2323
* resource files. An application may also create and
2424
* register a Provider object to dynamically add support
2525
* for a new provider.

api/src/main/java/jakarta/mail/Session.java

Lines changed: 110 additions & 95 deletions
Original file line numberDiff line numberDiff line change
@@ -59,18 +59,18 @@
5959
* implement the <code>Store</code>, <code>Transport</code>, and related
6060
* classes. The protocol providers are configured using the following files:
6161
* <ul>
62-
* <li> <code>javamail.providers</code> and
63-
* <code>javamail.default.providers</code> </li>
64-
* <li> <code>javamail.address.map</code> and
65-
* <code>javamail.default.address.map</code> </li>
62+
* <li> <code>jakarta.providers</code> and
63+
* <code>jakarta.default.providers</code> </li>
64+
* <li> <code>jakarta.address.map</code> and
65+
* <code>jakarta.default.address.map</code> </li>
6666
* </ul>
6767
* <p>
68-
* Each <code>javamail.</code><i>X</i> resource file is searched for using
68+
* Each <code>jakarta.</code><i>X</i> resource file is searched for using
6969
* three methods in the following order:
7070
* <ol>
71-
* <li> <code><i>java.home</i>/<i>conf</i>/javamail.</code><i>X</i> </li>
72-
* <li> <code>META-INF/javamail.</code><i>X</i> </li>
73-
* <li> <code>META-INF/javamail.default.</code><i>X</i> </li>
71+
* <li> <code><i>java.home</i>/<i>conf</i>/jakarta.</code><i>X</i> </li>
72+
* <li> <code>META-INF/jakarta.</code><i>X</i> </li>
73+
* <li> <code>META-INF/jakarta.default.</code><i>X</i> </li>
7474
* </ol>
7575
* <p>
7676
* (Where <i>java.home</i> is the value of the "java.home" System property
@@ -83,7 +83,7 @@
8383
* <code>java.home</code> property points. The second method allows an
8484
* application that uses the Jakarta Mail APIs to include their own resource
8585
* files in their application's or jar file's <code>META-INF</code>
86-
* directory. The <code>javamail.default.</code><i>X</i> default files
86+
* directory. The <code>jakarta.default.</code><i>X</i> default files
8787
* are part of the Jakarta Mail <code>mail.jar</code> file and should not be
8888
* supplied by users. <p>
8989
*
@@ -100,8 +100,8 @@
100100
* do not override, the default files included with the Jakarta Mail APIs.
101101
* This means that all entries in all files loaded will be available. <p>
102102
*
103-
* <b><code>javamail.providers</code></b> and
104-
* <b><code>javamail.default.providers</code></b><p>
103+
* <b><code>jakarta.providers</code></b> and
104+
* <b><code>jakarta.default.providers</code></b><p>
105105
*
106106
* These resource files specify the stores and transports that are
107107
* available on the system, allowing an application to "discover" what
@@ -142,7 +142,7 @@
142142
* </tr>
143143
* </table><p>
144144
*
145-
* Here's an example of <code>META-INF/javamail.default.providers</code>
145+
* Here's an example of <code>META-INF/jakarta.default.providers</code>
146146
* file contents:
147147
* <pre>
148148
* protocol=imap; type=store; class=com.sun.mail.imap.IMAPStore; vendor=Oracle;
@@ -172,13 +172,13 @@
172172
* </pre>
173173
* <p>
174174
*
175-
* <b><code>javamail.address.map</code></b> and
176-
* <b><code>javamail.default.address.map</code></b><p>
175+
* <b><code>jakarta.address.map</code></b> and
176+
* <b><code>jakarta.default.address.map</code></b><p>
177177
*
178178
* These resource files map transport address types to the transport
179179
* protocol. The <code>getType</code> method of
180180
* <code>jakarta.mail.Address</code> returns the address type. The
181-
* <code>javamail.address.map</code> file maps the transport type to the
181+
* <code>jakarta.address.map</code> file maps the transport type to the
182182
* protocol. The file format is a series of name-value pairs. Each key
183183
* name should correspond to an address type that is currently installed
184184
* on the system; there should also be an entry for each
@@ -190,7 +190,7 @@
190190
* the client should install a Transport provider supporting the nntp
191191
* protocol. <p>
192192
*
193-
* Here are the typical contents of a <code>javamail.address.map</code> file:
193+
* Here are the typical contents of a <code>jakarta.address.map</code> file:
194194
* <pre>
195195
* rfc822=smtp
196196
* news=nntp
@@ -206,6 +206,12 @@ public final class Session {
206206
// Support legacy @DefaultProvider
207207
private static final String DEFAULT_PROVIDER = "org.eclipse.angus.mail.util.DefaultProvider";
208208

209+
// This is for backwards compatibility. Eventually we have to remove the second value of the next arrays.
210+
private static final String[] DEFAULT_ADDRESS_MAP_RESOURCES = new String[] {"/META-INF/jakarta.default.address.map", "/META-INF/javamail.default.address.map"};
211+
private static final String[] ADDRESS_MAP_RESOURCES = new String[] {"META-INF/jakarta.address.map", "META-INF/javamail.address.map"};
212+
private static final String[] DEFAULT_PROVIDER_RESOURCES = new String[] {"/META-INF/jakarta.default.providers", "/META-INF/javamail.default.providers"};
213+
private static final String[] PROVIDER_RESOURCES = new String[] {"META-INF/jakarta.providers", "META-INF/javamail.providers"};
214+
209215
private final StreamProvider streamProvider;
210216
private final Properties props;
211217
private final Authenticator authenticator;
@@ -484,7 +490,7 @@ public synchronized PrintStream getDebugOut() {
484490

485491
/**
486492
* This method returns an array of all the implementations installed
487-
* via the javamail.[default.]providers files that can
493+
* via the jakarta.[default.]providers files that can
488494
* be loaded using the ClassLoader available to this application.
489495
*
490496
* @return Array of configured providers
@@ -966,11 +972,11 @@ public void load(InputStream is) throws IOException {
966972
}
967973
};
968974

969-
// load system-wide javamail.providers from the
975+
// load system-wide jakarta.providers from the
970976
// <java.home>/{conf,lib} directory
971977
try {
972978
if (confDir != null)
973-
loadFile(confDir + "javamail.providers", loader);
979+
loadFile(loader, confDir + "jakarta.providers", confDir + "javamail.providers");
974980
} catch (SecurityException ex) {
975981
}
976982

@@ -998,11 +1004,11 @@ public void load(InputStream is) throws IOException {
9981004
addProvider(p);
9991005
}
10001006

1001-
// load the META-INF/javamail.providers file supplied by an application
1002-
loadAllResources("META-INF/javamail.providers", cl, loader);
1007+
// load the META-INF/jakarta.providers file supplied by an application
1008+
loadAllResources(cl, loader, PROVIDER_RESOURCES);
10031009

1004-
// load default META-INF/javamail.default.providers from mail.jar file
1005-
loadResource("/META-INF/javamail.default.providers", cl, loader, false);
1010+
// load default META-INF/jakarta.default.providers from mail.jar file
1011+
loadResource(cl, loader, false, DEFAULT_PROVIDER_RESOURCES);
10061012

10071013
// finally, add all the default services
10081014
sl = ServiceLoader.load(Provider.class, gcl);
@@ -1137,17 +1143,17 @@ public void load(InputStream is) throws IOException {
11371143
}
11381144
};
11391145

1140-
// load default META-INF/javamail.default.address.map from mail.jar
1141-
loadResource("/META-INF/javamail.default.address.map", cl, loader, true);
1146+
// load default META-INF/jakarta.default.address.map from mail.jar
1147+
loadResource(cl, loader, true, DEFAULT_ADDRESS_MAP_RESOURCES);
11421148

1143-
// load the META-INF/javamail.address.map file supplied by an app
1144-
loadAllResources("META-INF/javamail.address.map", cl, loader);
1149+
// load the META-INF/jakarta.address.map file supplied by an app
1150+
loadAllResources(cl, loader, ADDRESS_MAP_RESOURCES);
11451151

1146-
// load system-wide javamail.address.map from the
1152+
// load system-wide jakarta.address.map from the
11471153
// <java.home>/{conf,lib} directory
11481154
try {
11491155
if (confDir != null)
1150-
loadFile(confDir + "javamail.address.map", loader);
1156+
loadFile(loader, confDir + "jakarta.address.map", confDir + "javamail.address.map");
11511157
} catch (SecurityException ex) {
11521158
}
11531159

@@ -1160,8 +1166,8 @@ public void load(InputStream is) throws IOException {
11601166
/**
11611167
* Set the default transport protocol to use for addresses of
11621168
* the specified type. Normally the default is set by the
1163-
* <code>javamail.default.address.map</code> or
1164-
* <code>javamail.address.map</code> files or resources.
1169+
* <code>jakarta.default.address.map</code> or
1170+
* <code>jakarta.address.map</code> files or resources.
11651171
*
11661172
* @param addresstype type of address
11671173
* @param protocol name of protocol
@@ -1178,41 +1184,46 @@ public synchronized void setProtocolForAddress(String addresstype, String protoc
11781184
/**
11791185
* Load from the named file.
11801186
*/
1181-
private void loadFile(String name, StreamLoader loader) {
1187+
private void loadFile(StreamLoader loader, String ... names) {
11821188
InputStream clis = null;
1183-
try {
1184-
clis = new BufferedInputStream(new FileInputStream(name));
1185-
loader.load(clis);
1186-
logger.log(Level.CONFIG, "successfully loaded file: {0}", name);
1187-
} catch (FileNotFoundException fex) {
1188-
// ignore it
1189-
} catch (IOException | SecurityException e) {
1190-
if (logger.isLoggable(Level.CONFIG))
1191-
logger.log(Level.CONFIG, "not loading file: " + name, e);
1192-
} finally {
1189+
for (String name : names) {
11931190
try {
1194-
if (clis != null)
1195-
clis.close();
1196-
} catch (IOException ex) {
1197-
} // ignore it
1191+
clis = new BufferedInputStream(new FileInputStream(name));
1192+
loader.load(clis);
1193+
logger.log(Level.CONFIG, "successfully loaded file: {0}", name);
1194+
break;
1195+
} catch (FileNotFoundException fex) {
1196+
// ignore it
1197+
} catch (IOException | SecurityException e) {
1198+
if (logger.isLoggable(Level.CONFIG))
1199+
logger.log(Level.CONFIG, "not loading file: " + name, e);
1200+
} finally {
1201+
try {
1202+
if (clis != null)
1203+
clis.close();
1204+
} catch (IOException ex) {
1205+
} // ignore it
1206+
}
11981207
}
11991208
}
12001209

12011210
/**
12021211
* Load from the named resource.
12031212
*/
1204-
private void loadResource(String name, Class<?> cl, StreamLoader loader, boolean expected) {
1213+
private void loadResource(Class<?> cl, StreamLoader loader, boolean expected, String ... names) {
12051214
InputStream clis = null;
12061215
try {
1207-
clis = getResourceAsStream(cl, name);
1208-
if (clis != null) {
1209-
loader.load(clis);
1210-
logger.log(Level.CONFIG, "successfully loaded resource: {0}",
1211-
name);
1212-
} else {
1216+
for (String name : names) {
1217+
clis = getResourceAsStream(cl, name);
1218+
if (clis != null) {
1219+
loader.load(clis);
1220+
logger.log(Level.CONFIG, "successfully loaded resource: {0}", name);
1221+
break;
1222+
}
1223+
}
1224+
if (clis == null) {
12131225
if (expected)
1214-
logger.log(Level.WARNING,
1215-
"expected resource not found: {0}", name);
1226+
logger.log(Level.WARNING, "expected resource not found: {0}", Arrays.asList(names));
12161227
}
12171228
} catch (IOException | SecurityException e) {
12181229
logger.log(Level.CONFIG, "Exception loading resource", e);
@@ -1228,45 +1239,48 @@ private void loadResource(String name, Class<?> cl, StreamLoader loader, boolean
12281239
/**
12291240
* Load all of the named resource.
12301241
*/
1231-
private void loadAllResources(String name, Class<?> cl, StreamLoader loader) {
1242+
private void loadAllResources(Class<?> cl, StreamLoader loader, String ... names) {
12321243
boolean anyLoaded = false;
12331244
try {
1234-
URL[] urls;
1235-
ClassLoader cld = null;
1236-
// First try the "application's" class loader.
1237-
cld = getContextClassLoader();
1238-
if (cld == null)
1239-
cld = cl.getClassLoader();
1240-
if (cld != null)
1241-
urls = getResources(cld, name);
1242-
else
1243-
urls = getSystemResources(name);
1244-
if (urls != null) {
1245-
for (int i = 0; i < urls.length; i++) {
1246-
URL url = urls[i];
1247-
InputStream clis = null;
1248-
logger.log(Level.CONFIG, "URL {0}", url);
1249-
try {
1250-
clis = openStream(url);
1251-
if (clis != null) {
1252-
loader.load(clis);
1253-
anyLoaded = true;
1254-
logger.log(Level.CONFIG,
1255-
"successfully loaded resource: {0}", url);
1256-
} else {
1257-
logger.log(Level.CONFIG,
1258-
"not loading resource: {0}", url);
1259-
}
1260-
} catch (FileNotFoundException fex) {
1261-
// ignore it
1262-
} catch (IOException | SecurityException ioex) {
1263-
logger.log(Level.CONFIG, "Exception loading resource",
1264-
ioex);
1265-
} finally {
1245+
for (String name : names) {
1246+
URL[] urls;
1247+
ClassLoader cld = null;
1248+
// First try the "application's" class loader.
1249+
cld = getContextClassLoader();
1250+
if (cld == null)
1251+
cld = cl.getClassLoader();
1252+
if (cld != null)
1253+
urls = getResources(cld, name);
1254+
else
1255+
urls = getSystemResources(name);
1256+
if (urls != null) {
1257+
for (int i = 0; i < urls.length; i++) {
1258+
URL url = urls[i];
1259+
InputStream clis = null;
1260+
logger.log(Level.CONFIG, "URL {0}", url);
12661261
try {
1267-
if (clis != null)
1268-
clis.close();
1269-
} catch (IOException cex) {
1262+
clis = openStream(url);
1263+
if (clis != null) {
1264+
loader.load(clis);
1265+
anyLoaded = true;
1266+
logger.log(Level.CONFIG,
1267+
"successfully loaded resource: {0}", url);
1268+
break;
1269+
} else {
1270+
logger.log(Level.CONFIG,
1271+
"not loading resource: {0}", url);
1272+
}
1273+
} catch (FileNotFoundException fex) {
1274+
// ignore it
1275+
} catch (IOException | SecurityException ioex) {
1276+
logger.log(Level.CONFIG, "Exception loading resource",
1277+
ioex);
1278+
} finally {
1279+
try {
1280+
if (clis != null)
1281+
clis.close();
1282+
} catch (IOException cex) {
1283+
}
12701284
}
12711285
}
12721286
}
@@ -1277,10 +1291,11 @@ private void loadAllResources(String name, Class<?> cl, StreamLoader loader) {
12771291

12781292
// if failed to load anything, fall back to old technique, just in case
12791293
if (!anyLoaded) {
1280-
/*
1281-
logger.config("!anyLoaded");
1282-
*/
1283-
loadResource("/" + name, cl, loader, false);
1294+
String[] resources = new String[names.length];
1295+
for (int i = 0; i < names.length; i++) {
1296+
resources[i] = "/" + names[i];
1297+
}
1298+
loadResource(cl, loader, false, resources);
12841299
}
12851300
}
12861301

0 commit comments

Comments
 (0)