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