/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright (c) 1997-2018 Oracle and/or its affiliates. All rights reserved.
*
* The contents of this file are subject to the terms of either the GNU
* General Public License Version 2 only ("GPL") or the Common Development
* and Distribution License("CDDL") (collectively, the "License"). You
* may not use this file except in compliance with the License. You can
* obtain a copy of the License at
* https://oss.oracle.com/licenses/CDDL+GPL-1.1
* or LICENSE.txt. See the License for the specific
* language governing permissions and limitations under the License.
*
* When distributing the software, include this License Header Notice in each
* file and include the License file at LICENSE.txt.
*
* GPL Classpath Exception:
* Oracle designates this particular file as subject to the "Classpath"
* exception as provided by Oracle in the GPL Version 2 section of the License
* file that accompanied this code.
*
* Modifications:
* If applicable, add the following below the License Header, with the fields
* enclosed by brackets [] replaced by your own identifying information:
* "Portions Copyright [year] [name of copyright owner]"
*
* Contributor(s):
* If you wish your version of this file to be governed by only the CDDL or
* only the GPL Version 2, indicate your decision by adding "[Contributor]
* elects to include this software in this distribution under the [CDDL or GPL
* Version 2] license." If you don't indicate a single choice of license, a
* recipient has the option to distribute your version of this file under
* either the CDDL, the GPL Version 2 or to extend the choice of license to
* its licensees as provided above. However, if you add GPL Version 2 code
* and therefore, elected the GPL Version 2 license, then the option applies
* only if the new code is made subject to such option by the copyright
* holder.
*/
package javax.mail;
import java.lang.reflect.*;
import java.io.*;
import java.net.*;
import java.security.*;
import java.util.Collections;
import java.util.Hashtable;
import java.util.Map;
import java.util.HashMap;
import java.util.List;
import java.util.ArrayList;
import java.util.Properties;
import java.util.StringTokenizer;
import java.util.ServiceLoader;
import java.util.logging.Level;
import java.util.concurrent.Executor;
import com.sun.mail.util.LineInputStream;
import com.sun.mail.util.MailLogger;
The Session class represents a mail session and is not subclassed.
It collects together properties and defaults used by the mail API's.
A single default session can be shared by multiple applications on the
desktop. Unshared sessions can also be created.
The Session class provides access to the protocol providers that
implement the Store
, Transport
, and related
classes. The protocol providers are configured using the following files:
-
javamail.providers
and
javamail.default.providers
-
javamail.address.map
and
javamail.default.address.map
Each javamail.
X resource file is searched for using
three methods in the following order:
-
java.home/conf/javamail.
X
-
META-INF/javamail.
X
-
META-INF/javamail.default.
X
(Where java.home is the value of the "java.home" System property
and conf is the directory named "conf" if it exists,
otherwise the directory named "lib"; the "conf" directory was
introduced in JDK 1.9.)
The first method allows the user to include their own version of the
resource file by placing it in the conf directory where the
java.home
property points. The second method allows an
application that uses the JavaMail APIs to include their own resource
files in their application's or jar file's META-INF
directory. The javamail.default.
X default files
are part of the JavaMail mail.jar
file and should not be
supplied by users.
File location depends upon how the ClassLoader
method
getResource
is implemented. Usually, the
getResource
method searches through CLASSPATH until it
finds the requested file and then stops.
The ordering of entries in the resource files matters. If multiple
entries exist, the first entries take precedence over the later
entries. For example, the first IMAP provider found will be set as the
default IMAP implementation until explicitly changed by the
application. The user- or system-supplied resource files augment, they
do not override, the default files included with the JavaMail APIs.
This means that all entries in all files loaded will be available.
javamail.providers
and
javamail.default.providers
These resource files specify the stores and transports that are
available on the system, allowing an application to "discover" what
store and transport implementations are available. The protocol
implementations are listed one per line. The file format defines four
attributes that describe a protocol implementation. Each attribute is
an "="-separated name-value pair with the name in lowercase. Each
name-value pair is semi-colon (";") separated. The following names
are defined.
Attribute Names in Providers Files
Name Description
protocol
Name assigned to protocol.
For example, smtp
for Transport.
type
Valid entries are store
and transport
.
class
Class name that implements this protocol.
vendor
Optional string identifying the vendor.
version
Optional string identifying the version.
Here's an example of META-INF/javamail.default.providers
file contents:
protocol=imap; type=store; class=com.sun.mail.imap.IMAPStore; vendor=Oracle;
protocol=smtp; type=transport; class=com.sun.mail.smtp.SMTPTransport; vendor=Oracle;
The current implementation also supports configuring providers using the Java SE ServiceLoader
mechanism. When creating your own provider, create a Provider
subclass, for example:
package com.example;
import javax.mail.Provider;
public class MyProvider extends Provider {
public MyProvider() {
super(Provider.Type.STORE, "myprot", MyStore.class.getName(),
"Example", null);
}
}
Then include a file named META-INF/services/javax.mail.Provider
in your jar file that lists the name of your Provider class:
com.example.MyProvider
javamail.address.map
and
javamail.default.address.map
These resource files map transport address types to the transport
protocol. The getType
method of
javax.mail.Address
returns the address type. The
javamail.address.map
file maps the transport type to the
protocol. The file format is a series of name-value pairs. Each key
name should correspond to an address type that is currently installed
on the system; there should also be an entry for each
javax.mail.Address
implementation that is present if it is
to be used. For example, the
javax.mail.internet.InternetAddress
method
getType
returns "rfc822". Each referenced protocol should
be installed on the system. For the case of news
, below,
the client should install a Transport provider supporting the nntp
protocol.
Here are the typical contents of a javamail.address.map
file:
rfc822=smtp
news=nntp
Author: John Mani, Bill Shannon, Max Spivak
/**
* The Session class represents a mail session and is not subclassed.
* It collects together properties and defaults used by the mail API's.
* A single default session can be shared by multiple applications on the
* desktop. Unshared sessions can also be created. <p>
*
* The Session class provides access to the protocol providers that
* implement the <code>Store</code>, <code>Transport</code>, and related
* classes. The protocol providers are configured using the following files:
* <ul>
* <li> <code>javamail.providers</code> and
* <code>javamail.default.providers</code> </li>
* <li> <code>javamail.address.map</code> and
* <code>javamail.default.address.map</code> </li>
* </ul>
* <p>
* Each <code>javamail.</code><i>X</i> resource file is searched for using
* three methods in the following order:
* <ol>
* <li> <code><i>java.home</i>/<i>conf</i>/javamail.</code><i>X</i> </li>
* <li> <code>META-INF/javamail.</code><i>X</i> </li>
* <li> <code>META-INF/javamail.default.</code><i>X</i> </li>
* </ol>
* <p>
* (Where <i>java.home</i> is the value of the "java.home" System property
* and <i>conf</i> is the directory named "conf" if it exists,
* otherwise the directory named "lib"; the "conf" directory was
* introduced in JDK 1.9.)
* <p>
* The first method allows the user to include their own version of the
* resource file by placing it in the <i>conf</i> directory where the
* <code>java.home</code> property points. The second method allows an
* application that uses the JavaMail APIs to include their own resource
* files in their application's or jar file's <code>META-INF</code>
* directory. The <code>javamail.default.</code><i>X</i> default files
* are part of the JavaMail <code>mail.jar</code> file and should not be
* supplied by users. <p>
*
* File location depends upon how the <code>ClassLoader</code> method
* <code>getResource</code> is implemented. Usually, the
* <code>getResource</code> method searches through CLASSPATH until it
* finds the requested file and then stops. <p>
*
* The ordering of entries in the resource files matters. If multiple
* entries exist, the first entries take precedence over the later
* entries. For example, the first IMAP provider found will be set as the
* default IMAP implementation until explicitly changed by the
* application. The user- or system-supplied resource files augment, they
* do not override, the default files included with the JavaMail APIs.
* This means that all entries in all files loaded will be available. <p>
*
* <b><code>javamail.providers</code></b> and
* <b><code>javamail.default.providers</code></b><p>
*
* These resource files specify the stores and transports that are
* available on the system, allowing an application to "discover" what
* store and transport implementations are available. The protocol
* implementations are listed one per line. The file format defines four
* attributes that describe a protocol implementation. Each attribute is
* an "="-separated name-value pair with the name in lowercase. Each
* name-value pair is semi-colon (";") separated. The following names
* are defined.
*
* <table border=1>
* <caption>
* Attribute Names in Providers Files
* </caption>
* <tr>
* <th>Name</th><th>Description</th>
* </tr>
* <tr>
* <td>protocol</td>
* <td>Name assigned to protocol.
* For example, <code>smtp</code> for Transport.</td>
* </tr>
* <tr>
* <td>type</td>
* <td>Valid entries are <code>store</code> and <code>transport</code>.</td>
* </tr>
* <tr>
* <td>class</td>
* <td>Class name that implements this protocol.</td>
* </tr>
* <tr>
* <td>vendor</td>
* <td>Optional string identifying the vendor.</td>
* </tr>
* <tr>
* <td>version</td>
* <td>Optional string identifying the version.</td>
* </tr>
* </table><p>
*
* Here's an example of <code>META-INF/javamail.default.providers</code>
* file contents:
* <pre>
* protocol=imap; type=store; class=com.sun.mail.imap.IMAPStore; vendor=Oracle;
* protocol=smtp; type=transport; class=com.sun.mail.smtp.SMTPTransport; vendor=Oracle;
* </pre><p>
*
* The current implementation also supports configuring providers using
* the Java SE {@link java.util.ServiceLoader ServiceLoader} mechanism.
* When creating your own provider, create a {@link Provider} subclass,
* for example:
* <pre>
* package com.example;
*
* import javax.mail.Provider;
*
* public class MyProvider extends Provider {
* public MyProvider() {
* super(Provider.Type.STORE, "myprot", MyStore.class.getName(),
* "Example", null);
* }
* }
* </pre>
* Then include a file named <code>META-INF/services/javax.mail.Provider</code>
* in your jar file that lists the name of your Provider class:
* <pre>
* com.example.MyProvider
* </pre>
* <p>
*
* <b><code>javamail.address.map</code></b> and
* <b><code>javamail.default.address.map</code></b><p>
*
* These resource files map transport address types to the transport
* protocol. The <code>getType</code> method of
* <code>javax.mail.Address</code> returns the address type. The
* <code>javamail.address.map</code> file maps the transport type to the
* protocol. The file format is a series of name-value pairs. Each key
* name should correspond to an address type that is currently installed
* on the system; there should also be an entry for each
* <code>javax.mail.Address</code> implementation that is present if it is
* to be used. For example, the
* <code>javax.mail.internet.InternetAddress</code> method
* <code>getType</code> returns "rfc822". Each referenced protocol should
* be installed on the system. For the case of <code>news</code>, below,
* the client should install a Transport provider supporting the nntp
* protocol. <p>
*
* Here are the typical contents of a <code>javamail.address.map</code> file:
* <pre>
* rfc822=smtp
* news=nntp
* </pre>
*
* @author John Mani
* @author Bill Shannon
* @author Max Spivak
*/
public final class Session {
private final Properties props;
private final Authenticator authenticator;
private final Hashtable<URLName, PasswordAuthentication> authTable
= new Hashtable<>();
private boolean debug = false;
private PrintStream out; // debug output stream
private MailLogger logger;
private List<Provider> providers;
private final Map<String, Provider> providersByProtocol = new HashMap<>();
private final Map<String, Provider> providersByClassName = new HashMap<>();
private final Properties addressMap = new Properties();
// maps type to protocol
private boolean loadedProviders; // javamail.[default.]providers loaded?
// the queue of events to be delivered, if mail.event.scope===session
private final EventQueue q;
// The default session.
private static Session defaultSession = null;
private static final String confDir;
static {
String dir = null;
try {
dir = AccessController.doPrivileged(
new PrivilegedAction<String>() {
@Override
public String run() {
String home = System.getProperty("java.home");
String newdir = home + File.separator + "conf";
File conf = new File(newdir);
if (conf.exists())
return newdir + File.separator;
else
return home + File.separator +
"lib" + File.separator;
}
});
} catch (Exception ex) {
// ignore any exceptions
}
confDir = dir;
}
// Constructor is not public
private Session(Properties props, Authenticator authenticator) {
this.props = props;
this.authenticator = authenticator;
if (Boolean.valueOf(props.getProperty("mail.debug")).booleanValue())
debug = true;
initLogger();
logger.log(Level.CONFIG, "JavaMail version {0}", Version.version);
// get the Class associated with the Authenticator
Class<?> cl;
if (authenticator != null)
cl = authenticator.getClass();
else
cl = this.getClass();
// load the resources
loadAddressMap(cl);
q = new EventQueue((Executor)props.get("mail.event.executor"));
}
private final synchronized void initLogger() {
logger = new MailLogger(this.getClass(), "DEBUG", debug, getDebugOut());
}
Get a new Session object.
Params: - props – Properties object that hold relevant properties.
It is expected that the client supplies values
for the properties listed in Appendix A of the
JavaMail spec (particularly mail.store.protocol,
mail.transport.protocol, mail.host, mail.user,
and mail.from) as the defaults are unlikely to
work in all cases. - authenticator – Authenticator object used to call back to
the application when a user name and password is
needed.
See Also: Returns: a new Session object
/**
* Get a new Session object.
*
* @param props Properties object that hold relevant properties.<br>
* It is expected that the client supplies values
* for the properties listed in Appendix A of the
* JavaMail spec (particularly mail.store.protocol,
* mail.transport.protocol, mail.host, mail.user,
* and mail.from) as the defaults are unlikely to
* work in all cases.
* @param authenticator Authenticator object used to call back to
* the application when a user name and password is
* needed.
* @return a new Session object
* @see javax.mail.Authenticator
*/
public static Session getInstance(Properties props,
Authenticator authenticator) {
return new Session(props, authenticator);
}
Get a new Session object.
Params: - props – Properties object that hold relevant properties.
It is expected that the client supplies values
for the properties listed in Appendix A of the
JavaMail spec (particularly mail.store.protocol,
mail.transport.protocol, mail.host, mail.user,
and mail.from) as the defaults are unlikely to
work in all cases.
Returns: a new Session object Since: JavaMail 1.2
/**
* Get a new Session object.
*
* @param props Properties object that hold relevant properties.<br>
* It is expected that the client supplies values
* for the properties listed in Appendix A of the
* JavaMail spec (particularly mail.store.protocol,
* mail.transport.protocol, mail.host, mail.user,
* and mail.from) as the defaults are unlikely to
* work in all cases.
* @return a new Session object
* @since JavaMail 1.2
*/
public static Session getInstance(Properties props) {
return new Session(props, null);
}
Get the default Session object. If a default has not yet been
setup, a new Session object is created and installed as the
default.
Since the default session is potentially available to all
code executing in the same Java virtual machine, and the session
can contain security sensitive information such as user names
and passwords, access to the default session is restricted.
The Authenticator object, which must be created by the caller,
is used indirectly to check access permission. The Authenticator
object passed in when the session is created is compared with
the Authenticator object passed in to subsequent requests to
get the default session. If both objects are the same, or are
from the same ClassLoader, the request is allowed. Otherwise,
it is denied.
Note that if the Authenticator object used to create the session
is null, anyone can get the default session by passing in null.
Note also that the Properties object is used only the first time
this method is called, when a new Session object is created.
Subsequent calls return the Session object that was created by the
first call, and ignore the passed Properties object. Use the
getInstance
method to get a new Session object every
time the method is called.
Additional security Permission objects may be used to
control access to the default session.
In the current implementation, if a SecurityManager is set, the
caller must have the RuntimePermission("setFactory")
permission.
Params: - props – Properties object. Used only if a new Session
object is created.
It is expected that the client supplies values
for the properties listed in Appendix A of the
JavaMail spec (particularly mail.store.protocol,
mail.transport.protocol, mail.host, mail.user,
and mail.from) as the defaults are unlikely to
work in all cases. - authenticator – Authenticator object. Used only if a
new Session object is created. Otherwise,
it must match the Authenticator used to create
the Session.
Returns: the default Session object
/**
* Get the default Session object. If a default has not yet been
* setup, a new Session object is created and installed as the
* default. <p>
*
* Since the default session is potentially available to all
* code executing in the same Java virtual machine, and the session
* can contain security sensitive information such as user names
* and passwords, access to the default session is restricted.
* The Authenticator object, which must be created by the caller,
* is used indirectly to check access permission. The Authenticator
* object passed in when the session is created is compared with
* the Authenticator object passed in to subsequent requests to
* get the default session. If both objects are the same, or are
* from the same ClassLoader, the request is allowed. Otherwise,
* it is denied. <p>
*
* Note that if the Authenticator object used to create the session
* is null, anyone can get the default session by passing in null. <p>
*
* Note also that the Properties object is used only the first time
* this method is called, when a new Session object is created.
* Subsequent calls return the Session object that was created by the
* first call, and ignore the passed Properties object. Use the
* <code>getInstance</code> method to get a new Session object every
* time the method is called. <p>
*
* Additional security Permission objects may be used to
* control access to the default session. <p>
*
* In the current implementation, if a SecurityManager is set, the
* caller must have the <code>RuntimePermission("setFactory")</code>
* permission.
*
* @param props Properties object. Used only if a new Session
* object is created.<br>
* It is expected that the client supplies values
* for the properties listed in Appendix A of the
* JavaMail spec (particularly mail.store.protocol,
* mail.transport.protocol, mail.host, mail.user,
* and mail.from) as the defaults are unlikely to
* work in all cases.
* @param authenticator Authenticator object. Used only if a
* new Session object is created. Otherwise,
* it must match the Authenticator used to create
* the Session.
* @return the default Session object
*/
public static synchronized Session getDefaultInstance(Properties props,
Authenticator authenticator) {
if (defaultSession == null) {
SecurityManager security = System.getSecurityManager();
if (security != null)
security.checkSetFactory();
defaultSession = new Session(props, authenticator);
} else {
// have to check whether caller is allowed to see default session
if (defaultSession.authenticator == authenticator)
; // either same object or both null, either way OK
else if (defaultSession.authenticator != null &&
authenticator != null &&
defaultSession.authenticator.getClass().getClassLoader() ==
authenticator.getClass().getClassLoader())
; // both objects came from the same class loader, OK
else
// anything else is not allowed
throw new SecurityException("Access to default session denied");
}
return defaultSession;
}
Get the default Session object. If a default has not yet been
setup, a new Session object is created and installed as the
default.
Note that a default session created with no Authenticator is
available to all code executing in the same Java virtual
machine, and the session can contain security sensitive
information such as user names and passwords.
Params: - props – Properties object. Used only if a new Session
object is created.
It is expected that the client supplies values
for the properties listed in Appendix A of the
JavaMail spec (particularly mail.store.protocol,
mail.transport.protocol, mail.host, mail.user,
and mail.from) as the defaults are unlikely to
work in all cases.
Returns: the default Session object Since: JavaMail 1.2
/**
* Get the default Session object. If a default has not yet been
* setup, a new Session object is created and installed as the
* default. <p>
*
* Note that a default session created with no Authenticator is
* available to all code executing in the same Java virtual
* machine, and the session can contain security sensitive
* information such as user names and passwords.
*
* @param props Properties object. Used only if a new Session
* object is created.<br>
* It is expected that the client supplies values
* for the properties listed in Appendix A of the
* JavaMail spec (particularly mail.store.protocol,
* mail.transport.protocol, mail.host, mail.user,
* and mail.from) as the defaults are unlikely to
* work in all cases.
* @return the default Session object
* @since JavaMail 1.2
*/
public static Session getDefaultInstance(Properties props) {
return getDefaultInstance(props, null);
}
Set the debug setting for this Session.
Since the debug setting can be turned on only after the Session
has been created, to turn on debugging in the Session
constructor, set the property mail.debug
in the
Properties object passed in to the constructor to true. The
value of the mail.debug
property is used to
initialize the per-Session debugging flag. Subsequent calls to
the setDebug
method manipulate the per-Session
debugging flag and have no affect on the mail.debug
property.
Params: - debug – Debug setting
/**
* Set the debug setting for this Session.
* <p>
* Since the debug setting can be turned on only after the Session
* has been created, to turn on debugging in the Session
* constructor, set the property <code>mail.debug</code> in the
* Properties object passed in to the constructor to true. The
* value of the <code>mail.debug</code> property is used to
* initialize the per-Session debugging flag. Subsequent calls to
* the <code>setDebug</code> method manipulate the per-Session
* debugging flag and have no affect on the <code>mail.debug</code>
* property.
*
* @param debug Debug setting
*/
public synchronized void setDebug(boolean debug) {
this.debug = debug;
initLogger();
logger.log(Level.CONFIG, "setDebug: JavaMail version {0}",
Version.version);
}
Get the debug setting for this Session.
Returns: current debug setting
/**
* Get the debug setting for this Session.
*
* @return current debug setting
*/
public synchronized boolean getDebug() {
return debug;
}
Set the stream to be used for debugging output for this session.
If out
is null, System.out
will be used.
Note that debugging output that occurs before any session is created,
as a result of setting the mail.debug
system property,
will always be sent to System.out
.
Params: - out – the PrintStream to use for debugging output
Since: JavaMail 1.3
/**
* Set the stream to be used for debugging output for this session.
* If <code>out</code> is null, <code>System.out</code> will be used.
* Note that debugging output that occurs before any session is created,
* as a result of setting the <code>mail.debug</code> system property,
* will always be sent to <code>System.out</code>.
*
* @param out the PrintStream to use for debugging output
* @since JavaMail 1.3
*/
public synchronized void setDebugOut(PrintStream out) {
this.out = out;
initLogger();
}
Returns the stream to be used for debugging output. If no stream
has been set, System.out
is returned.
Returns: the PrintStream to use for debugging output Since: JavaMail 1.3
/**
* Returns the stream to be used for debugging output. If no stream
* has been set, <code>System.out</code> is returned.
*
* @return the PrintStream to use for debugging output
* @since JavaMail 1.3
*/
public synchronized PrintStream getDebugOut() {
if (out == null)
return System.out;
else
return out;
}
This method returns an array of all the implementations installed
via the javamail.[default.]providers files that can
be loaded using the ClassLoader available to this application.
Returns: Array of configured providers
/**
* This method returns an array of all the implementations installed
* via the javamail.[default.]providers files that can
* be loaded using the ClassLoader available to this application.
*
* @return Array of configured providers
*/
public synchronized Provider[] getProviders() {
List<Provider> plist = new ArrayList<Provider>();
boolean needFallback = true;
// first, add all the services
ServiceLoader<Provider> loader = ServiceLoader.load(Provider.class);
for (Provider p : loader) {
plist.add(p);
needFallback = false;
}
// then, add all the providers from config files
if (!loadedProviders)
loadProviders(needFallback);
if (providers != null)
plist.addAll(providers);
Provider[] _providers = new Provider[plist.size()];
plist.toArray(_providers);
return _providers;
}
Returns the default Provider for the protocol
specified. Checks mail.<protocol>.class property
first and if it exists, returns the Provider
associated with this implementation. If it doesn't exist,
returns the Provider that appeared first in the
configuration files. If an implementation for the protocol
isn't found, throws NoSuchProviderException
Params: - protocol – Configured protocol (i.e. smtp, imap, etc)
Throws: - NoSuchProviderException – If a provider for the given
protocol is not found.
Returns: Currently configured Provider for the specified protocol
/**
* Returns the default Provider for the protocol
* specified. Checks mail.<protocol>.class property
* first and if it exists, returns the Provider
* associated with this implementation. If it doesn't exist,
* returns the Provider that appeared first in the
* configuration files. If an implementation for the protocol
* isn't found, throws NoSuchProviderException
*
* @param protocol Configured protocol (i.e. smtp, imap, etc)
* @return Currently configured Provider for the specified protocol
* @exception NoSuchProviderException If a provider for the given
* protocol is not found.
*/
public synchronized Provider getProvider(String protocol)
throws NoSuchProviderException {
if (protocol == null || protocol.length() <= 0) {
throw new NoSuchProviderException("Invalid protocol: null");
}
Provider _provider = null;
// check if the mail.<protocol>.class property exists
String _className = props.getProperty("mail."+protocol+".class");
if (_className != null) {
if (logger.isLoggable(Level.FINE)) {
logger.fine("mail."+protocol+
".class property exists and points to " +
_className);
}
_provider = getProviderByClassName(_className);
}
if (_provider == null)
_provider = getProviderByProtocol(protocol);
if (_provider == null) {
throw new NoSuchProviderException("No provider for " + protocol);
} else {
if (logger.isLoggable(Level.FINE)) {
logger.fine("getProvider() returning " + _provider.toString());
}
return _provider;
}
}
Set the passed Provider to be the default implementation
for the protocol in Provider.protocol overriding any previous values.
Params: - provider – Currently configured Provider which will be
set as the default for the protocol
Throws: - NoSuchProviderException – If the provider passed in
is invalid.
/**
* Set the passed Provider to be the default implementation
* for the protocol in Provider.protocol overriding any previous values.
*
* @param provider Currently configured Provider which will be
* set as the default for the protocol
* @exception NoSuchProviderException If the provider passed in
* is invalid.
*/
public synchronized void setProvider(Provider provider)
throws NoSuchProviderException {
if (provider == null) {
throw new NoSuchProviderException("Can't set null provider");
}
providersByProtocol.put(provider.getProtocol(), provider);
providersByClassName.put(provider.getClassName(), provider);
props.put("mail." + provider.getProtocol() + ".class",
provider.getClassName());
}
Get a Store object that implements this user's desired Store
protocol. The mail.store.protocol
property specifies the
desired protocol. If an appropriate Store object is not obtained,
NoSuchProviderException is thrown
Throws: - NoSuchProviderException – If a provider for the given
protocol is not found.
Returns: a Store object
/**
* Get a Store object that implements this user's desired Store
* protocol. The <code>mail.store.protocol</code> property specifies the
* desired protocol. If an appropriate Store object is not obtained,
* NoSuchProviderException is thrown
*
* @return a Store object
* @exception NoSuchProviderException If a provider for the given
* protocol is not found.
*/
public Store getStore() throws NoSuchProviderException {
return getStore(getProperty("mail.store.protocol"));
}
Get a Store object that implements the specified protocol. If an
appropriate Store object cannot be obtained,
NoSuchProviderException is thrown.
Params: - protocol – the Store protocol
Throws: - NoSuchProviderException – If a provider for the given
protocol is not found.
Returns: a Store object
/**
* Get a Store object that implements the specified protocol. If an
* appropriate Store object cannot be obtained,
* NoSuchProviderException is thrown.
*
* @param protocol the Store protocol
* @return a Store object
* @exception NoSuchProviderException If a provider for the given
* protocol is not found.
*/
public Store getStore(String protocol) throws NoSuchProviderException {
return getStore(new URLName(protocol, null, -1, null, null, null));
}
Get a Store object for the given URLName. If the requested Store
object cannot be obtained, NoSuchProviderException is thrown.
The "scheme" part of the URL string (Refer RFC 1738) is used
to locate the Store protocol.
Params: - url – URLName that represents the desired Store
Throws: - NoSuchProviderException – If a provider for the given
URLName is not found.
See Also: Returns: a closed Store object
/**
* Get a Store object for the given URLName. If the requested Store
* object cannot be obtained, NoSuchProviderException is thrown.
*
* The "scheme" part of the URL string (Refer RFC 1738) is used
* to locate the Store protocol. <p>
*
* @param url URLName that represents the desired Store
* @return a closed Store object
* @see #getFolder(URLName)
* @see javax.mail.URLName
* @exception NoSuchProviderException If a provider for the given
* URLName is not found.
*/
public Store getStore(URLName url) throws NoSuchProviderException {
String protocol = url.getProtocol();
Provider p = getProvider(protocol);
return getStore(p, url);
}
Get an instance of the store specified by Provider. Instantiates
the store and returns it.
Params: - provider – Store Provider that will be instantiated
Throws: - NoSuchProviderException – If a provider for the given
Provider is not found.
Returns: Instantiated Store
/**
* Get an instance of the store specified by Provider. Instantiates
* the store and returns it.
*
* @param provider Store Provider that will be instantiated
* @return Instantiated Store
* @exception NoSuchProviderException If a provider for the given
* Provider is not found.
*/
public Store getStore(Provider provider) throws NoSuchProviderException {
return getStore(provider, null);
}
Get an instance of the store specified by Provider. If the URLName
is not null, uses it, otherwise creates a new one. Instantiates
the store and returns it. This is a private method used by
getStore(Provider) and getStore(URLName)
Params: - provider – Store Provider that will be instantiated
- url – URLName used to instantiate the Store
Throws: - NoSuchProviderException – If a provider for the given
Provider/URLName is not found.
Returns: Instantiated Store
/**
* Get an instance of the store specified by Provider. If the URLName
* is not null, uses it, otherwise creates a new one. Instantiates
* the store and returns it. This is a private method used by
* getStore(Provider) and getStore(URLName)
*
* @param provider Store Provider that will be instantiated
* @param url URLName used to instantiate the Store
* @return Instantiated Store
* @exception NoSuchProviderException If a provider for the given
* Provider/URLName is not found.
*/
private Store getStore(Provider provider, URLName url)
throws NoSuchProviderException {
// make sure we have the correct type of provider
if (provider == null || provider.getType() != Provider.Type.STORE ) {
throw new NoSuchProviderException("invalid provider");
}
return getService(provider, url, Store.class);
}
Get a closed Folder object for the given URLName. If the requested
Folder object cannot be obtained, null is returned.
The "scheme" part of the URL string (Refer RFC 1738) is used
to locate the Store protocol. The rest of the URL string (that is,
the "schemepart", as per RFC 1738) is used by that Store
in a protocol dependent manner to locate and instantiate the
appropriate Folder object.
Note that RFC 1738 also specifies the syntax for the
"schemepart" for IP-based protocols (IMAP4, POP3, etc.).
Providers of IP-based mail Stores should implement that
syntax for referring to Folders.
Params: - url – URLName that represents the desired folder
Throws: - NoSuchProviderException – If a provider for the given
URLName is not found.
- MessagingException – if the Folder could not be
located or created.
See Also: Returns: Folder
/**
* Get a closed Folder object for the given URLName. If the requested
* Folder object cannot be obtained, null is returned. <p>
*
* The "scheme" part of the URL string (Refer RFC 1738) is used
* to locate the Store protocol. The rest of the URL string (that is,
* the "schemepart", as per RFC 1738) is used by that Store
* in a protocol dependent manner to locate and instantiate the
* appropriate Folder object. <p>
*
* Note that RFC 1738 also specifies the syntax for the
* "schemepart" for IP-based protocols (IMAP4, POP3, etc.).
* Providers of IP-based mail Stores should implement that
* syntax for referring to Folders. <p>
*
* @param url URLName that represents the desired folder
* @return Folder
* @see #getStore(URLName)
* @see javax.mail.URLName
* @exception NoSuchProviderException If a provider for the given
* URLName is not found.
* @exception MessagingException if the Folder could not be
* located or created.
*/
public Folder getFolder(URLName url)
throws MessagingException {
// First get the Store
Store store = getStore(url);
store.connect();
return store.getFolder(url);
}
Get a Transport object that implements this user's desired
Transport protcol. The mail.transport.protocol
property
specifies the desired protocol. If an appropriate Transport
object cannot be obtained, MessagingException is thrown.
Throws: - NoSuchProviderException – If the provider is not found.
Returns: a Transport object
/**
* Get a Transport object that implements this user's desired
* Transport protcol. The <code>mail.transport.protocol</code> property
* specifies the desired protocol. If an appropriate Transport
* object cannot be obtained, MessagingException is thrown.
*
* @return a Transport object
* @exception NoSuchProviderException If the provider is not found.
*/
public Transport getTransport() throws NoSuchProviderException {
String prot = getProperty("mail.transport.protocol");
if (prot != null)
return getTransport(prot);
// if the property isn't set, use the protocol for "rfc822"
prot = (String)addressMap.get("rfc822");
if (prot != null)
return getTransport(prot);
return getTransport("smtp"); // if all else fails
}
Get a Transport object that implements the specified protocol.
If an appropriate Transport object cannot be obtained, null is
returned.
Params: - protocol – the Transport protocol
Throws: - NoSuchProviderException – If provider for the given
protocol is not found.
Returns: a Transport object
/**
* Get a Transport object that implements the specified protocol.
* If an appropriate Transport object cannot be obtained, null is
* returned.
*
* @param protocol the Transport protocol
* @return a Transport object
* @exception NoSuchProviderException If provider for the given
* protocol is not found.
*/
public Transport getTransport(String protocol)
throws NoSuchProviderException {
return getTransport(new URLName(protocol, null, -1, null, null, null));
}
Get a Transport object for the given URLName. If the requested
Transport object cannot be obtained, NoSuchProviderException is thrown.
The "scheme" part of the URL string (Refer RFC 1738) is used
to locate the Transport protocol.
Params: - url – URLName that represents the desired Transport
Throws: - NoSuchProviderException – If a provider for the given
URLName is not found.
See Also: Returns: a closed Transport object
/**
* Get a Transport object for the given URLName. If the requested
* Transport object cannot be obtained, NoSuchProviderException is thrown.
*
* The "scheme" part of the URL string (Refer RFC 1738) is used
* to locate the Transport protocol. <p>
*
* @param url URLName that represents the desired Transport
* @return a closed Transport object
* @see javax.mail.URLName
* @exception NoSuchProviderException If a provider for the given
* URLName is not found.
*/
public Transport getTransport(URLName url) throws NoSuchProviderException {
String protocol = url.getProtocol();
Provider p = getProvider(protocol);
return getTransport(p, url);
}
Get an instance of the transport specified in the Provider. Instantiates
the transport and returns it.
Params: - provider – Transport Provider that will be instantiated
Throws: - NoSuchProviderException – If provider for the given
provider is not found.
Returns: Instantiated Transport
/**
* Get an instance of the transport specified in the Provider. Instantiates
* the transport and returns it.
*
* @param provider Transport Provider that will be instantiated
* @return Instantiated Transport
* @exception NoSuchProviderException If provider for the given
* provider is not found.
*/
public Transport getTransport(Provider provider)
throws NoSuchProviderException {
return getTransport(provider, null);
}
Get a Transport object that can transport a Message of the
specified address type.
Params: - address – an address for which a Transport is needed
Throws: - NoSuchProviderException – If provider for the
Address type is not found
See Also: Returns: A Transport object
/**
* Get a Transport object that can transport a Message of the
* specified address type.
*
* @param address an address for which a Transport is needed
* @return A Transport object
* @see javax.mail.Address
* @exception NoSuchProviderException If provider for the
* Address type is not found
*/
public Transport getTransport(Address address)
throws NoSuchProviderException {
String transportProtocol;
transportProtocol =
getProperty("mail.transport.protocol." + address.getType());
if (transportProtocol != null)
return getTransport(transportProtocol);
transportProtocol = (String)addressMap.get(address.getType());
if (transportProtocol != null)
return getTransport(transportProtocol);
throw new NoSuchProviderException("No provider for Address type: "+
address.getType());
}
Get a Transport object using the given provider and urlname.
Params: - provider – the provider to use
- url – urlname to use (can be null)
Throws: - NoSuchProviderException – If no provider or the provider
was the wrong class.
Returns: A Transport object
/**
* Get a Transport object using the given provider and urlname.
*
* @param provider the provider to use
* @param url urlname to use (can be null)
* @return A Transport object
* @exception NoSuchProviderException If no provider or the provider
* was the wrong class.
*/
private Transport getTransport(Provider provider, URLName url)
throws NoSuchProviderException {
// make sure we have the correct type of provider
if (provider == null || provider.getType() != Provider.Type.TRANSPORT) {
throw new NoSuchProviderException("invalid provider");
}
return getService(provider, url, Transport.class);
}
Get a Service object. Needs a provider object, but will
create a URLName if needed. It attempts to instantiate
the correct class.
Params: - provider – which provider to use
- url – which URLName to use (can be null)
- type – the service type (class)
Throws: - NoSuchProviderException – thrown when the class cannot be
found or when it does not have the correct constructor
(Session, URLName), or if it is not derived from
Service.
/**
* Get a Service object. Needs a provider object, but will
* create a URLName if needed. It attempts to instantiate
* the correct class.
*
* @param provider which provider to use
* @param url which URLName to use (can be null)
* @param type the service type (class)
* @exception NoSuchProviderException thrown when the class cannot be
* found or when it does not have the correct constructor
* (Session, URLName), or if it is not derived from
* Service.
*/
private <T extends Service> T getService(Provider provider, URLName url,
Class<T> type)
throws NoSuchProviderException {
// need a provider and url
if (provider == null) {
throw new NoSuchProviderException("null");
}
// create a url if needed
if (url == null) {
url = new URLName(provider.getProtocol(), null, -1,
null, null, null);
}
Object service = null;
// get the ClassLoader associated with the Authenticator
ClassLoader cl;
if (authenticator != null)
cl = authenticator.getClass().getClassLoader();
else
cl = this.getClass().getClassLoader();
// now load the class
Class<?> serviceClass = null;
try {
// First try the "application's" class loader.
ClassLoader ccl = getContextClassLoader();
if (ccl != null)
try {
serviceClass =
Class.forName(provider.getClassName(), false, ccl);
} catch (ClassNotFoundException ex) {
// ignore it
}
if (serviceClass == null || !type.isAssignableFrom(serviceClass))
serviceClass =
Class.forName(provider.getClassName(), false, cl);
if (!type.isAssignableFrom(serviceClass))
throw new ClassCastException(
type.getName() + " " + serviceClass.getName());
} catch (Exception ex1) {
// That didn't work, now try the "system" class loader.
// (Need both of these because JDK 1.1 class loaders
// may not delegate to their parent class loader.)
try {
serviceClass = Class.forName(provider.getClassName());
if (!type.isAssignableFrom(serviceClass))
throw new ClassCastException(
type.getName() + " " + serviceClass.getName());
} catch (Exception ex) {
// Nothing worked, give up.
logger.log(Level.FINE, "Exception loading provider", ex);
throw new NoSuchProviderException(provider.getProtocol());
}
}
// construct an instance of the class
try {
Class<?>[] c = {javax.mail.Session.class, javax.mail.URLName.class};
Constructor<?> cons = serviceClass.getConstructor(c);
Object[] o = {this, url};
service = cons.newInstance(o);
} catch (Exception ex) {
logger.log(Level.FINE, "Exception loading provider", ex);
throw new NoSuchProviderException(provider.getProtocol());
}
return type.cast(service);
}
Save a PasswordAuthentication for this (store or transport) URLName.
If pw is null the entry corresponding to the URLName is removed.
This is normally used only by the store or transport implementations
to allow authentication information to be shared among multiple
uses of a session.
Params: - url – the URLName
- pw – the PasswordAuthentication to save
/**
* Save a PasswordAuthentication for this (store or transport) URLName.
* If pw is null the entry corresponding to the URLName is removed.
* <p>
* This is normally used only by the store or transport implementations
* to allow authentication information to be shared among multiple
* uses of a session.
*
* @param url the URLName
* @param pw the PasswordAuthentication to save
*/
public void setPasswordAuthentication(URLName url,
PasswordAuthentication pw) {
if (pw == null)
authTable.remove(url);
else
authTable.put(url, pw);
}
Return any saved PasswordAuthentication for this (store or transport)
URLName. Normally used only by store or transport implementations.
Params: - url – the URLName
Returns: the PasswordAuthentication corresponding to the URLName
/**
* Return any saved PasswordAuthentication for this (store or transport)
* URLName. Normally used only by store or transport implementations.
*
* @param url the URLName
* @return the PasswordAuthentication corresponding to the URLName
*/
public PasswordAuthentication getPasswordAuthentication(URLName url) {
return authTable.get(url);
}
Call back to the application to get the needed user name and password.
The application should put up a dialog something like:
Connecting to <protocol> mail service on host <addr>, port <port>.
<prompt>
User Name: <defaultUserName>
Password:
Params: - addr – InetAddress of the host. may be null.
- port – the port on the host
- protocol – protocol scheme (e.g. imap, pop3, etc.)
- prompt – any additional String to show as part of
the prompt; may be null.
- defaultUserName – the default username. may be null.
Returns: the authentication which was collected by the authenticator;
may be null.
/**
* Call back to the application to get the needed user name and password.
* The application should put up a dialog something like:
* <pre>
* Connecting to <protocol> mail service on host <addr>, port <port>.
* <prompt>
*
* User Name: <defaultUserName>
* Password:
* </pre>
*
* @param addr InetAddress of the host. may be null.
* @param port the port on the host
* @param protocol protocol scheme (e.g. imap, pop3, etc.)
* @param prompt any additional String to show as part of
* the prompt; may be null.
* @param defaultUserName the default username. may be null.
* @return the authentication which was collected by the authenticator;
* may be null.
*/
public PasswordAuthentication requestPasswordAuthentication(
InetAddress addr, int port,
String protocol, String prompt, String defaultUserName) {
if (authenticator != null) {
return authenticator.requestPasswordAuthentication(
addr, port, protocol, prompt, defaultUserName);
} else {
return null;
}
}
Returns the Properties object associated with this Session
Returns: Properties object
/**
* Returns the Properties object associated with this Session
*
* @return Properties object
*/
public Properties getProperties() {
return props;
}
Returns the value of the specified property. Returns null
if this property does not exist.
Params: - name – the property name
Returns: String that is the property value
/**
* Returns the value of the specified property. Returns null
* if this property does not exist.
*
* @param name the property name
* @return String that is the property value
*/
public String getProperty(String name) {
return props.getProperty(name);
}
Get the Provider that uses the specified class name.
Params: - className – the class name
Returns: the Provider
/**
* Get the Provider that uses the specified class name.
*
* @param className the class name
* @return the Provider
*/
private Provider getProviderByClassName(String className) {
// first, try our local list of providers
Provider p = providersByClassName.get(className);
if (p != null)
return p;
// now, try services
ServiceLoader<Provider> loader = ServiceLoader.load(Provider.class);
for (Provider pp : loader) {
if (className.equals(pp.getClassName()))
return pp;
}
// finally, if we haven't loaded our config, load it and try again
if (!loadedProviders) {
loadProviders(true);
p = providersByClassName.get(className);
}
return p;
}
Get the Provider for the specified protocol.
Params: - protocol – the protocol
Returns: the Provider
/**
* Get the Provider for the specified protocol.
*
* @param protocol the protocol
* @return the Provider
*/
private Provider getProviderByProtocol(String protocol) {
// first, try our local list of providers
Provider p = providersByProtocol.get(protocol);
if (p != null)
return p;
// now, try services
ServiceLoader<Provider> loader = ServiceLoader.load(Provider.class);
for (Provider pp : loader) {
if (protocol.equals(pp.getProtocol()))
return pp;
}
// finally, if we haven't loaded our config, load it and try again
if (!loadedProviders) {
loadProviders(true);
p = providersByProtocol.get(protocol);
}
return p;
}
Load the protocol providers config files.
If fallback is true, provide built in defaults if nothing is loaded.
/**
* Load the protocol providers config files.
* If fallback is true, provide built in defaults if nothing is loaded.
*/
private void loadProviders(boolean fallback) {
StreamLoader loader = new StreamLoader() {
@Override
public void load(InputStream is) throws IOException {
loadProvidersFromStream(is);
}
};
// load system-wide javamail.providers from the
// <java.home>/{conf,lib} directory
try {
if (confDir != null)
loadFile(confDir + "javamail.providers", loader);
} catch (SecurityException ex) {}
// get the Class associated with the Authenticator
Class<?> cl;
if (authenticator != null)
cl = authenticator.getClass();
else
cl = this.getClass();
// load the META-INF/javamail.providers file supplied by an application
loadAllResources("META-INF/javamail.providers", cl, loader);
// load default META-INF/javamail.default.providers from mail.jar file
loadResource("/META-INF/javamail.default.providers", cl, loader, false);
/*
* If we haven't loaded any providers and the fallback configuration
* is needed, fake it.
*/
if ((providers == null || providers.size() == 0) && fallback) {
logger.config("failed to load any providers, using defaults");
// failed to load any providers, initialize with our defaults
addProvider(new Provider(Provider.Type.STORE,
"imap", "com.sun.mail.imap.IMAPStore",
"Oracle", Version.version));
addProvider(new Provider(Provider.Type.STORE,
"imaps", "com.sun.mail.imap.IMAPSSLStore",
"Oracle", Version.version));
addProvider(new Provider(Provider.Type.STORE,
"pop3", "com.sun.mail.pop3.POP3Store",
"Oracle", Version.version));
addProvider(new Provider(Provider.Type.STORE,
"pop3s", "com.sun.mail.pop3.POP3SSLStore",
"Oracle", Version.version));
addProvider(new Provider(Provider.Type.TRANSPORT,
"smtp", "com.sun.mail.smtp.SMTPTransport",
"Oracle", Version.version));
addProvider(new Provider(Provider.Type.TRANSPORT,
"smtps", "com.sun.mail.smtp.SMTPSSLTransport",
"Oracle", Version.version));
}
if (logger.isLoggable(Level.CONFIG)) {
// dump the output of the tables for debugging
logger.config("Tables of loaded providers from javamail.providers");
logger.config("Providers Listed By Class Name: " +
providersByClassName.toString());
logger.config("Providers Listed By Protocol: " +
providersByProtocol.toString());
}
loadedProviders = true;
}
private void loadProvidersFromStream(InputStream is)
throws IOException {
if (is != null) {
LineInputStream lis = new LineInputStream(is);
String currLine;
// load and process one line at a time using LineInputStream
while ((currLine = lis.readLine()) != null) {
if (currLine.startsWith("#"))
continue;
if (currLine.trim().length() == 0)
continue; // skip blank line
Provider.Type type = null;
String protocol = null, className = null;
String vendor = null, version = null;
// separate line into key-value tuples
StringTokenizer tuples = new StringTokenizer(currLine,";");
while (tuples.hasMoreTokens()) {
String currTuple = tuples.nextToken().trim();
// set the value of each attribute based on its key
int sep = currTuple.indexOf("=");
if (currTuple.startsWith("protocol=")) {
protocol = currTuple.substring(sep+1);
} else if (currTuple.startsWith("type=")) {
String strType = currTuple.substring(sep+1);
if (strType.equalsIgnoreCase("store")) {
type = Provider.Type.STORE;
} else if (strType.equalsIgnoreCase("transport")) {
type = Provider.Type.TRANSPORT;
}
} else if (currTuple.startsWith("class=")) {
className = currTuple.substring(sep+1);
} else if (currTuple.startsWith("vendor=")) {
vendor = currTuple.substring(sep+1);
} else if (currTuple.startsWith("version=")) {
version = currTuple.substring(sep+1);
}
}
// check if a valid Provider; else, continue
if (type == null || protocol == null || className == null
|| protocol.length() <= 0 || className.length() <= 0) {
logger.log(Level.CONFIG, "Bad provider entry: {0}",
currLine);
continue;
}
Provider provider = new Provider(type, protocol, className,
vendor, version);
// add the newly-created Provider to the lookup tables
addProvider(provider);
}
}
}
Add a provider to the session.
Params: - provider – the provider to add
Since: JavaMail 1.4
/**
* Add a provider to the session.
*
* @param provider the provider to add
* @since JavaMail 1.4
*/
public synchronized void addProvider(Provider provider) {
if (providers == null)
providers = new ArrayList<Provider>();
providers.add(provider);
providersByClassName.put(provider.getClassName(), provider);
if (!providersByProtocol.containsKey(provider.getProtocol()))
providersByProtocol.put(provider.getProtocol(), provider);
}
// load maps in reverse order of preference so that the preferred
// map is loaded last since its entries will override the previous ones
private void loadAddressMap(Class<?> cl) {
StreamLoader loader = new StreamLoader() {
@Override
public void load(InputStream is) throws IOException {
addressMap.load(is);
}
};
// load default META-INF/javamail.default.address.map from mail.jar
loadResource("/META-INF/javamail.default.address.map", cl, loader, true);
// load the META-INF/javamail.address.map file supplied by an app
loadAllResources("META-INF/javamail.address.map", cl, loader);
// load system-wide javamail.address.map from the
// <java.home>/{conf,lib} directory
try {
if (confDir != null)
loadFile(confDir + "javamail.address.map", loader);
} catch (SecurityException ex) {}
if (addressMap.isEmpty()) {
logger.config("failed to load address map, using defaults");
addressMap.put("rfc822", "smtp");
}
}
Set the default transport protocol to use for addresses of
the specified type. Normally the default is set by the
javamail.default.address.map
or
javamail.address.map
files or resources.
Params: - addresstype – type of address
- protocol – name of protocol
See Also: Since: JavaMail 1.4
/**
* Set the default transport protocol to use for addresses of
* the specified type. Normally the default is set by the
* <code>javamail.default.address.map</code> or
* <code>javamail.address.map</code> files or resources.
*
* @param addresstype type of address
* @param protocol name of protocol
* @see #getTransport(Address)
* @since JavaMail 1.4
*/
public synchronized void setProtocolForAddress(String addresstype,
String protocol) {
if (protocol == null)
addressMap.remove(addresstype);
else
addressMap.put(addresstype, protocol);
}
Load from the named file.
/**
* Load from the named file.
*/
private void loadFile(String name, StreamLoader loader) {
InputStream clis = null;
try {
clis = new BufferedInputStream(new FileInputStream(name));
loader.load(clis);
logger.log(Level.CONFIG, "successfully loaded file: {0}", name);
} catch (FileNotFoundException fex) {
// ignore it
} catch (IOException e) {
if (logger.isLoggable(Level.CONFIG))
logger.log(Level.CONFIG, "not loading file: " + name, e);
} catch (SecurityException sex) {
if (logger.isLoggable(Level.CONFIG))
logger.log(Level.CONFIG, "not loading file: " + name, sex);
} finally {
try {
if (clis != null)
clis.close();
} catch (IOException ex) { } // ignore it
}
}
Load from the named resource.
/**
* Load from the named resource.
*/
private void loadResource(String name, Class<?> cl, StreamLoader loader,
boolean expected) {
InputStream clis = null;
try {
clis = getResourceAsStream(cl, name);
if (clis != null) {
loader.load(clis);
logger.log(Level.CONFIG, "successfully loaded resource: {0}",
name);
} else {
if (expected)
logger.log(Level.WARNING,
"expected resource not found: {0}", name);
}
} catch (IOException e) {
logger.log(Level.CONFIG, "Exception loading resource", e);
} catch (SecurityException sex) {
logger.log(Level.CONFIG, "Exception loading resource", sex);
} finally {
try {
if (clis != null)
clis.close();
} catch (IOException ex) { } // ignore it
}
}
Load all of the named resource.
/**
* Load all of the named resource.
*/
private void loadAllResources(String name, Class<?> cl,
StreamLoader loader) {
boolean anyLoaded = false;
try {
URL[] urls;
ClassLoader cld = null;
// First try the "application's" class loader.
cld = getContextClassLoader();
if (cld == null)
cld = cl.getClassLoader();
if (cld != null)
urls = getResources(cld, name);
else
urls = getSystemResources(name);
if (urls != null) {
for (int i = 0; i < urls.length; i++) {
URL url = urls[i];
InputStream clis = null;
logger.log(Level.CONFIG, "URL {0}", url);
try {
clis = openStream(url);
if (clis != null) {
loader.load(clis);
anyLoaded = true;
logger.log(Level.CONFIG,
"successfully loaded resource: {0}", url);
} else {
logger.log(Level.CONFIG,
"not loading resource: {0}", url);
}
} catch (FileNotFoundException fex) {
// ignore it
} catch (IOException ioex) {
logger.log(Level.CONFIG, "Exception loading resource",
ioex);
} catch (SecurityException sex) {
logger.log(Level.CONFIG, "Exception loading resource",
sex);
} finally {
try {
if (clis != null)
clis.close();
} catch (IOException cex) { }
}
}
}
} catch (Exception ex) {
logger.log(Level.CONFIG, "Exception loading resource", ex);
}
// if failed to load anything, fall back to old technique, just in case
if (!anyLoaded) {
/*
logger.config("!anyLoaded");
*/
loadResource("/" + name, cl, loader, false);
}
}
/*
* Following are security related methods that work on JDK 1.2 or newer.
*/
static ClassLoader getContextClassLoader() {
return AccessController.doPrivileged(
new PrivilegedAction<ClassLoader>() {
@Override
public ClassLoader run() {
ClassLoader cl = null;
try {
cl = Thread.currentThread().getContextClassLoader();
} catch (SecurityException ex) {
}
return cl;
}
}
);
}
private static InputStream getResourceAsStream(final Class<?> c,
final String name) throws IOException {
try {
return AccessController.doPrivileged(
new PrivilegedExceptionAction<InputStream>() {
@Override
public InputStream run() throws IOException {
try {
return c.getResourceAsStream(name);
} catch (RuntimeException e) {
// gracefully handle ClassLoader bugs (Tomcat)
IOException ioex = new IOException(
"ClassLoader.getResourceAsStream failed");
ioex.initCause(e);
throw ioex;
}
}
}
);
} catch (PrivilegedActionException e) {
throw (IOException)e.getException();
}
}
private static URL[] getResources(final ClassLoader cl, final String name) {
return AccessController.doPrivileged(new PrivilegedAction<URL[]>() {
@Override
public URL[] run() {
URL[] ret = null;
try {
List<URL> v = Collections.list(cl.getResources(name));
if (!v.isEmpty()) {
ret = new URL[v.size()];
v.toArray(ret);
}
} catch (IOException ioex) {
} catch (SecurityException ex) { }
return ret;
}
});
}
private static URL[] getSystemResources(final String name) {
return AccessController.doPrivileged(new PrivilegedAction<URL[]>() {
@Override
public URL[] run() {
URL[] ret = null;
try {
List<URL> v = Collections.list(
ClassLoader.getSystemResources(name));
if (!v.isEmpty()) {
ret = new URL[v.size()];
v.toArray(ret);
}
} catch (IOException ioex) {
} catch (SecurityException ex) { }
return ret;
}
});
}
private static InputStream openStream(final URL url) throws IOException {
try {
return AccessController.doPrivileged(
new PrivilegedExceptionAction<InputStream>() {
@Override
public InputStream run() throws IOException {
return url.openStream();
}
}
);
} catch (PrivilegedActionException e) {
throw (IOException)e.getException();
}
}
EventQueue getEventQueue() {
return q;
}
}
Support interface to generalize
code that loads resources from stream.
/**
* Support interface to generalize
* code that loads resources from stream.
*/
interface StreamLoader {
public void load(InputStream is) throws IOException;
}