001 /** 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017 package org.apache.geronimo.mail; 018 019 import javax.mail.Authenticator; 020 import javax.mail.Session; 021 import javax.naming.Context; 022 import javax.naming.InitialContext; 023 import javax.naming.NamingException; 024 import javax.naming.Name; 025 import java.util.Collection; 026 import java.util.Iterator; 027 import java.util.Properties; 028 029 import org.apache.commons.logging.Log; 030 import org.apache.commons.logging.LogFactory; 031 032 import org.apache.geronimo.gbean.GBeanInfo; 033 import org.apache.geronimo.gbean.GBeanInfoBuilder; 034 import org.apache.geronimo.gbean.GBeanLifecycle; 035 import org.apache.geronimo.j2ee.j2eeobjectnames.NameFactory; 036 import org.apache.geronimo.management.JavaMailResource; 037 038 039 /** 040 * GBean that provides access to JavaMail Sessions. 041 * <p/> 042 * This GBean is used to generate JavaMail Sessions. JavaMail properties that 043 * are common to all JavaMail Sessions are provided via member variables of this 044 * class. 045 * 046 * @version $Rev: 524985 $ $Date: 2007-04-02 20:59:10 -0400 (Mon, 02 Apr 2007) $ 047 * @see ProtocolGBean 048 * @see SMTPTransportGBean 049 * @see POP3StoreGBean 050 * @see IMAPStoreGBean 051 */ 052 public class MailGBean implements GBeanLifecycle, JavaMailResource { 053 054 private final Log log = LogFactory.getLog(MailGBean.class); 055 056 private final String objectName; 057 private final Collection protocols; 058 private Boolean useDefault; 059 private Properties properties; 060 private Authenticator authenticator; 061 private String storeProtocol; 062 private String transportProtocol; 063 private String host; 064 private String user; 065 private Boolean debug; 066 private String jndiName; 067 068 069 /** 070 * Construct an instance of MailGBean 071 * <p/> 072 * Values that are set in the individual member variables will override any of 073 * the corresponding values that have been set in the properties set. 074 * 075 * @param protocols the set of protocol GBeans that contain protocol specific configurations 076 * @param useDefault whether this GBean will return default Sessions or not 077 * @param properties the set of default properties for the protocols 078 * @param authenticator the authenticator object 079 * @param storeProtocol the store protocol that Sessions created from this GBean will return 080 * @param transportProtocol the transport protocol that Sessions created from this GBean will return 081 * @param host the default Mail server 082 * @param user the username to provide when connecting to a Mail server 083 * @param debug the debug setting for Sessions created from this GBean 084 * @param jndiName the JNDI name to which the mail Session should be bound 085 */ 086 public MailGBean(String objectName, Collection protocols, Boolean useDefault, Properties properties, Authenticator authenticator, 087 String storeProtocol, String transportProtocol, String host, String user, Boolean debug, String jndiName) { 088 this.objectName = objectName; 089 this.protocols = protocols; 090 setUseDefault(useDefault); 091 this.properties = (properties == null ? new Properties() : properties); 092 setAuthenticator(authenticator); 093 setStoreProtocol(storeProtocol); 094 setTransportProtocol(transportProtocol); 095 setHost(host); 096 setUser(user); 097 setDebug(debug); 098 setJndiName(jndiName); 099 } 100 101 /** 102 * Returns the set of protocol GBeans that contain protocol specific configurations. 103 */ 104 public Collection getProtocols() { 105 return protocols; 106 } 107 108 /** 109 * Returns whether this GBean will return default Sessions or not. 110 */ 111 public Boolean getUseDefault() { 112 return useDefault; 113 } 114 115 /** 116 * Sets whether this GBean will return default Sessions or not, 117 * 118 * @param useDefault whether this GBean will return default Sessions or not 119 */ 120 public void setUseDefault(Boolean useDefault) { 121 this.useDefault = useDefault; 122 } 123 124 /** 125 * Returns the set of default properties for the protocols. 126 * <p/> 127 * Note: Proerties that are set here will override the properties that are 128 * set in the protocol GBeans. 129 */ 130 public Properties getProperties() { 131 return properties; 132 } 133 134 /** 135 * Sets the set of default properties for the protocols. 136 * <p/> 137 * Note: Proerties that are set here will override the properties that are 138 * set in the protocol GBeans. 139 * 140 * @param properties the set of default properties for the protocols 141 */ 142 public void setProperties(Properties properties) { 143 this.properties = properties; 144 } 145 146 /** 147 * Returns the authenticator object. 148 * <p/> 149 * Used only if a new Session object is created. Otherwise, it must match 150 * the Authenticator used to create the Session. 151 */ 152 public Authenticator getAuthenticator() { 153 return authenticator; 154 } 155 156 /** 157 * Sets the authenticator object. 158 * <p/> 159 * Used only if a new Session object is created. Otherwise, it must match 160 * the Authenticator used to create the Session. 161 * 162 * @param authenticator the authenticator object 163 */ 164 public void setAuthenticator(Authenticator authenticator) { 165 this.authenticator = authenticator; 166 } 167 168 /** 169 * Returns the store protocol that Sessions created from this GBean will return. 170 * <p/> 171 * Specifies the default Message Access Protocol. The Session.getStore() 172 * method returns a Store object that implements this protocol. The client 173 * can override this property and explicitly specify the protocol with the 174 * Session.getStore(String protocol) method. 175 */ 176 public String getStoreProtocol() { 177 return storeProtocol; 178 } 179 180 /** 181 * Sets the store protocol that Sessions created from this GBean will return. 182 * <p/> 183 * Specifies the default Message Access Protocol. The Session.getStore() 184 * method returns a Store object that implements this protocol. The client 185 * can override this property and explicitly specify the protocol with the 186 * Session.getStore(String protocol) method. 187 * <p/> 188 * Values that are set here will override any of the corresponding value 189 * that has been set in the properties. 190 * 191 * @param storeProtocol the store protocol that Sessions created from this GBean will return 192 */ 193 public void setStoreProtocol(String storeProtocol) { 194 this.storeProtocol = storeProtocol; 195 } 196 197 /** 198 * Returns the transport protocol that Sessions created from this GBean will return. 199 * <p/> 200 * Specifies the default Transport Protocol. The Session.getTransport() 201 * method returns a Transport object that implements this protocol. The 202 * client can override this property and explicitly specify the protocol 203 * by using Session.getTransport(String protocol) method. 204 */ 205 public String getTransportProtocol() { 206 return transportProtocol; 207 } 208 209 /** 210 * Sets the transport protocol that Sessions created from this GBean will return. 211 * <p/> 212 * Specifies the default Transport Protocol. The Session.getTransport() 213 * method returns a Transport object that implements this protocol. The 214 * client can override this property and explicitly specify the protocol 215 * by using Session.getTransport(String protocol) method. 216 * <p/> 217 * Values that are set here will override any of the corresponding value 218 * that has been set in the properties. 219 * 220 * @param transportProtocol the transport protocol that Sessions created from this GBean will return 221 */ 222 public void setTransportProtocol(String transportProtocol) { 223 this.transportProtocol = transportProtocol; 224 } 225 226 /** 227 * Returns the default Mail server. 228 * <p/> 229 * Specifies the default Mail server. The Store and Transport object’s 230 * connect methods use this property, if the protocolspecific host property 231 * is absent, to locate the target host. 232 */ 233 public String getHost() { 234 return host; 235 } 236 237 /** 238 * Sets the default Mail server. 239 * <p/> 240 * Specifies the default Mail server. The Store and Transport object’s 241 * connect methods use this property, if the protocolspecific host property 242 * is absent, to locate the target host. 243 * <p/> 244 * Values that are set here will override any of the corresponding value 245 * that has been set in the properties. 246 * 247 * @param host the default Mail server 248 */ 249 public void setHost(String host) { 250 this.host = host; 251 } 252 253 /** 254 * Returns the username to provide when connecting to a Mail server. 255 * <p/> 256 * Specifies the username to provide when connecting to a Mail server. The 257 * Store and Transport object’s connect methods use this property, if the 258 * protocolspecific username property is absent, to obtain the username. 259 */ 260 public String getUser() { 261 return user; 262 } 263 264 /** 265 * Sets the username to provide when connecting to a Mail server. 266 * <p/> 267 * Specifies the username to provide when connecting to a Mail server. The 268 * Store and Transport object’s connect methods use this property, if the 269 * protocolspecific username property is absent, to obtain the username. 270 * <p/> 271 * Values that are set here will override any of the corresponding value 272 * that has been set in the properties. 273 * 274 * @param user the username to provide when connecting to a Mail server 275 */ 276 public void setUser(String user) { 277 this.user = user; 278 } 279 280 /** 281 * Returns the debug setting for Sessions created from this GBean. 282 */ 283 public Boolean getDebug() { 284 return debug; 285 } 286 287 /** 288 * Sets the debug setting for Sessions created from this GBean. 289 * <p/> 290 * Values that are set here will override any of the corresponding value 291 * that has been set in the properties. 292 * 293 * @param debug the debug setting for Sessions created from this GBean 294 */ 295 public void setDebug(Boolean debug) { 296 this.debug = debug; 297 } 298 299 /** 300 * Gets the JNDI name to which the mail Session should be bound 301 * @return the JNDI name to which the mail Session should be bound 302 */ 303 public String getJndiName() { 304 return jndiName; 305 } 306 307 /** 308 * Sets the JNDI name to which the mail Session should be bound 309 * @param jndiName the JNDI name to which the mail Session should be bound 310 */ 311 public void setJndiName(String jndiName) { 312 this.jndiName = jndiName; 313 } 314 315 public Object $getResource() { 316 Properties props = new Properties(properties); 317 318 if (protocols != null) { 319 for (Iterator iter = protocols.iterator(); iter.hasNext();) { 320 ProtocolGBean protocol = (ProtocolGBean) iter.next(); 321 protocol.addOverrides(props); 322 } 323 } 324 325 props.putAll(properties); 326 327 if (storeProtocol != null) props.put("mail.store.protocol", storeProtocol); 328 if (transportProtocol != null) props.put("mail.transport.protocol", transportProtocol); 329 if (host != null) props.put("mail.host", host); 330 if (user != null) props.put("mail.user", user); 331 // this needs to be translated into a string version. 332 if (debug != null) props.put("mail.debug", debug.toString()); 333 334 if (Boolean.TRUE.equals(useDefault)) { 335 if (authenticator == null) { 336 return Session.getDefaultInstance(props); 337 } else { 338 return Session.getDefaultInstance(props, authenticator); 339 } 340 } else { 341 if (authenticator == null) { 342 return Session.getInstance(props); 343 } else { 344 return Session.getInstance(props, authenticator); 345 } 346 } 347 } 348 349 public void doStart() throws Exception { 350 log.debug("Started " + objectName + " - will return " 351 + (Boolean.TRUE.equals(useDefault) ? "default" : "new") 352 + " JavaMail Session " 353 + (authenticator == null ? "without" : "with") 354 + " authenticator"); 355 356 String jndiName = getJndiName(); 357 if (jndiName != null && jndiName.length() > 0) { 358 // first get the resource incase there are exceptions 359 Object value = $getResource(); 360 361 // get the initial context 362 Context context = new InitialContext(); 363 Name parsedName = context.getNameParser("").parse(jndiName); 364 365 // create intermediate contexts 366 for (int i = 1; i < parsedName.size(); i++) { 367 Name contextName = parsedName.getPrefix(i); 368 if (!bindingExists(context, contextName)) { 369 context.createSubcontext(contextName); 370 } 371 } 372 373 // bind 374 context.bind(jndiName, value); 375 log.info("JavaMail session bound to " + jndiName); 376 } 377 } 378 379 public void doStop() throws Exception { 380 log.debug("Stopped " + objectName); 381 stop(); 382 } 383 384 public void doFail() { 385 log.warn("Failed " + objectName); 386 stop(); 387 } 388 389 private void stop() { 390 String jndiName = getJndiName(); 391 if (jndiName != null && jndiName.length() > 0) { 392 try { 393 Context context = new InitialContext(); 394 context.unbind(jndiName); 395 log.info("JavaMail session unbound from " + jndiName); 396 } catch (NamingException e) { 397 // we tried... this is a common error which occurs during shutdown due to ordering 398 } 399 } 400 } 401 402 private static boolean bindingExists(Context context, Name contextName) { 403 try { 404 return context.lookup(contextName) != null; 405 } catch (NamingException e) { 406 } 407 return false; 408 } 409 410 /** 411 * Returns the GBean name of this Mail GBean 412 */ 413 public String getObjectName() { 414 return objectName; 415 } 416 417 public boolean isStateManageable() { 418 return false; 419 } 420 421 public boolean isStatisticsProvider() { 422 return false; 423 } 424 425 public boolean isEventProvider() { 426 return false; 427 } 428 429 public static final GBeanInfo GBEAN_INFO; 430 431 static { 432 GBeanInfoBuilder infoFactory = GBeanInfoBuilder.createStatic(MailGBean.class, NameFactory.JAVA_MAIL_RESOURCE); 433 434 infoFactory.addAttribute("objectName", String.class, false); 435 infoFactory.addReference("Protocols", ProtocolGBean.class, NameFactory.GERONIMO_SERVICE); 436 infoFactory.addAttribute("useDefault", Boolean.class, true); 437 infoFactory.addAttribute("properties", Properties.class, true); 438 infoFactory.addReference("Authenticator", Authenticator.class, NameFactory.GERONIMO_SERVICE); 439 infoFactory.addAttribute("storeProtocol", String.class, true); 440 infoFactory.addAttribute("transportProtocol", String.class, true); 441 infoFactory.addAttribute("host", String.class, true); 442 infoFactory.addAttribute("user", String.class, true); 443 infoFactory.addAttribute("debug", Boolean.class, true); 444 infoFactory.addAttribute("jndiName", String.class, true); 445 infoFactory.addOperation("$getResource"); 446 infoFactory.addOperation("getProtocols"); 447 infoFactory.addInterface(JavaMailResource.class); 448 449 infoFactory.setConstructor(new String[]{"objectName", 450 "Protocols", 451 "useDefault", 452 "properties", 453 "Authenticator", 454 "storeProtocol", 455 "transportProtocol", 456 "host", 457 "user", 458 "debug", 459 "jndiName"}); 460 461 GBEAN_INFO = infoFactory.getBeanInfo(); 462 } 463 464 public static GBeanInfo getGBeanInfo() { 465 return GBEAN_INFO; 466 } 467 }