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