1. /*
  2. * Licensed to the Apache Software Foundation (ASF) under one
  3. * or more contributor license agreements. See the NOTICE file
  4. * distributed with this work for additional information
  5. * regarding copyright ownership. The ASF licenses this file
  6. * to you under the Apache License, Version 2.0 (the
  7. * "License"); you may not use this file except in compliance
  8. * with the License. You may obtain a copy of the License at
  9. *
  10. * http://www.apache.org/licenses/LICENSE-2.0
  11. *
  12. * Unless required by applicable law or agreed to in writing,
  13. * software distributed under the License is distributed on an
  14. * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  15. * KIND, either express or implied. See the License for the
  16. * specific language governing permissions and limitations
  17. * under the License.
  18. */
  19.  
  20. package javax.mail;
  21.  
  22. import java.io.BufferedReader;
  23. import java.io.File;
  24. import java.io.FileInputStream;
  25. import java.io.IOException;
  26. import java.io.InputStream;
  27. import java.io.InputStreamReader;
  28. import java.io.PrintStream;
  29. import java.lang.reflect.Constructor;
  30. import java.lang.reflect.InvocationTargetException;
  31. import java.net.InetAddress;
  32. import java.net.URL;
  33. import java.util.ArrayList;
  34. import java.util.Collection;
  35. import java.util.Enumeration;
  36. import java.util.HashMap;
  37. import java.util.List;
  38. import java.util.Map;
  39. import java.util.Properties;
  40. import java.util.StringTokenizer;
  41. import java.util.WeakHashMap;
  42.  
  43. import org.apache.geronimo.osgi.locator.ProviderLocator;
  44. import org.apache.geronimo.mail.MailProviderRegistry;
  45.  
  46. /**
  47. * OK, so we have a final class in the API with a heck of a lot of implementation required...
  48. * let's try and figure out what it is meant to do.
  49. * <p/>
  50. * It is supposed to collect together properties and defaults so that they can be
  51. * shared by multiple applications on a desktop; with process isolation and no
  52. * real concept of shared memory, this seems challenging. These properties and
  53. * defaults rely on system properties, making management in a app server harder,
  54. * and on resources loaded from "mail.jar" which may lead to skew between
  55. * differnet independent implementations of this API.
  56. *
  57. * @version $Rev: 924365 $ $Date: 2010-03-17 12:52:03 -0400 (Wed, 17 Mar 2010) $
  58. */
  59. public final class Session {
  60. private static final Class[] PARAM_TYPES = {Session.class, URLName.class};
  61. private static final WeakHashMap addressMapsByClassLoader = new WeakHashMap();
  62. private static Session DEFAULT_SESSION;
  63.  
  64. private Map passwordAuthentications = new HashMap();
  65.  
  66. private final Properties properties;
  67. private final Authenticator authenticator;
  68. private boolean debug;
  69. private PrintStream debugOut = System.out;
  70.  
  71. private static final WeakHashMap providersByClassLoader = new WeakHashMap();
  72.  
  73. /**
  74. * No public constrcutor allowed.
  75. */
  76. private Session(Properties properties, Authenticator authenticator) {
  77. this.properties = properties;
  78. this.authenticator = authenticator;
  79. debug = Boolean.valueOf(properties.getProperty("mail.debug")).booleanValue();
  80. }
  81.  
  82. /**
  83. * Create a new session initialized with the supplied properties which uses the supplied authenticator.
  84. * Clients should ensure the properties listed in Appendix A of the JavaMail specification are
  85. * set as the defaults are unlikey to work in most scenarios; particular attention should be given
  86. * to:
  87. * <ul>
  88. * <li>mail.store.protocol</li>
  89. * <li>mail.transport.protocol</li>
  90. * <li>mail.host</li>
  91. * <li>mail.user</li>
  92. * <li>mail.from</li>
  93. * </ul>
  94. *
  95. * @param properties the session properties
  96. * @param authenticator an authenticator for callbacks to the user
  97. * @return a new session
  98. */
  99. public static Session getInstance(Properties properties, Authenticator authenticator) {
  100. // if we have a properties bundle, we need a copy of the provided one
  101. if (properties != null) {
  102. properties = (Properties)properties.clone();
  103. }
  104.  
  105. return new Session(properties, authenticator);
  106. }
  107.  
  108. /**
  109. * Create a new session initialized with the supplied properties with no authenticator.
  110. *
  111. * @param properties the session properties
  112. * @return a new session
  113. * @see #getInstance(java.util.Properties, Authenticator)
  114. */
  115. public static Session getInstance(Properties properties) {
  116. return getInstance(properties, null);
  117. }
  118.  
  119. /**
  120. * Get the "default" instance assuming no authenticator is required.
  121. *
  122. * @param properties the session properties
  123. * @return if "default" session
  124. * @throws SecurityException if the does not have permission to access the default session
  125. */
  126. public synchronized static Session getDefaultInstance(Properties properties) {
  127. return getDefaultInstance(properties, null);
  128. }
  129.  
  130. /**
  131. * Get the "default" session.
  132. * If there is not current "default", a new Session is created and installed as the default.
  133. *
  134. * @param properties
  135. * @param authenticator
  136. * @return if "default" session
  137. * @throws SecurityException if the does not have permission to access the default session
  138. */
  139. public synchronized static Session getDefaultInstance(Properties properties, Authenticator authenticator) {
  140. if (DEFAULT_SESSION == null) {
  141. DEFAULT_SESSION = getInstance(properties, authenticator);
  142. } else {
  143. if (authenticator != DEFAULT_SESSION.authenticator) {
  144. if (authenticator == null || DEFAULT_SESSION.authenticator == null || authenticator.getClass().getClassLoader() != DEFAULT_SESSION.authenticator.getClass().getClassLoader()) {
  145. throw new SecurityException();
  146. }
  147. }
  148. // todo we should check with the SecurityManager here as well
  149. }
  150. return DEFAULT_SESSION;
  151. }
  152.  
  153. /**
  154. * Enable debugging for this session.
  155. * Debugging can also be enabled by setting the "mail.debug" property to true when
  156. * the session is being created.
  157. *
  158. * @param debug the debug setting
  159. */
  160. public void setDebug(boolean debug) {
  161. this.debug = debug;
  162. }
  163.  
  164. /**
  165. * Get the debug setting for this session.
  166. *
  167. * @return the debug setting
  168. */
  169. public boolean getDebug() {
  170. return debug;
  171. }
  172.  
  173. /**
  174. * Set the output stream where debug information should be sent.
  175. * If set to null, System.out will be used.
  176. *
  177. * @param out the stream to write debug information to
  178. */
  179. public void setDebugOut(PrintStream out) {
  180. debugOut = out == null ? System.out : out;
  181. }
  182.  
  183. /**
  184. * Return the debug output stream.
  185. *
  186. * @return the debug output stream
  187. */
  188. public PrintStream getDebugOut() {
  189. return debugOut;
  190. }
  191.  
  192. /**
  193. * Return the list of providers available to this application.
  194. * This method searches for providers that are defined in the javamail.providers
  195. * and javamail.default.providers resources available through the current context
  196. * classloader, or if that is not available, the classloader that loaded this class.
  197. * <p/>
  198. * As searching for providers is potentially expensive, this implementation maintains
  199. * a WeakHashMap of providers indexed by ClassLoader.
  200. *
  201. * @return an array of providers
  202. */
  203. public Provider[] getProviders() {
  204. ProviderInfo info = getProviderInfo();
  205. return (Provider[]) info.all.toArray(new Provider[info.all.size()]);
  206. }
  207.  
  208. /**
  209. * Return the provider for a specific protocol.
  210. * This implementation initially looks in the Session properties for an property with the name
  211. * "mail.<protocol>.class"; if found it attempts to create an instance of the class named in that
  212. * property throwing a NoSuchProviderException if the class cannot be loaded.
  213. * If this property is not found, it searches the providers returned by {@link #getProviders()}
  214. * for a entry for the specified protocol.
  215. *
  216. * @param protocol the protocol to get a provider for
  217. * @return a provider for that protocol
  218. * @throws NoSuchProviderException
  219. */
  220. public Provider getProvider(String protocol) throws NoSuchProviderException {
  221. ProviderInfo info = getProviderInfo();
  222. Provider provider = null;
  223. String providerName = properties.getProperty("mail." + protocol + ".class");
  224. if (providerName != null) {
  225. provider = (Provider) info.byClassName.get(providerName);
  226. if (debug) {
  227. writeDebug("DEBUG: new provider loaded: " + provider.toString());
  228. }
  229. }
  230.  
  231. // if not able to locate this by class name, just grab a registered protocol.
  232. if (provider == null) {
  233. provider = (Provider) info.byProtocol.get(protocol);
  234. }
  235.  
  236. if (provider == null) {
  237. throw new NoSuchProviderException("Unable to locate provider for protocol: " + protocol);
  238. }
  239. if (debug) {
  240. writeDebug("DEBUG: getProvider() returning provider " + provider.toString());
  241. }
  242. return provider;
  243. }
  244.  
  245. /**
  246. * Make the supplied Provider the default for its protocol.
  247. *
  248. * @param provider the new default Provider
  249. * @throws NoSuchProviderException
  250. */
  251. public void setProvider(Provider provider) throws NoSuchProviderException {
  252. ProviderInfo info = getProviderInfo();
  253. info.byProtocol.put(provider.getProtocol(), provider);
  254. }
  255.  
  256. /**
  257. * Return a Store for the default protocol defined by the mail.store.protocol property.
  258. *
  259. * @return the store for the default protocol
  260. * @throws NoSuchProviderException
  261. */
  262. public Store getStore() throws NoSuchProviderException {
  263. String protocol = properties.getProperty("mail.store.protocol");
  264. if (protocol == null) {
  265. throw new NoSuchProviderException("mail.store.protocol property is not set");
  266. }
  267. return getStore(protocol);
  268. }
  269.  
  270. /**
  271. * Return a Store for the specified protocol.
  272. *
  273. * @param protocol the protocol to get a Store for
  274. * @return a Store
  275. * @throws NoSuchProviderException if no provider is defined for the specified protocol
  276. */
  277. public Store getStore(String protocol) throws NoSuchProviderException {
  278. Provider provider = getProvider(protocol);
  279. return getStore(provider);
  280. }
  281.  
  282. /**
  283. * Return a Store for the protocol specified in the given URL
  284. *
  285. * @param url the URL of the Store
  286. * @return a Store
  287. * @throws NoSuchProviderException if no provider is defined for the specified protocol
  288. */
  289. public Store getStore(URLName url) throws NoSuchProviderException {
  290. return (Store) getService(getProvider(url.getProtocol()), url);
  291. }
  292.  
  293. /**
  294. * Return the Store specified by the given provider.
  295. *
  296. * @param provider the provider to create from
  297. * @return a Store
  298. * @throws NoSuchProviderException if there was a problem creating the Store
  299. */
  300. public Store getStore(Provider provider) throws NoSuchProviderException {
  301. if (Provider.Type.STORE != provider.getType()) {
  302. throw new NoSuchProviderException("Not a Store Provider: " + provider);
  303. }
  304. return (Store) getService(provider, null);
  305. }
  306.  
  307. /**
  308. * Return a closed folder for the supplied URLName, or null if it cannot be obtained.
  309. * <p/>
  310. * The scheme portion of the URL is used to locate the Provider and create the Store;
  311. * the returned Store is then used to obtain the folder.
  312. *
  313. * @param name the location of the folder
  314. * @return the requested folder, or null if it is unavailable
  315. * @throws NoSuchProviderException if there is no provider
  316. * @throws MessagingException if there was a problem accessing the Store
  317. */
  318. public Folder getFolder(URLName name) throws MessagingException {
  319. Store store = getStore(name);
  320. return store.getFolder(name);
  321. }
  322.  
  323. /**
  324. * Return a Transport for the default protocol specified by the
  325. * <code>mail.transport.protocol</code> property.
  326. *
  327. * @return a Transport
  328. * @throws NoSuchProviderException
  329. */
  330. public Transport getTransport() throws NoSuchProviderException {
  331. String protocol = properties.getProperty("mail.transport.protocol");
  332. if (protocol == null) {
  333. throw new NoSuchProviderException("mail.transport.protocol property is not set");
  334. }
  335. return getTransport(protocol);
  336. }
  337.  
  338. /**
  339. * Return a Transport for the specified protocol.
  340. *
  341. * @param protocol the protocol to use
  342. * @return a Transport
  343. * @throws NoSuchProviderException
  344. */
  345. public Transport getTransport(String protocol) throws NoSuchProviderException {
  346. Provider provider = getProvider(protocol);
  347. return getTransport(provider);
  348. }
  349.  
  350. /**
  351. * Return a transport for the protocol specified in the URL.
  352. *
  353. * @param name the URL whose scheme specifies the protocol
  354. * @return a Transport
  355. * @throws NoSuchProviderException
  356. */
  357. public Transport getTransport(URLName name) throws NoSuchProviderException {
  358. return (Transport) getService(getProvider(name.getProtocol()), name);
  359. }
  360.  
  361. /**
  362. * Return a transport for the protocol associated with the type of this address.
  363. *
  364. * @param address the address we are trying to deliver to
  365. * @return a Transport
  366. * @throws NoSuchProviderException
  367. */
  368. public Transport getTransport(Address address) throws NoSuchProviderException {
  369. String type = address.getType();
  370. // load the address map from the resource files.
  371. Map addressMap = getAddressMap();
  372. String protocolName = (String)addressMap.get(type);
  373. if (protocolName == null) {
  374. throw new NoSuchProviderException("No provider for address type " + type);
  375. }
  376. return getTransport(protocolName);
  377. }
  378.  
  379. /**
  380. * Return the Transport specified by a Provider
  381. *
  382. * @param provider the defining Provider
  383. * @return a Transport
  384. * @throws NoSuchProviderException
  385. */
  386. public Transport getTransport(Provider provider) throws NoSuchProviderException {
  387. return (Transport) getService(provider, null);
  388. }
  389.  
  390. /**
  391. * Set the password authentication associated with a URL.
  392. *
  393. * @param name the url
  394. * @param authenticator the authenticator
  395. */
  396. public void setPasswordAuthentication(URLName name, PasswordAuthentication authenticator) {
  397. if (authenticator == null) {
  398. passwordAuthentications.remove(name);
  399. } else {
  400. passwordAuthentications.put(name, authenticator);
  401. }
  402. }
  403.  
  404. /**
  405. * Get the password authentication associated with a URL
  406. *
  407. * @param name the URL
  408. * @return any authenticator for that url, or null if none
  409. */
  410. public PasswordAuthentication getPasswordAuthentication(URLName name) {
  411. return (PasswordAuthentication) passwordAuthentications.get(name);
  412. }
  413.  
  414. /**
  415. * Call back to the application supplied authenticator to get the needed username add password.
  416. *
  417. * @param host the host we are trying to connect to, may be null
  418. * @param port the port on that host
  419. * @param protocol the protocol trying to be used
  420. * @param prompt a String to show as part of the prompt, may be null
  421. * @param defaultUserName the default username, may be null
  422. * @return the authentication information collected by the authenticator; may be null
  423. */
  424. public PasswordAuthentication requestPasswordAuthentication(InetAddress host, int port, String protocol, String prompt, String defaultUserName) {
  425. if (authenticator == null) {
  426. return null;
  427. }
  428. return authenticator.authenticate(host, port, protocol, prompt, defaultUserName);
  429. }
  430.  
  431. /**
  432. * Return the properties object for this Session; this is a live collection.
  433. *
  434. * @return the properties for the Session
  435. */
  436. public Properties getProperties() {
  437. return properties;
  438. }
  439.  
  440. /**
  441. * Return the specified property.
  442. *
  443. * @param property the property to get
  444. * @return its value, or null if not present
  445. */
  446. public String getProperty(String property) {
  447. return getProperties().getProperty(property);
  448. }
  449.  
  450. /**
  451. * Add a provider to the Session managed provider list.
  452. *
  453. * @param provider The new provider to add.
  454. */
  455. public synchronized void addProvider(Provider provider) {
  456. ProviderInfo info = getProviderInfo();
  457. info.addProvider(provider);
  458. }
  459.  
  460. /**
  461. * Add a mapping between an address type and a protocol used
  462. * to process that address type.
  463. *
  464. * @param addressType
  465. * The address type identifier.
  466. * @param protocol The protocol name mapping.
  467. */
  468. public void setProtocolForAddress(String addressType, String protocol) {
  469. Map addressMap = getAddressMap();
  470.  
  471. // no protocol specified is a removal
  472. if (protocol == null) {
  473. addressMap.remove(addressType);
  474. }
  475. else {
  476. addressMap.put(addressType, protocol);
  477. }
  478. }
  479.  
  480. private Service getService(Provider provider, URLName name) throws NoSuchProviderException {
  481. try {
  482. if (name == null) {
  483. name = new URLName(provider.getProtocol(), null, -1, null, null, null);
  484. }
  485. ClassLoader cl = getClassLoader();
  486. Class clazz = null;
  487. try {
  488. clazz = ProviderLocator.loadClass(provider.getClassName(), this.getClass(), cl);
  489. } catch (ClassNotFoundException e) {
  490. throw (NoSuchProviderException) new NoSuchProviderException("Unable to load class for provider: " + provider).initCause(e);
  491. }
  492. Constructor ctr = clazz.getConstructor(PARAM_TYPES);
  493. return(Service) ctr.newInstance(new Object[]{this, name});
  494. } catch (NoSuchMethodException e) {
  495. throw (NoSuchProviderException) new NoSuchProviderException("Provider class does not have a constructor(Session, URLName): " + provider).initCause(e);
  496. } catch (InstantiationException e) {
  497. throw (NoSuchProviderException) new NoSuchProviderException("Unable to instantiate provider class: " + provider).initCause(e);
  498. } catch (IllegalAccessException e) {
  499. throw (NoSuchProviderException) new NoSuchProviderException("Unable to instantiate provider class: " + provider).initCause(e);
  500. } catch (InvocationTargetException e) {
  501. throw (NoSuchProviderException) new NoSuchProviderException("Exception from constructor of provider class: " + provider).initCause(e.getCause());
  502. }
  503. }
  504.  
  505. private ProviderInfo getProviderInfo() {
  506. ClassLoader cl = getClassLoader();
  507. synchronized (providersByClassLoader) {
  508. ProviderInfo info = (ProviderInfo) providersByClassLoader.get(cl);
  509. if (info == null) {
  510. info = loadProviders(cl);
  511. }
  512. return info;
  513. }
  514. }
  515.  
  516. private Map getAddressMap() {
  517. ClassLoader cl = getClassLoader();
  518. Map addressMap = (Map)addressMapsByClassLoader.get(cl);
  519. if (addressMap == null) {
  520. addressMap = loadAddressMap(cl);
  521. }
  522. return addressMap;
  523. }
  524.  
  525. /**
  526. * Resolve a class loader used to resolve context resources. The
  527. * class loader used is either a current thread context class
  528. * loader (if set), the class loader used to load an authenticator
  529. * we've been initialized with, or the class loader used to load
  530. * this class instance (which may be a subclass of Session).
  531. *
  532. * @return The class loader used to load resources.
  533. */
  534. private ClassLoader getClassLoader() {
  535. ClassLoader cl = Thread.currentThread().getContextClassLoader();
  536. if (cl == null) {
  537. if (authenticator != null) {
  538. cl = authenticator.getClass().getClassLoader();
  539. }
  540. else {
  541. cl = this.getClass().getClassLoader();
  542. }
  543. }
  544. return cl;
  545. }
  546.  
  547. private ProviderInfo loadProviders(ClassLoader cl) {
  548. // we create a merged map from reading all of the potential address map entries. The locations
  549. // searched are:
  550. // 1. java.home/lib/javamail.address.map
  551. // 2. META-INF/javamail.address.map
  552. // 3. META-INF/javamail.default.address.map
  553. //
  554. ProviderInfo info = new ProviderInfo();
  555.  
  556. // NOTE: Unlike the addressMap, we process these in the defined order. The loading routine
  557. // will not overwrite entries if they already exist in the map.
  558.  
  559. try {
  560. File file = new File(System.getProperty("java.home"), "lib/javamail.providers");
  561. InputStream is = new FileInputStream(file);
  562. try {
  563. loadProviders(info, is);
  564. if (debug) {
  565. writeDebug("Loaded lib/javamail.providers from " + file.toString());
  566. }
  567. } finally{
  568. is.close();
  569. }
  570. } catch (SecurityException e) {
  571. // ignore
  572. } catch (IOException e) {
  573. // ignore
  574. }
  575.  
  576. try {
  577. Enumeration e = cl.getResources("META-INF/javamail.providers");
  578. while (e.hasMoreElements()) {
  579. URL url = (URL) e.nextElement();
  580. if (debug) {
  581. writeDebug("Loading META-INF/javamail.providers from " + url.toString());
  582. }
  583. InputStream is = url.openStream();
  584. try {
  585. loadProviders(info, is);
  586. } finally{
  587. is.close();
  588. }
  589. }
  590. } catch (SecurityException e) {
  591. // ignore
  592. } catch (IOException e) {
  593. // ignore
  594. }
  595.  
  596. // we could be running in an OSGi environment, so there might be some globally defined
  597. // providers
  598. try {
  599. Collection<URL> l = MailProviderRegistry.getProviders();
  600. for (URL url : l) {
  601. if (debug) {
  602. writeDebug("Loading META-INF/javamail.providers from " + url.toString());
  603. }
  604. InputStream is = url.openStream();
  605. try {
  606. loadProviders(info, is);
  607. } finally{
  608. is.close();
  609. }
  610. }
  611. } catch (SecurityException e) {
  612. // ignore
  613. } catch (IOException e) {
  614. // ignore
  615. }
  616.  
  617. try {
  618. Enumeration e = cl.getResources("META-INF/javamail.default.providers");
  619. while (e.hasMoreElements()) {
  620. URL url = (URL) e.nextElement();
  621. if (debug) {
  622. writeDebug("Loading javamail.default.providers from " + url.toString());
  623. }
  624.  
  625. InputStream is = url.openStream();
  626. try {
  627. loadProviders(info, is);
  628. } finally{
  629. is.close();
  630. }
  631. }
  632. } catch (SecurityException e) {
  633. // ignore
  634. } catch (IOException e) {
  635. // ignore
  636. }
  637.  
  638. // we could be running in an OSGi environment, so there might be some globally defined
  639. // providers
  640. try {
  641. Collection<URL> l = MailProviderRegistry.getDefaultProviders();
  642. for (URL url : l) {
  643. if (debug) {
  644. writeDebug("Loading META-INF/javamail.providers from " + url.toString());
  645. }
  646. InputStream is = url.openStream();
  647. try {
  648. loadProviders(info, is);
  649. } finally{
  650. is.close();
  651. }
  652. }
  653. } catch (SecurityException e) {
  654. // ignore
  655. } catch (IOException e) {
  656. // ignore
  657. }
  658.  
  659. // make sure this is added to the global map.
  660. providersByClassLoader.put(cl, info);
  661.  
  662. return info;
  663. }
  664.  
  665. private void loadProviders(ProviderInfo info, InputStream is) throws IOException {
  666. BufferedReader reader = new BufferedReader(new InputStreamReader(is));
  667. String line;
  668. while ((line = reader.readLine()) != null) {
  669. // Lines beginning with "#" are just comments.
  670. if (line.startsWith("#")) {
  671. continue;
  672. }
  673.  
  674. StringTokenizer tok = new StringTokenizer(line, ";");
  675. String protocol = null;
  676. Provider.Type type = null;
  677. String className = null;
  678. String vendor = null;
  679. String version = null;
  680. while (tok.hasMoreTokens()) {
  681. String property = tok.nextToken();
  682. int index = property.indexOf('=');
  683. if (index == -1) {
  684. continue;
  685. }
  686. String key = property.substring(0, index).trim().toLowerCase();
  687. String value = property.substring(index+1).trim();
  688. if (protocol == null && "protocol".equals(key)) {
  689. protocol = value;
  690. } else if (type == null && "type".equals(key)) {
  691. if ("store".equals(value)) {
  692. type = Provider.Type.STORE;
  693. } else if ("transport".equals(value)) {
  694. type = Provider.Type.TRANSPORT;
  695. }
  696. } else if (className == null && "class".equals(key)) {
  697. className = value;
  698. } else if ("vendor".equals(key)) {
  699. vendor = value;
  700. } else if ("version".equals(key)) {
  701. version = value;
  702. }
  703. }
  704. if (protocol == null || type == null || className == null) {
  705. //todo should we log a warning?
  706. continue;
  707. }
  708.  
  709. if (debug) {
  710. writeDebug("DEBUG: loading new provider protocol=" + protocol + ", className=" + className + ", vendor=" + vendor + ", version=" + version);
  711. }
  712. Provider provider = new Provider(type, protocol, className, vendor, version);
  713. // add to the info list.
  714. info.addProvider(provider);
  715. }
  716. }
  717.  
  718. /**
  719. * Load up an address map associated with a using class loader
  720. * instance.
  721. *
  722. * @param cl The class loader used to resolve the address map.
  723. *
  724. * @return A map containing the entries associated with this classloader
  725. * instance.
  726. */
  727. private static Map loadAddressMap(ClassLoader cl) {
  728. // we create a merged map from reading all of the potential address map entries. The locations
  729. // searched are:
  730. // 1. java.home/lib/javamail.address.map
  731. // 2. META-INF/javamail.address.map
  732. // 3. META-INF/javamail.default.address.map
  733. //
  734. // if all of the above searches fail, we just set up some "default" defaults.
  735.  
  736. // the format of the address.map file is defined as a property file. We can cheat and
  737. // just use Properties.load() to read in the files.
  738. Properties addressMap = new Properties();
  739.  
  740. // add this to the tracking map.
  741. addressMapsByClassLoader.put(cl, addressMap);
  742.  
  743. // NOTE: We are reading these resources in reverse order of what's cited above. This allows
  744. // user defined entries to overwrite default entries if there are similarly named items.
  745.  
  746. try {
  747. Enumeration e = cl.getResources("META-INF/javamail.default.address.map");
  748. while (e.hasMoreElements()) {
  749. URL url = (URL) e.nextElement();
  750. InputStream is = url.openStream();
  751. try {
  752. // load as a property file
  753. addressMap.load(is);
  754. } finally{
  755. is.close();
  756. }
  757. }
  758. } catch (SecurityException e) {
  759. // ignore
  760. } catch (IOException e) {
  761. // ignore
  762. }
  763.  
  764. try {
  765. Enumeration e = cl.getResources("META-INF/javamail.address.map");
  766. while (e.hasMoreElements()) {
  767. URL url = (URL) e.nextElement();
  768. InputStream is = url.openStream();
  769. try {
  770. // load as a property file
  771. addressMap.load(is);
  772. } finally{
  773. is.close();
  774. }
  775. }
  776. } catch (SecurityException e) {
  777. // ignore
  778. } catch (IOException e) {
  779. // ignore
  780. }
  781.  
  782. try {
  783. File file = new File(System.getProperty("java.home"), "lib/javamail.address.map");
  784. InputStream is = new FileInputStream(file);
  785. try {
  786. // load as a property file
  787. addressMap.load(is);
  788. } finally{
  789. is.close();
  790. }
  791. } catch (SecurityException e) {
  792. // ignore
  793. } catch (IOException e) {
  794. // ignore
  795. }
  796.  
  797. try {
  798. Enumeration e = cl.getResources("META-INF/javamail.address.map");
  799. while (e.hasMoreElements()) {
  800. URL url = (URL) e.nextElement();
  801. InputStream is = url.openStream();
  802. try {
  803. // load as a property file
  804. addressMap.load(is);
  805. } finally{
  806. is.close();
  807. }
  808. }
  809. } catch (SecurityException e) {
  810. // ignore
  811. } catch (IOException e) {
  812. // ignore
  813. }
  814.  
  815. // if unable to load anything, at least create the MimeMessage-smtp protocol mapping.
  816. if (addressMap.isEmpty()) {
  817. addressMap.put("rfc822", "smtp");
  818. }
  819.  
  820. return addressMap;
  821. }
  822.  
  823. /**
  824. * Private convenience routine for debug output.
  825. *
  826. * @param msg The message to write out to the debug stream.
  827. */
  828. private void writeDebug(String msg) {
  829. debugOut.println(msg);
  830. }
  831.  
  832. private static class ProviderInfo {
  833. private final Map byClassName = new HashMap();
  834. private final Map byProtocol = new HashMap();
  835. private final List all = new ArrayList();
  836.  
  837. public void addProvider(Provider provider) {
  838. String className = provider.getClassName();
  839.  
  840. if (!byClassName.containsKey(className)) {
  841. byClassName.put(className, provider);
  842. }
  843.  
  844. String protocol = provider.getProtocol();
  845. if (!byProtocol.containsKey(protocol)) {
  846. byProtocol.put(protocol, provider);
  847. }
  848. all.add(provider);
  849. }
  850. }
  851. }

java mail session使用Properties的clone方法的更多相关文章

  1. 为什么阿里Java手册推荐慎用 Object 的 clone 方法来拷贝对象

    图片若无法显示,可至掘金查看https://juejin.im/post/5d425230f265da039519d248 前言 在阿里Java开发手册中,有这么一条建议:慎用 Object 的 cl ...

  2. java基础面试题:写clone()方法时,通常都有一行代码,是什么?

    clone()方法 与new constructor()构造器创建对象不同 是克隆一个新的对象 package com.swift; public class Clone_Test { public ...

  3. java/eclipse/myeclipse建立.properties文件的方法

      相比较来说,Java程序的编写相对简单很多,多数文件都可以通过编写文本文件生成!     对于不用IDE的java程序来讲,只需要右键新建>文本文件,建立好以后写好代码,另存为xx.prop ...

  4. java mail实现Email的发送,完整代码

    java mail实现Email的发送,完整代码 1.对应用程序配置邮件会话 首先, 导入jar <dependencies> <dependency> <groupId ...

  5. java mail qq邮箱配置 实例

    程序入口:Test_Email_N.java import java.io.IOException; import java.util.Date; import java.util.Propertie ...

  6. Java Mail(三):Session、Message详解

    http://blog.csdn.net/ghsau/article/details/17909093 ************************************* 本文来自:高爽|Co ...

  7. 详解Java中的clone方法:原型模式

    转:http://developer.51cto.com/art/201506/478985.htm clone顾名思义就是复制, 在Java语言中, clone方法被对象调用,所以会复制对象.所谓的 ...

  8. Java基础——clone()方法浅析

    一.clone的概念 clone顾名思义就是复制, 在Java语言中, clone方法被对象调用,所以会复制对象.所谓的复制对象,首先要分配一个和源对象同样大小的空间,在这个空间中创建一个新的对象.那 ...

  9. 分析java中clone()方法 (转载+修改)

    Java中的clone() 方法 java所有的类都是从java.lang.Object类继承而来的,而Object类提供下面的方法对对象进行复制. protected native Object c ...

随机推荐

  1. Docker部署HDFS

    docker部署hadoop只是实验目的,每个服务都是通过手动部署,比如namenode, datanode, journalnode等.如果为了灵活的管理集群,而不使用官方封装好的自动化部署脚本,本 ...

  2. EXCEL这样根据某单元格的内容来改变整行颜色

    1.选择你需要改变颜色的单元格列数,然后打开“格式”--“条件格式”: 2.选择“公式”一项,在后面输入=$L1=2050,然后点开下面的“格式”按钮设置好格式. 3.基本上就OK了,注意在输入公式的 ...

  3. [luogu 5300][bzoj 5502] [GXOI/GZOI2019] 与或和

    题面 思路还是挺容易想的, 只是由于我还是太\(naive\)了一点不会做只会打暴力吧...... 题目要我们求所有子矩阵的\(and\)值之和与\(or\)值之和, 一看之下似乎不好入手, 我们慢慢 ...

  4. Appium——处理混合APP中H5的操作

    https://blog.csdn.net/iiyting/article/details/51887488

  5. Winform 基础一 panel

    一 居上.居中.居下 二 添加子控件 三 适应不同分辨率 四 内容超出,显示滚动条 一 .居上.居中.居下 二.添加子页面 Form7 childFrm = new Form7(); childFrm ...

  6. 【ZOJ 3463】Piano

    ZOJ 3463 题意:有一个钢琴,一个人把左手放在L位置上,右手放在R位置上,要弹某\(n\)个键,每个手最多能够得着9个位置,并且两只手不能交叉.把手移动的代价是大拇指移动的距离的平方根.问弹完这 ...

  7. sql语句,查询昨天的数据

    如果在程序中,有前台传来两个时间点:beginTime和endTime,在sql查询中的限制条件就是查询昨天的数据,那么可以这样写: 但是如果在这里要查询昨天的数据的话, 则不能简单地在开始时间的那里 ...

  8. Django 学习 (第四部)

    1.Django请求的生命周期 首先是url---->路由系统 -> 试图函数(获取模板+数据=>渲染) -> 字符串返回给用户2.路由系统{建立路由关系urls.py (fu ...

  9. BZOJ3676 APIO2014 回文串 Manacher、SA

    传送门 首先一个结论:串\(S\)中本质不同的回文串个数最多有\(|S|\)个 证明考虑以点\(i\)结尾的所有回文串,假设为\(S[l_1,i],S[l_2,i],...,S[l_k,i]\),其中 ...

  10. Codechef STREDUC Reduce string Trie、bitset、区间DP

    VJ传送门 简化题意:给出一个长度为\(l\)的模板串\(s\)与若干匹配串\(p_i\),每一次你可以选择\(s\)中的一个出现在集合\(\{p_i\}\)中的子串将其消去,其左右分成的两个串拼接在 ...