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 }