Skip to content

Package: Session$7

Session$7

nameinstructionbranchcomplexitylinemethod
run()
M: 24 C: 0
0%
M: 2 C: 0
0%
M: 2 C: 0
0%
M: 9 C: 0
0%
M: 1 C: 0
0%
{...}
M: 6 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 1 C: 0
0%
M: 1 C: 0
0%

Coverage

1: /*
2: * Copyright (c) 1997, 2023 Oracle and/or its affiliates. All rights reserved.
3: *
4: * This program and the accompanying materials are made available under the
5: * terms of the Eclipse Public License v. 2.0, which is available at
6: * http://www.eclipse.org/legal/epl-2.0.
7: *
8: * This Source Code may also be made available under the following Secondary
9: * Licenses when the conditions for such availability set forth in the
10: * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
11: * version 2 with the GNU Classpath Exception, which is available at
12: * https://www.gnu.org/software/classpath/license.html.
13: *
14: * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
15: */
16:
17: package jakarta.mail;
18:
19: import java.io.BufferedInputStream;
20: import java.io.File;
21: import java.io.FileInputStream;
22: import java.io.FileNotFoundException;
23: import java.io.IOException;
24: import java.io.InputStream;
25: import java.io.PrintStream;
26: import java.lang.annotation.Annotation;
27: import java.lang.reflect.Constructor;
28: import java.lang.reflect.Method;
29: import java.net.InetAddress;
30: import java.net.URL;
31: import java.security.AccessController;
32: import java.security.PrivilegedAction;
33: import java.security.PrivilegedActionException;
34: import java.security.PrivilegedExceptionAction;
35: import java.util.ArrayList;
36: import java.util.Collections;
37: import java.util.HashMap;
38: import java.util.Hashtable;
39: import java.util.Iterator;
40: import java.util.List;
41: import java.util.Map;
42: import java.util.Properties;
43: import java.util.ServiceLoader;
44: import java.util.StringTokenizer;
45: import java.util.concurrent.Executor;
46: import java.util.logging.Level;
47:
48: import jakarta.mail.util.LineInputStream;
49: import jakarta.mail.util.StreamProvider;
50:
51: /**
52: * The Session class represents a mail session and is not subclassed.
53: * It collects together properties and defaults used by the mail API's.
54: * A single default session can be shared by multiple applications on the
55: * desktop. Unshared sessions can also be created. <p>
56: *
57: * The Session class provides access to the protocol providers that
58: * implement the <code>Store</code>, <code>Transport</code>, and related
59: * classes. The protocol providers are configured using the following files:
60: * <ul>
61: * <li> <code>javamail.providers</code> and
62: *         <code>javamail.default.providers</code> </li>
63: * <li> <code>javamail.address.map</code> and
64: *         <code>javamail.default.address.map</code> </li>
65: * </ul>
66: * <p>
67: * Each <code>javamail.</code><i>X</i> resource file is searched for using
68: * three methods in the following order:
69: * <ol>
70: * <li> <code><i>java.home</i>/<i>conf</i>/javamail.</code><i>X</i> </li>
71: * <li> <code>META-INF/javamail.</code><i>X</i> </li>
72: * <li> <code>META-INF/javamail.default.</code><i>X</i> </li>
73: * </ol>
74: * <p>
75: * (Where <i>java.home</i> is the value of the "java.home" System property
76: * and <i>conf</i> is the directory named "conf" if it exists,
77: * otherwise the directory named "lib"; the "conf" directory was
78: * introduced in JDK 1.9.)
79: * <p>
80: * The first method allows the user to include their own version of the
81: * resource file by placing it in the <i>conf</i> directory where the
82: * <code>java.home</code> property points. The second method allows an
83: * application that uses the Jakarta Mail APIs to include their own resource
84: * files in their application's or jar file's <code>META-INF</code>
85: * directory. The <code>javamail.default.</code><i>X</i> default files
86: * are part of the Jakarta Mail <code>mail.jar</code> file and should not be
87: * supplied by users. <p>
88: *
89: * File location depends upon how the <code>ClassLoader</code> method
90: * <code>getResource</code> is implemented. Usually, the
91: * <code>getResource</code> method searches through CLASSPATH until it
92: * finds the requested file and then stops. <p>
93: *
94: * The ordering of entries in the resource files matters. If multiple
95: * entries exist, the first entries take precedence over the later
96: * entries. For example, the first IMAP provider found will be set as the
97: * default IMAP implementation until explicitly changed by the
98: * application. The user- or system-supplied resource files augment, they
99: * do not override, the default files included with the Jakarta Mail APIs.
100: * This means that all entries in all files loaded will be available. <p>
101: *
102: * <b><code>javamail.providers</code></b> and
103: * <b><code>javamail.default.providers</code></b><p>
104: *
105: * These resource files specify the stores and transports that are
106: * available on the system, allowing an application to "discover" what
107: * store and transport implementations are available. The protocol
108: * implementations are listed one per line. The file format defines four
109: * attributes that describe a protocol implementation. Each attribute is
110: * an "="-separated name-value pair with the name in lowercase. Each
111: * name-value pair is semi-colon (";") separated. The following names
112: * are defined.
113: *
114: * <table border=1>
115: * <caption>
116: * Attribute Names in Providers Files
117: * </caption>
118: * <tr>
119: * <th>Name</th><th>Description</th>
120: * </tr>
121: * <tr>
122: * <td>protocol</td>
123: * <td>Name assigned to protocol.
124: * For example, <code>smtp</code> for Transport.</td>
125: * </tr>
126: * <tr>
127: * <td>type</td>
128: * <td>Valid entries are <code>store</code> and <code>transport</code>.</td>
129: * </tr>
130: * <tr>
131: * <td>class</td>
132: * <td>Class name that implements this protocol.</td>
133: * </tr>
134: * <tr>
135: * <td>vendor</td>
136: * <td>Optional string identifying the vendor.</td>
137: * </tr>
138: * <tr>
139: * <td>version</td>
140: * <td>Optional string identifying the version.</td>
141: * </tr>
142: * </table><p>
143: *
144: * Here's an example of <code>META-INF/javamail.default.providers</code>
145: * file contents:
146: * <pre>
147: * protocol=imap; type=store; class=com.sun.mail.imap.IMAPStore; vendor=Oracle;
148: * protocol=smtp; type=transport; class=com.sun.mail.smtp.SMTPTransport; vendor=Oracle;
149: * </pre><p>
150: *
151: * The current implementation also supports configuring providers using
152: * the Java SE {@link java.util.ServiceLoader ServiceLoader} mechanism.
153: * When creating your own provider, create a {@link Provider} subclass,
154: * for example:
155: * <pre>
156: * package com.example;
157: *
158: * import jakarta.mail.Provider;
159: *
160: * public class MyProvider extends Provider {
161: * public MyProvider() {
162: * super(Provider.Type.STORE, "myprot", MyStore.class.getName(),
163: * "Example", null);
164: * }
165: * }
166: * </pre>
167: * Then include a file named <code>META-INF/services/jakarta.mail.Provider</code>
168: * in your jar file that lists the name of your Provider class:
169: * <pre>
170: * com.example.MyProvider
171: * </pre>
172: * <p>
173: *
174: * <b><code>javamail.address.map</code></b> and
175: * <b><code>javamail.default.address.map</code></b><p>
176: *
177: * These resource files map transport address types to the transport
178: * protocol. The <code>getType</code> method of
179: * <code>jakarta.mail.Address</code> returns the address type. The
180: * <code>javamail.address.map</code> file maps the transport type to the
181: * protocol. The file format is a series of name-value pairs. Each key
182: * name should correspond to an address type that is currently installed
183: * on the system; there should also be an entry for each
184: * <code>jakarta.mail.Address</code> implementation that is present if it is
185: * to be used. For example, the
186: * <code>jakarta.mail.internet.InternetAddress</code> method
187: * <code>getType</code> returns "rfc822". Each referenced protocol should
188: * be installed on the system. For the case of <code>news</code>, below,
189: * the client should install a Transport provider supporting the nntp
190: * protocol. <p>
191: *
192: * Here are the typical contents of a <code>javamail.address.map</code> file:
193: * <pre>
194: * rfc822=smtp
195: * news=nntp
196: * </pre>
197: *
198: * @author John Mani
199: * @author Bill Shannon
200: * @author Max Spivak
201: */
202:
203: public final class Session {
204:
205:         // Support legacy @DefaultProvider
206:         private static final String DEFAULT_PROVIDER = "com.sun.mail.util.DefaultProvider";
207:
208:         private final StreamProvider streamProvider;
209: private final Properties props;
210: private final Authenticator authenticator;
211: private final Hashtable<URLName, PasswordAuthentication> authTable
212:          = new Hashtable<>();
213: private boolean debug = false;
214: private PrintStream out;                        // debug output stream
215: private MailLogger logger;
216: private final List<Provider> providers = new ArrayList<>();
217: private final Map<String, Provider> providersByProtocol = new HashMap<>();
218: private final Map<String, Provider> providersByClassName = new HashMap<>();
219: private final Properties addressMap = new Properties();
220:                                                 // maps type to protocol
221: // the queue of events to be delivered, if mail.event.scope===session
222: private final EventQueue q;
223:
224: // The default session.
225: private static Session defaultSession = null;
226:
227: private static final String confDir;
228:
229: static {
230:                 String dir = null;
231:                 try {
232:                  dir = AccessController.doPrivileged(
233:                         new PrivilegedAction<String>() {
234:                          @Override
235:                          public String run() {
236:                                 String home = System.getProperty("java.home");
237:                                 String newdir = home + File.separator + "conf";
238:                                 File conf = new File(newdir);
239:                                 if (conf.exists())
240:                                  return newdir + File.separator;
241:                                 else
242:                                  return home + File.separator +
243:                                          "lib" + File.separator;
244:                          }
245:                         });
246:                 } catch (Exception ex) {
247:                  // ignore any exceptions
248:                 }
249:                 confDir = dir;
250: }
251:
252: // Constructor is not public
253: private Session(Properties props, Authenticator authenticator) {
254:                 this.props = props;
255:                 this.authenticator = authenticator;
256:                 this.streamProvider = StreamProvider.provider();
257:         
258:                 if (Boolean.valueOf(props.getProperty("mail.debug")).booleanValue())
259:                  debug = true;
260:         
261:                 initLogger();
262:                 logger.log(Level.CONFIG, "Jakarta Mail version {0}", Version.version);
263:         
264:                 // get the Class associated with the Authenticator
265:                 Class<?> cl;
266:                 if (authenticator != null) {
267:                  cl = authenticator.getClass();
268:                 } else {
269:                  // Use implementation class, because that class loader has access to jakarta.mail module and implementation resources
270:                  cl = streamProvider.getClass();
271:                 }
272:                 // load the resources
273:                 loadProviders(cl);
274:                 loadAddressMap(cl);
275:                 q = new EventQueue((Executor)props.get("mail.event.executor"));
276: }
277:
278: /**
279: * Get the stream provider instance of the session.
280: *
281: * @return the stream provider
282: *
283: * @since JavaMail 2.1
284: */
285: public StreamProvider getStreamProvider() {
286: return streamProvider;
287: }
288:
289: private final synchronized void initLogger() {
290:         logger = new MailLogger(this.getClass(), "DEBUG", debug, getDebugOut());
291: }
292:
293: /**
294: * Get a new Session object.
295: *
296: * @param        props        Properties object that hold relevant properties.<br>
297: * It is expected that the client supplies values
298: * for the properties listed in Appendix A of the
299: * Jakarta Mail spec (particularly mail.store.protocol,
300: * mail.transport.protocol, mail.host, mail.user,
301: * and mail.from) as the defaults are unlikely to
302: * work in all cases.
303: * @param        authenticator Authenticator object used to call back to
304: *                        the application when a user name and password is
305: *                        needed.
306: * @return                a new Session object
307: * @see        jakarta.mail.Authenticator
308: */
309: public static Session getInstance(Properties props, Authenticator authenticator) {
310:         return new Session(props, authenticator);
311: }
312:
313: /**
314: * Get a new Session object.
315: *
316: * @param        props        Properties object that hold relevant properties.<br>
317: * It is expected that the client supplies values
318: * for the properties listed in Appendix A of the
319: * Jakarta Mail spec (particularly mail.store.protocol,
320: * mail.transport.protocol, mail.host, mail.user,
321: * and mail.from) as the defaults are unlikely to
322: * work in all cases.
323: * @return                a new Session object
324: * @since                JavaMail 1.2
325: */
326: public static Session getInstance(Properties props) {
327:         return new Session(props, null);
328: }
329:
330: /**
331: * Get the default Session object. If a default has not yet been
332: * setup, a new Session object is created and installed as the
333: * default. <p>
334: *
335: * Since the default session is potentially available to all
336: * code executing in the same Java virtual machine, and the session
337: * can contain security sensitive information such as user names
338: * and passwords, access to the default session is restricted.
339: * The Authenticator object, which must be created by the caller,
340: * is used indirectly to check access permission. The Authenticator
341: * object passed in when the session is created is compared with
342: * the Authenticator object passed in to subsequent requests to
343: * get the default session. If both objects are the same, or are
344: * from the same ClassLoader, the request is allowed. Otherwise,
345: * it is denied. <p>
346: *
347: * Note that if the Authenticator object used to create the session
348: * is null, anyone can get the default session by passing in null. <p>
349: *
350: * Note also that the Properties object is used only the first time
351: * this method is called, when a new Session object is created.
352: * Subsequent calls return the Session object that was created by the
353: * first call, and ignore the passed Properties object. Use the
354: * <code>getInstance</code> method to get a new Session object every
355: * time the method is called. <p>
356: *
357: * Additional security Permission objects may be used to
358: * control access to the default session. <p>
359: *
360: * In the current implementation, if a SecurityManager is set, the
361: * caller must have the <code>RuntimePermission("setFactory")</code>
362: * permission.
363: *
364: * @param        props        Properties object. Used only if a new Session
365: *                        object is created.<br>
366: * It is expected that the client supplies values
367: * for the properties listed in Appendix A of the
368: * Jakarta Mail spec (particularly mail.store.protocol,
369: * mail.transport.protocol, mail.host, mail.user,
370: * and mail.from) as the defaults are unlikely to
371: * work in all cases.
372: * @param        authenticator Authenticator object. Used only if a
373: *                        new Session object is created. Otherwise,
374: *                        it must match the Authenticator used to create
375: *                        the Session.
376: * @return                the default Session object
377: */
378: public static synchronized Session getDefaultInstance(Properties props, Authenticator authenticator) {
379:                 if (defaultSession == null) {
380:                  SecurityManager security = System.getSecurityManager();
381:                  if (security != null)
382:                         security.checkSetFactory();
383:                  defaultSession = new Session(props, authenticator);
384:                 } else {
385:                  // have to check whether caller is allowed to see default session
386:                  if (defaultSession.authenticator == authenticator)
387:                                 // either same object or both null, either way OK
388:                  else if (defaultSession.authenticator != null &&
389:                          authenticator != null &&
390:                          defaultSession.authenticator.getClass().getClassLoader() ==
391:                                 authenticator.getClass().getClassLoader())
392:                                 // both objects came from the same class loader, OK
393:                  else
394:                         // anything else is not allowed
395:                         throw new SecurityException("Access to default session denied");
396:                 }
397:         
398:                 return defaultSession;
399: }
400:
401: /**
402: * Get the default Session object. If a default has not yet been
403: * setup, a new Session object is created and installed as the
404: * default. <p>
405: *
406: * Note that a default session created with no Authenticator is
407: * available to all code executing in the same Java virtual
408: * machine, and the session can contain security sensitive
409: * information such as user names and passwords.
410: *
411: * @param        props        Properties object. Used only if a new Session
412: *                        object is created.<br>
413: * It is expected that the client supplies values
414: * for the properties listed in Appendix A of the
415: * Jakarta Mail spec (particularly mail.store.protocol,
416: * mail.transport.protocol, mail.host, mail.user,
417: * and mail.from) as the defaults are unlikely to
418: * work in all cases.
419: * @return                the default Session object
420: * @since                JavaMail 1.2
421: */
422: public static Session getDefaultInstance(Properties props) {
423: return getDefaultInstance(props, null);
424: }
425:
426: /**
427: * Set the debug setting for this Session.
428: * <p>
429: * Since the debug setting can be turned on only after the Session
430: * has been created, to turn on debugging in the Session
431: * constructor, set the property <code>mail.debug</code> in the
432: * Properties object passed in to the constructor to true. The
433: * value of the <code>mail.debug</code> property is used to
434: * initialize the per-Session debugging flag. Subsequent calls to
435: * the <code>setDebug</code> method manipulate the per-Session
436: * debugging flag and have no effect on the <code>mail.debug</code>
437: * property.
438: *
439: * @param debug        Debug setting
440: */
441: public synchronized void setDebug(boolean debug) {
442:                 this.debug = debug;
443:                 initLogger();
444:                 logger.log(Level.CONFIG, "setDebug: Jakarta Mail version {0}", Version.version);
445: }
446:
447: /**
448: * Get the debug setting for this Session.
449: *
450: * @return current debug setting
451: */
452: public synchronized boolean getDebug() {
453:         return debug;
454: }
455:
456: /**
457: * Set the stream to be used for debugging output for this session.
458: * If <code>out</code> is null, <code>System.out</code> will be used.
459: * Note that debugging output that occurs before any session is created,
460: * as a result of setting the <code>mail.debug</code> system property,
461: * will always be sent to <code>System.out</code>.
462: *
463: * @param        out        the PrintStream to use for debugging output
464: * @since                JavaMail 1.3
465: */
466: public synchronized void setDebugOut(PrintStream out) {
467:                 this.out = out;
468:                 initLogger();
469: }
470:
471: /**
472: * Returns the stream to be used for debugging output. If no stream
473: * has been set, <code>System.out</code> is returned.
474: *
475: * @return                the PrintStream to use for debugging output
476: * @since                JavaMail 1.3
477: */
478: public synchronized PrintStream getDebugOut() {
479:                 if (out == null)
480:                  return System.out;
481:                 else
482:                  return out;
483: }
484:
485: /**
486: * This method returns an array of all the implementations installed
487: * via the javamail.[default.]providers files that can
488: * be loaded using the ClassLoader available to this application.
489: *
490: * @return Array of configured providers
491: */
492: public synchronized Provider[] getProviders() {
493:                 Provider[] _providers = new Provider[providers.size()];
494:                 providers.toArray(_providers);
495:                 return _providers;
496: }
497:
498: /**
499: * Returns the default Provider for the protocol
500: * specified. Checks mail.<protocol>.class property
501: * first and if it exists, returns the Provider
502: * associated with this implementation. If it doesn't exist,
503: * returns the Provider that appeared first in the
504: * configuration files. If an implementation for the protocol
505: * isn't found, throws NoSuchProviderException
506: *
507: * @param protocol Configured protocol (i.e. smtp, imap, etc)
508: * @return Currently configured Provider for the specified protocol
509: * @exception        NoSuchProviderException If a provider for the given
510: *                        protocol is not found.
511: */
512: public synchronized Provider getProvider(String protocol) throws NoSuchProviderException {
513:
514:                 if (protocol == null || protocol.length() <= 0) {
515:                  throw new NoSuchProviderException("Invalid protocol: null");
516:                 }
517:         
518:                 Provider _provider = null;
519:         
520:                 // check if the mail.<protocol>.class property exists
521:                 String _className = props.getProperty("mail."+protocol+".class");
522:                 if (_className != null) {
523:                  if (logger.isLoggable(Level.FINE)) {
524:                         logger.fine("mail."+protocol+
525:                                          ".class property exists and points to " +
526:                                          _className);
527:                  }
528:                  _provider = providersByClassName.get(_className);
529:                 }
530:         
531:                 if (_provider != null) {
532:                  return _provider;
533:                 } else {
534:                  // returning currently default protocol in providersByProtocol
535:                  _provider = providersByProtocol.get(protocol);
536:                 }
537:         
538:                 if (_provider == null) {
539:                  throw new NoSuchProviderException("No provider for " + protocol);
540:                 } else {
541:                  if (logger.isLoggable(Level.FINE)) {
542:                         logger.fine("getProvider() returning " + _provider.toString());
543:                  }
544:                  return _provider;
545:                 }
546: }
547:
548: /**
549: * Set the passed Provider to be the default implementation
550: * for the protocol in Provider.protocol overriding any previous values.
551: *
552: * @param provider Currently configured Provider which will be
553: * set as the default for the protocol
554: * @exception        NoSuchProviderException If the provider passed in
555: *                        is invalid.
556: */
557: public synchronized void setProvider(Provider provider)
558:                                 throws NoSuchProviderException {
559:                 if (provider == null) {
560:                  throw new NoSuchProviderException("Can't set null provider");
561:                 }
562:                 providersByProtocol.put(provider.getProtocol(), provider);
563:                 providersByClassName.put(provider.getClassName(), provider);
564:                 props.put("mail." + provider.getProtocol() + ".class", provider.getClassName());
565: }
566:
567:
568: /**
569: * Get a Store object that implements this user's desired Store
570: * protocol. The <code>mail.store.protocol</code> property specifies the
571: * desired protocol. If an appropriate Store object is not obtained,
572: * NoSuchProviderException is thrown
573: *
574: * @return                 a Store object
575: * @exception        NoSuchProviderException If a provider for the given
576: *                        protocol is not found.
577: */
578: public Store getStore() throws NoSuchProviderException {
579:         return getStore(getProperty("mail.store.protocol"));
580: }
581:
582: /**
583: * Get a Store object that implements the specified protocol. If an
584: * appropriate Store object cannot be obtained,
585: * NoSuchProviderException is thrown.
586: *
587: * @param         protocol        the Store protocol
588: * @return                a Store object
589: * @exception        NoSuchProviderException If a provider for the given
590: *                        protocol is not found.
591: */
592: public Store getStore(String protocol) throws NoSuchProviderException {
593:         return getStore(new URLName(protocol, null, -1, null, null, null));
594: }
595:
596:
597: /**
598: * Get a Store object for the given URLName. If the requested Store
599: * object cannot be obtained, NoSuchProviderException is thrown.
600: *
601: * The "scheme" part of the URL string (Refer RFC 1738) is used
602: * to locate the Store protocol.
603: *
604: * @param        url        URLName that represents the desired Store
605: * @return                a closed Store object
606: * @see                #getFolder(URLName)
607: * @see                jakarta.mail.URLName
608: * @exception        NoSuchProviderException If a provider for the given
609: *                        URLName is not found.
610: */
611: public Store getStore(URLName url) throws NoSuchProviderException {
612:                 String protocol = url.getProtocol();
613:                 Provider p = getProvider(protocol);
614:                 return getStore(p, url);
615: }
616:
617: /**
618: * Get an instance of the store specified by Provider. Instantiates
619: * the store and returns it.
620: *
621: * @param provider Store Provider that will be instantiated
622: * @return Instantiated Store
623: * @exception        NoSuchProviderException If a provider for the given
624: *                        Provider is not found.
625: */
626: public Store getStore(Provider provider) throws NoSuchProviderException {
627:         return getStore(provider, null);
628: }
629:
630:
631: /**
632: * Get an instance of the store specified by Provider. If the URLName
633: * is not null, uses it, otherwise creates a new one. Instantiates
634: * the store and returns it. This is a private method used by
635: * getStore(Provider) and getStore(URLName)
636: *
637: * @param provider Store Provider that will be instantiated
638: * @param url URLName used to instantiate the Store
639: * @return Instantiated Store
640: * @exception        NoSuchProviderException If a provider for the given
641: *                        Provider/URLName is not found.
642: */
643: private Store getStore(Provider provider, URLName url) throws NoSuchProviderException {
644:
645:                 // make sure we have the correct type of provider
646:                 if (provider == null || provider.getType() != Provider.Type.STORE ) {
647:                  throw new NoSuchProviderException("invalid provider");
648:                 }
649:         
650:                 return getService(provider, url, Store.class);
651: }
652:
653: /**
654: * Get a closed Folder object for the given URLName. If the requested
655: * Folder object cannot be obtained, null is returned. <p>
656: *
657: * The "scheme" part of the URL string (Refer RFC 1738) is used
658: * to locate the Store protocol. The rest of the URL string (that is,
659: * the "schemepart", as per RFC 1738) is used by that Store
660: * in a protocol dependent manner to locate and instantiate the
661: * appropriate Folder object. <p>
662: *
663: * Note that RFC 1738 also specifies the syntax for the
664: * "schemepart" for IP-based protocols (IMAP4, POP3, etc.).
665: * Providers of IP-based mail Stores should implement that
666: * syntax for referring to Folders.
667: *
668: * @param        url        URLName that represents the desired folder
669: * @return                Folder
670: * @see                #getStore(URLName)
671: * @see                jakarta.mail.URLName
672: * @exception        NoSuchProviderException If a provider for the given
673: *                        URLName is not found.
674: * @exception        MessagingException if the Folder could not be
675: *                        located or created.
676: */
677: public Folder getFolder(URLName url) throws MessagingException {
678:                 // First get the Store
679:                 Store store = getStore(url);
680:                 store.connect();
681:                 return store.getFolder(url);
682: }
683:
684: /**
685: * Get a Transport object that implements this user's desired
686: * Transport protcol. The <code>mail.transport.protocol</code> property
687: * specifies the desired protocol. If an appropriate Transport
688: * object cannot be obtained, MessagingException is thrown.
689: *
690: * @return                 a Transport object
691: * @exception        NoSuchProviderException If the provider is not found.
692: */
693: public Transport getTransport() throws NoSuchProviderException {
694:                 String prot = getProperty("mail.transport.protocol");
695:                 if (prot != null)
696:                  return getTransport(prot);
697:                 // if the property isn't set, use the protocol for "rfc822"
698:                 prot = (String)addressMap.get("rfc822");
699:                 if (prot != null)
700:                  return getTransport(prot);
701:                 return getTransport("smtp");        // if all else fails
702: }
703:
704: /**
705: * Get a Transport object that implements the specified protocol.
706: * If an appropriate Transport object cannot be obtained, null is
707: * returned.
708: *
709: * @param        protocol the Transport protocol
710: * @return                 a Transport object
711: * @exception        NoSuchProviderException If provider for the given
712: *                        protocol is not found.
713: */
714: public Transport getTransport(String protocol)
715:                                 throws NoSuchProviderException {
716:         return getTransport(new URLName(protocol, null, -1, null, null, null));
717: }
718:
719:
720: /**
721: * Get a Transport object for the given URLName. If the requested
722: * Transport object cannot be obtained, NoSuchProviderException is thrown.
723: *
724: * The "scheme" part of the URL string (Refer RFC 1738) is used
725: * to locate the Transport protocol.
726: *
727: * @param        url        URLName that represents the desired Transport
728: * @return                a closed Transport object
729: * @see                jakarta.mail.URLName
730: * @exception        NoSuchProviderException If a provider for the given
731: *                        URLName is not found.
732: */
733: public Transport getTransport(URLName url) throws NoSuchProviderException {
734:                 String protocol = url.getProtocol();
735:                 Provider p = getProvider(protocol);
736:                 return getTransport(p, url);
737: }
738:
739: /**
740: * Get an instance of the transport specified in the Provider. Instantiates
741: * the transport and returns it.
742: *
743: * @param provider Transport Provider that will be instantiated
744: * @return Instantiated Transport
745: * @exception        NoSuchProviderException If provider for the given
746: *                        provider is not found.
747: */
748: public Transport getTransport(Provider provider) throws NoSuchProviderException {
749:         return getTransport(provider, null);
750: }
751:
752: /**
753: * Get a Transport object that can transport a Message of the
754: * specified address type.
755: *
756: * @param        address        an address for which a Transport is needed
757: * @return        A Transport object
758: * @see jakarta.mail.Address
759: * @exception        NoSuchProviderException If provider for the
760: *                        Address type is not found
761: */
762: public Transport getTransport(Address address) throws NoSuchProviderException {
763:
764:                 String transportProtocol;
765:                 transportProtocol =
766:                  getProperty("mail.transport.protocol." + address.getType());
767:                 if (transportProtocol != null)
768:                  return getTransport(transportProtocol);
769:                 transportProtocol = (String)addressMap.get(address.getType());
770:                 if (transportProtocol != null)
771:                  return getTransport(transportProtocol);
772:                 throw new NoSuchProviderException("No provider for Address type: " + address.getType());
773: }
774:
775: /**
776: * Get a Transport object using the given provider and urlname.
777: *
778: * @param        provider        the provider to use
779: * @param        url                urlname to use (can be null)
780: * @return A Transport object
781: * @exception        NoSuchProviderException        If no provider or the provider
782: *                        was the wrong class.        
783: */
784:
785: private Transport getTransport(Provider provider, URLName url) throws NoSuchProviderException {
786:                 // make sure we have the correct type of provider
787:                 if (provider == null || provider.getType() != Provider.Type.TRANSPORT) {
788:                  throw new NoSuchProviderException("invalid provider");
789:                 }
790:         
791:                 return getService(provider, url, Transport.class);
792: }
793:
794: /**
795: * Get a Service object. Needs a provider object, but will
796: * create a URLName if needed. It attempts to instantiate
797: * the correct class.
798: *
799: * @param provider        which provider to use
800: * @param url        which URLName to use (can be null)
801: * @param type        the service type (class)
802: * @exception        NoSuchProviderException        thrown when the class cannot be
803: *                        found or when it does not have the correct constructor
804: *                        (Session, URLName), or if it is not derived from
805: *                        Service.
806: */
807: private <T extends Service> T getService(Provider provider, URLName url, Class<T> type) throws NoSuchProviderException {
808:                 // need a provider and url
809:                 if (provider == null) {
810:                  throw new NoSuchProviderException("null");
811:                 }
812:         
813:                 // create a url if needed
814:                 if (url == null) {
815:                  url = new URLName(provider.getProtocol(), null, -1,
816:                                  null, null, null);
817:                 }
818:         
819:                 Object service = null;
820:                 
821:                 // get the ClassLoader associated with the Authenticator
822:                 ClassLoader cl;
823:                 if (authenticator != null)
824:                  cl = authenticator.getClass().getClassLoader();
825:                 else
826:                  cl = this.getClass().getClassLoader();
827:         
828:                 // now load the class
829:                 Class<?> serviceClass = null;
830:                 try {
831:                  // First try the "application's" class loader.
832:                  ClassLoader ccl = getContextClassLoader();
833:                  if (ccl != null)
834:                         try {
835:                          serviceClass =
836:                                 Class.forName(provider.getClassName(), false, ccl);
837:                         } catch (ClassNotFoundException ex) {
838:                          // ignore it
839:                         }
840:                  if (serviceClass == null || !type.isAssignableFrom(serviceClass))
841:                         serviceClass =
842:                          Class.forName(provider.getClassName(), false, cl);
843:         
844:                  if (!type.isAssignableFrom(serviceClass))
845:                         throw new ClassCastException(
846:                                         type.getName() + " " + serviceClass.getName());
847:                 } catch (Exception ex1) {
848:                  // That didn't work, now try the "system" class loader.
849:                  // (Need both of these because JDK 1.1 class loaders
850:                  // may not delegate to their parent class loader.)
851:                  try {
852:                         serviceClass = Class.forName(provider.getClassName());
853:                         if (!type.isAssignableFrom(serviceClass))
854:                          throw new ClassCastException(
855:                                         type.getName() + " " + serviceClass.getName());
856:                  } catch (Exception ex) {
857:                         // Nothing worked, give up.
858:                         logger.log(Level.FINE, "Exception loading provider", ex);
859:                         throw new NoSuchProviderException(provider.getProtocol());
860:                  }
861:                 }
862:         
863:                 // construct an instance of the class
864:                 try {
865:                  Class<?>[] c = {jakarta.mail.Session.class, jakarta.mail.URLName.class};
866:                  Constructor<?> cons = serviceClass.getConstructor(c);
867:         
868:                  Object[] o = {this, url};
869:                  service = cons.newInstance(o);
870:         
871:                 } catch (Exception ex) {
872:                  logger.log(Level.FINE, "Exception loading provider", ex);
873:                  throw new NoSuchProviderException(provider.getProtocol());
874:                 }
875:         
876:                 return type.cast(service);
877: }
878:
879: /**
880: * Save a PasswordAuthentication for this (store or transport) URLName.
881: * If pw is null the entry corresponding to the URLName is removed.
882: * <p>
883: * This is normally used only by the store or transport implementations
884: * to allow authentication information to be shared among multiple
885: * uses of a session.
886: *
887: * @param        url        the URLName
888: * @param        pw        the PasswordAuthentication to save
889: */
890: public void setPasswordAuthentication(URLName url, PasswordAuthentication pw) {
891:                 if (pw == null)
892:                  authTable.remove(url);
893:                 else
894:                  authTable.put(url, pw);
895: }
896:
897: /**
898: * Return any saved PasswordAuthentication for this (store or transport)
899: * URLName. Normally used only by store or transport implementations.
900: *
901: * @param        url        the URLName
902: * @return        the PasswordAuthentication corresponding to the URLName
903: */
904: public PasswordAuthentication getPasswordAuthentication(URLName url) {
905:         return authTable.get(url);
906: }
907:
908: /**
909: * Call back to the application to get the needed user name and password.
910: * The application should put up a dialog something like:
911: * <pre>
912: * Connecting to <protocol> mail service on host <addr>, port <port>.
913: * <prompt>
914: *
915: * User Name: <defaultUserName>
916: * Password:
917: * </pre>
918: *
919: * @param        addr                InetAddress of the host. may be null.
920: * @param        port                the port on the host
921: * @param        protocol        protocol scheme (e.g. imap, pop3, etc.)
922: * @param        prompt                any additional String to show as part of
923: * the prompt; may be null.
924: * @param        defaultUserName        the default username. may be null.
925: * @return        the authentication which was collected by the authenticator;
926: * may be null.
927: */
928: public PasswordAuthentication requestPasswordAuthentication(InetAddress addr, int port, String protocol, String prompt, String defaultUserName) {
929:                 if (authenticator != null) {
930:                  return authenticator.requestPasswordAuthentication(
931:                         addr, port, protocol, prompt, defaultUserName);
932:                 } else {
933:                  return null;
934:                 }
935: }
936:
937: /**
938: * Returns the Properties object associated with this Session
939: *
940: * @return                Properties object
941: */
942: public Properties getProperties() {
943:         return props;
944: }
945:
946: /**
947: * Returns the value of the specified property. Returns null
948: * if this property does not exist.
949: *
950: * @param        name        the property name
951: * @return                String that is the property value
952: */
953: public String getProperty(String name) {
954:         return props.getProperty(name);
955: }
956:
957: static boolean containsDefaultProvider(Provider provider) {
958:         Annotation[] annotations = provider.getClass().getDeclaredAnnotations();
959:         for (Annotation annotation : annotations) {
960:                 if (DEFAULT_PROVIDER.equals(annotation.annotationType().getName())) {
961:                         return true;
962:                 }
963:         }
964:         return false;
965: }
966:
967: /**
968: * Load the protocol providers config files.
969: */
970: private void loadProviders(Class<?> cl) {
971:                 StreamLoader loader = new StreamLoader() {
972:                  @Override
973:                  public void load(InputStream is) throws IOException {
974:                          loadProvidersFromStream(is);
975:                  }
976:                 };
977:         
978:                 // load system-wide javamail.providers from the
979:                 // <java.home>/{conf,lib} directory
980:                 try {
981:                  if (confDir != null)
982:                         loadFile(confDir + "javamail.providers", loader);
983:                 } catch (SecurityException ex) {}
984:         
985:                 // next, add all the non-default services
986:                 ServiceLoader<Provider> sl = ServiceLoader.load(Provider.class);
987:                 for (Provider p : sl) {
988:                  if (!containsDefaultProvider(p))
989:                          addProvider(p);
990:                 }
991:
992:                 // + handle Glassfish/OSGi (platform specific default)
993:                 if (isHk2Available()) {
994:                         Iterator<Provider> iter = lookupUsingHk2ServiceLoader(Provider.class.getName());
995:                         while (iter.hasNext()) {
996:                                 Provider p = iter.next();
997:                                 if (!containsDefaultProvider(p))
998:                                         addProvider(p);
999:                         }
1000:                 }
1001:
1002:                 // load the META-INF/javamail.providers file supplied by an application
1003:                 loadAllResources("META-INF/javamail.providers", cl, loader);
1004:         
1005:                 // load default META-INF/javamail.default.providers from mail.jar file
1006:                 loadResource("/META-INF/javamail.default.providers", cl, loader, false);
1007:         
1008:                 // finally, add all the default services
1009:                 sl = ServiceLoader.load(Provider.class);
1010:                 for (Provider p : sl) {
1011:                  if (containsDefaultProvider(p))
1012:                          addProvider(p);
1013:                 }
1014:
1015:                 // + handle Glassfish/OSGi (platform specific default)
1016:                 if (isHk2Available()) {
1017:                         Iterator<Provider> iter = lookupUsingHk2ServiceLoader(Provider.class.getName());
1018:                         while (iter.hasNext()) {
1019:                                 Provider p = iter.next();
1020:                                 if (containsDefaultProvider(p)) {
1021:                                         addProvider(p);
1022:                                 }
1023:                         }
1024:                 }
1025:
1026:                 /*
1027:                  * If we haven't loaded any providers, fake it.
1028:                  */
1029:                 if (providers.size() == 0) {
1030:                  logger.config("failed to load any providers, using defaults");
1031:                  // failed to load any providers, initialize with our defaults
1032:                  addProvider(new Provider(Provider.Type.STORE,
1033:                                 "imap", "com.sun.mail.imap.IMAPStore",
1034:                                 "Oracle", Version.version));
1035:                  addProvider(new Provider(Provider.Type.STORE,
1036:                                 "imaps", "com.sun.mail.imap.IMAPSSLStore",
1037:                                 "Oracle", Version.version));
1038:                  addProvider(new Provider(Provider.Type.STORE,
1039:                                 "pop3", "com.sun.mail.pop3.POP3Store",
1040:                                 "Oracle", Version.version));
1041:                  addProvider(new Provider(Provider.Type.STORE,
1042:                                 "pop3s", "com.sun.mail.pop3.POP3SSLStore",
1043:                                 "Oracle", Version.version));
1044:                  addProvider(new Provider(Provider.Type.TRANSPORT,
1045:                                 "smtp", "com.sun.mail.smtp.SMTPTransport",
1046:                                 "Oracle", Version.version));
1047:                  addProvider(new Provider(Provider.Type.TRANSPORT,
1048:                                 "smtps", "com.sun.mail.smtp.SMTPSSLTransport",
1049:                                 "Oracle", Version.version));
1050:                 }
1051:         
1052:                 if (logger.isLoggable(Level.CONFIG)) {
1053:                  // dump the output of the tables for debugging
1054:                  logger.config("Tables of loaded providers");
1055:                  logger.config("Providers Listed By Class Name: " +
1056:                  providersByClassName.toString());
1057:                  logger.config("Providers Listed By Protocol: " +
1058:                  providersByProtocol.toString());
1059:                 }
1060: }
1061:
1062: private void loadProvidersFromStream(InputStream is) throws IOException {
1063:                 if (is != null) {
1064:                  LineInputStream lis = streamProvider.inputLineStream(is, false);
1065:                  String currLine;
1066:         
1067:                  // load and process one line at a time using LineInputStream
1068:                  while ((currLine = lis.readLine()) != null) {
1069:         
1070:                                 if (currLine.startsWith("#"))
1071:                                  continue;
1072:                                 if (currLine.trim().length() == 0)
1073:                                  continue;        // skip blank line
1074:                                 Provider.Type type = null;
1075:                                 String protocol = null, className = null;
1076:                                 String vendor = null, version = null;
1077:                                 
1078:                                 // separate line into key-value tuples
1079:                                 StringTokenizer tuples = new StringTokenizer(currLine,";");
1080:                                 while (tuples.hasMoreTokens()) {
1081:                                  String currTuple = tuples.nextToken().trim();
1082:                                         
1083:                                  // set the value of each attribute based on its key
1084:                                  int sep = currTuple.indexOf("=");
1085:                                  if (currTuple.startsWith("protocol=")) {
1086:                                         protocol = currTuple.substring(sep+1);
1087:                                  } else if (currTuple.startsWith("type=")) {
1088:                                         String strType = currTuple.substring(sep+1);
1089:                                         if (strType.equalsIgnoreCase("store")) {
1090:                                          type = Provider.Type.STORE;
1091:                                         } else if (strType.equalsIgnoreCase("transport")) {
1092:                                          type = Provider.Type.TRANSPORT;
1093:                                          }
1094:                                  } else if (currTuple.startsWith("class=")) {
1095:                                         className = currTuple.substring(sep+1);
1096:                                  } else if (currTuple.startsWith("vendor=")) {
1097:                                         vendor = currTuple.substring(sep+1);
1098:                                  } else if (currTuple.startsWith("version=")) {
1099:                                         version = currTuple.substring(sep+1);
1100:                                  }
1101:                                 }
1102:                 
1103:                                 // check if a valid Provider; else, continue
1104:                                 if (type == null || protocol == null || className == null
1105:                                  || protocol.length() <= 0 || className.length() <= 0) {
1106:                                         
1107:                                  logger.log(Level.CONFIG, "Bad provider entry: {0}",
1108:                                                                 currLine);
1109:                                  continue;
1110:                                 }
1111:                                 Provider provider = new Provider(type, protocol, className,
1112:                                                          vendor, version);
1113:                 
1114:                                 // add the newly-created Provider to the lookup tables
1115:                                 addProvider(provider);
1116:                  }
1117:                 }
1118: }
1119:
1120: /**
1121: * Add a provider to the session.
1122: *
1123: * @param        provider        the provider to add
1124: * @since        JavaMail 1.4
1125: */
1126: public synchronized void addProvider(Provider provider) {
1127:                 providers.add(provider);
1128:                 providersByClassName.put(provider.getClassName(), provider);
1129:                 if (!providersByProtocol.containsKey(provider.getProtocol()))
1130:                  providersByProtocol.put(provider.getProtocol(), provider);
1131:         }
1132:         
1133: // load maps in reverse order of preference so that the preferred
1134: // map is loaded last since its entries will override the previous ones
1135: private void loadAddressMap(Class<?> cl) {
1136:                 StreamLoader loader = new StreamLoader() {
1137:                  @Override
1138:                  public void load(InputStream is) throws IOException {
1139:                         addressMap.load(is);
1140:                  }
1141:                 };
1142:         
1143:                 // load default META-INF/javamail.default.address.map from mail.jar
1144:                 loadResource("/META-INF/javamail.default.address.map", cl, loader, true);
1145:         
1146:                 // load the META-INF/javamail.address.map file supplied by an app
1147:                 loadAllResources("META-INF/javamail.address.map", cl, loader);
1148:         
1149:                 // load system-wide javamail.address.map from the
1150:                 // <java.home>/{conf,lib} directory
1151:                 try {
1152:                  if (confDir != null)
1153:                         loadFile(confDir + "javamail.address.map", loader);
1154:                 } catch (SecurityException ex) {}
1155:         
1156:                 if (addressMap.isEmpty()) {
1157:                  logger.config("failed to load address map, using defaults");
1158:                  addressMap.put("rfc822", "smtp");
1159:                 }
1160: }
1161:
1162: /**
1163: * Set the default transport protocol to use for addresses of
1164: * the specified type. Normally the default is set by the
1165: * <code>javamail.default.address.map</code> or
1166: * <code>javamail.address.map</code> files or resources.
1167: *
1168: * @param        addresstype        type of address
1169: * @param        protocol        name of protocol
1170: * @see #getTransport(Address)
1171: * @since        JavaMail 1.4
1172: */
1173: public synchronized void setProtocolForAddress(String addresstype, String protocol) {
1174:                 if (protocol == null)
1175:                  addressMap.remove(addresstype);
1176:                 else
1177:                  addressMap.put(addresstype, protocol);
1178:          }
1179:         
1180:          /**
1181:          * Load from the named file.
1182:          */
1183:          private void loadFile(String name, StreamLoader loader) {
1184:                 InputStream clis = null;
1185:                 try {
1186:                  clis = new BufferedInputStream(new FileInputStream(name));
1187:                  loader.load(clis);
1188:                  logger.log(Level.CONFIG, "successfully loaded file: {0}", name);
1189:                 } catch (FileNotFoundException fex) {
1190:                  // ignore it
1191:                 } catch (IOException e) {
1192:                  if (logger.isLoggable(Level.CONFIG))
1193:                         logger.log(Level.CONFIG, "not loading file: " + name, e);
1194:                 } catch (SecurityException sex) {
1195:                  if (logger.isLoggable(Level.CONFIG))
1196:                         logger.log(Level.CONFIG, "not loading file: " + name, sex);
1197:                 } finally {
1198:                  try {
1199:                         if (clis != null)
1200:                          clis.close();
1201:                  } catch (IOException ex) { }        // ignore it
1202:                 }
1203: }
1204:
1205: /**
1206: * Load from the named resource.
1207: */
1208: private void loadResource(String name, Class<?> cl, StreamLoader loader, boolean expected) {
1209:                 InputStream clis = null;
1210:                 try {
1211:                  clis = getResourceAsStream(cl, name);
1212:                  if (clis != null) {
1213:                         loader.load(clis);
1214:                         logger.log(Level.CONFIG, "successfully loaded resource: {0}",
1215:                                                  name);
1216:                  } else {
1217:                         if (expected)
1218:                          logger.log(Level.WARNING,
1219:                                          "expected resource not found: {0}", name);
1220:                  }
1221:                 } catch (IOException e) {
1222:                  logger.log(Level.CONFIG, "Exception loading resource", e);
1223:                 } catch (SecurityException sex) {
1224:                  logger.log(Level.CONFIG, "Exception loading resource", sex);
1225:                 } finally {
1226:                  try {
1227:                         if (clis != null)
1228:                          clis.close();
1229:                  } catch (IOException ex) { }        // ignore it
1230:                 }
1231: }
1232:
1233: /**
1234: * Load all of the named resource.
1235: */
1236: private void loadAllResources(String name, Class<?> cl, StreamLoader loader) {
1237:                 boolean anyLoaded = false;
1238:                 try {
1239:                  URL[] urls;
1240:                  ClassLoader cld = null;
1241:                  // First try the "application's" class loader.
1242:                  cld = getContextClassLoader();
1243:                  if (cld == null)
1244:                         cld = cl.getClassLoader();
1245:                  if (cld != null)
1246:                         urls = getResources(cld, name);
1247:                  else
1248:                         urls = getSystemResources(name);
1249:                  if (urls != null) {
1250:                         for (int i = 0; i < urls.length; i++) {
1251:                          URL url = urls[i];
1252:                          InputStream clis = null;
1253:                          logger.log(Level.CONFIG, "URL {0}", url);
1254:                          try {
1255:                                 clis = openStream(url);
1256:                                 if (clis != null) {
1257:                                  loader.load(clis);
1258:                                  anyLoaded = true;
1259:                                  logger.log(Level.CONFIG,
1260:                                         "successfully loaded resource: {0}", url);
1261:                                 } else {
1262:                                  logger.log(Level.CONFIG,
1263:                                         "not loading resource: {0}", url);
1264:                                 }
1265:                          } catch (FileNotFoundException fex) {
1266:                                 // ignore it
1267:                          } catch (IOException ioex) {
1268:                                 logger.log(Level.CONFIG, "Exception loading resource",
1269:                                          ioex);
1270:                          } catch (SecurityException sex) {
1271:                                 logger.log(Level.CONFIG, "Exception loading resource",
1272:                                          sex);
1273:                          } finally {
1274:                                 try {
1275:                                  if (clis != null)
1276:                                         clis.close();
1277:                                 } catch (IOException cex) { }
1278:                          }
1279:                         }
1280:                  }
1281:                 } catch (Exception ex) {
1282:                  logger.log(Level.CONFIG, "Exception loading resource", ex);
1283:                 }
1284:         
1285:                 // if failed to load anything, fall back to old technique, just in case
1286:                 if (!anyLoaded) {
1287:                  /*
1288:                  logger.config("!anyLoaded");
1289:                  */
1290:                  loadResource("/" + name, cl, loader, false);
1291:                 }
1292: }
1293:
1294: /*
1295: * Following are security related methods that work on JDK 1.2 or newer.
1296: */
1297:
1298: static ClassLoader getContextClassLoader() {
1299:                 return AccessController.doPrivileged(
1300:                         new PrivilegedAction<ClassLoader>() {
1301:                          @Override
1302:                          public ClassLoader run() {
1303:                                 ClassLoader cl = null;
1304:                                 try {
1305:                                  cl = Thread.currentThread().getContextClassLoader();
1306:                                 } catch (SecurityException ex) {
1307:                                 }
1308:                                 return cl;
1309:                          }
1310:                         }
1311:                 );
1312: }
1313:
1314: private static InputStream getResourceAsStream(final Class<?> c, final String name) throws IOException {
1315:                 try {
1316:                  return AccessController.doPrivileged(
1317:                          new PrivilegedExceptionAction<InputStream>() {
1318:                                 @Override
1319:                                 public InputStream run() throws IOException {
1320:                                  try {
1321:                                         return c.getResourceAsStream(name);
1322:                                  } catch (RuntimeException e) {
1323:                                         // gracefully handle ClassLoader bugs (Tomcat)
1324:                                         IOException ioex = new IOException(
1325:                                          "ClassLoader.getResourceAsStream failed");
1326:                                         ioex.initCause(e);
1327:                                         throw ioex;
1328:                                  }
1329:                                 }
1330:                          }
1331:                  );
1332:                 } catch (PrivilegedActionException e) {
1333:                  throw (IOException)e.getException();
1334:                 }
1335: }
1336:
1337: private static URL[] getResources(final ClassLoader cl, final String name) {
1338:                 return AccessController.doPrivileged(new PrivilegedAction<URL[]>() {
1339:                  @Override
1340:                  public URL[] run() {
1341:                         URL[] ret = null;
1342:                         try {
1343:                          List<URL> v = Collections.list(cl.getResources(name));
1344:                          if (!v.isEmpty()) {
1345:                                 ret = new URL[v.size()];
1346:                                 v.toArray(ret);
1347:                          }
1348:                         } catch (IOException ioex) {
1349:                         } catch (SecurityException ex) { }
1350:                         return ret;
1351:                  }
1352:                 });
1353: }
1354:
1355: private static URL[] getSystemResources(final String name) {
1356:                 return AccessController.doPrivileged(new PrivilegedAction<URL[]>() {
1357:                  @Override
1358:                  public URL[] run() {
1359:                         URL[] ret = null;
1360:                         try {
1361:                          List<URL> v = Collections.list(
1362:                                  ClassLoader.getSystemResources(name));
1363:•                         if (!v.isEmpty()) {
1364:                                 ret = new URL[v.size()];
1365:                                 v.toArray(ret);
1366:                          }
1367:                         } catch (IOException ioex) {
1368:                         } catch (SecurityException ex) { }
1369:                         return ret;
1370:                  }
1371:                 });
1372: }
1373:
1374: private static InputStream openStream(final URL url) throws IOException {
1375:                 try {
1376:                  return AccessController.doPrivileged(
1377:                          new PrivilegedExceptionAction<InputStream>() {
1378:                                 @Override
1379:                                 public InputStream run() throws IOException {
1380:                                  return url.openStream();
1381:                                 }
1382:                          }
1383:                  );
1384:                 } catch (PrivilegedActionException e) {
1385:                  throw (IOException)e.getException();
1386:                 }
1387: }
1388:
1389: EventQueue getEventQueue() {
1390:         return q;
1391: }
1392:
1393: private static final String OSGI_SERVICE_LOADER_CLASS_NAME = "org.glassfish.hk2.osgiresourcelocator.ServiceLoader";
1394:
1395: private static boolean isHk2Available() {
1396: try {
1397: Class.forName(OSGI_SERVICE_LOADER_CLASS_NAME);
1398: return true;
1399: } catch (ClassNotFoundException ignored) {
1400: }
1401: return false;
1402: }
1403:
1404: @SuppressWarnings({"unchecked"})
1405: private <T> Iterator<T> lookupUsingHk2ServiceLoader(String factoryId) {
1406: try {
1407: // Use reflection to avoid having any dependency on HK2 ServiceLoader class
1408: Class<?> serviceClass = Class.forName(factoryId);
1409: Class<?>[] args = new Class<?>[]{serviceClass};
1410: Class<?> target = Class.forName(OSGI_SERVICE_LOADER_CLASS_NAME);
1411: Method m = target.getMethod("lookupProviderInstances", Class.class);
1412: Iterable<T> result = ((Iterable<T>) m.invoke(null, (Object[]) args));
1413: return result != null ? result.iterator() : Collections.emptyIterator();
1414: } catch (Exception ignored) {
1415: // log and continue
1416: return Collections.emptyIterator();
1417: }
1418: }
1419:
1420: }
1421:
1422: /**
1423: * Support interface to generalize
1424: * code that loads resources from stream.
1425: */
1426: interface StreamLoader {
1427: public void load(InputStream is) throws IOException;
1428: }