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