001: /*
002: * $Id: AbstractMailConnector.java 10489 2008-01-23 17:53:38Z dfeist $
003: * --------------------------------------------------------------------------------------
004: * Copyright (c) MuleSource, Inc. All rights reserved. http://www.mulesource.com
005: *
006: * The software in this package is published under the terms of the CPAL v1.0
007: * license, a copy of which has been included with this distribution in the
008: * LICENSE.txt file.
009: */
010:
011: package org.mule.transport.email;
012:
013: import org.mule.api.MuleException;
014: import org.mule.api.endpoint.EndpointURI;
015: import org.mule.api.endpoint.ImmutableEndpoint;
016: import org.mule.api.lifecycle.InitialisationException;
017: import org.mule.transport.AbstractConnector;
018: import org.mule.util.StringUtils;
019:
020: import java.util.Enumeration;
021: import java.util.HashMap;
022: import java.util.Map;
023: import java.util.Properties;
024:
025: import javax.mail.Authenticator;
026: import javax.mail.Session;
027: import javax.mail.URLName;
028:
029: /**
030: * Abstract superclass for mail connectors. Provides Mule with an Authenticator
031: * object and other shared functionality like e.g. MuleSession creation.
032: */
033: public abstract class AbstractMailConnector extends AbstractConnector {
034:
035: public static final String MAILBOX = "INBOX";
036:
037: private Map sessions = new HashMap();
038: private String mailboxFolder;
039: private int defaultPort;
040:
041: /**
042: * A custom authenticator to be used on any mail sessions created with this
043: * connector. This will only be used if user name credendials are set on the
044: * endpoint.
045: */
046: private Authenticator authenticator = null;
047:
048: public AbstractMailConnector(int defaultPort, String mailboxFolder) {
049: super ();
050: this .defaultPort = defaultPort;
051: this .mailboxFolder = mailboxFolder;
052: }
053:
054: public int getDefaultPort() {
055: return defaultPort;
056: }
057:
058: public Authenticator getAuthenticator() {
059: return authenticator;
060: }
061:
062: public void setAuthenticator(Authenticator authenticator) {
063: this .authenticator = authenticator;
064: }
065:
066: public String getMailboxFolder() {
067: return mailboxFolder;
068: }
069:
070: public void setMailboxFolder(String mailboxFolder) {
071: this .mailboxFolder = mailboxFolder;
072: }
073:
074: public synchronized SessionDetails getSessionDetails(
075: ImmutableEndpoint endpoint) {
076: SessionDetails sessionDetails = (SessionDetails) sessions
077: .get(endpoint);
078: if (null == sessionDetails) {
079: sessionDetails = newSession(endpoint);
080: sessions.put(endpoint, sessionDetails);
081: }
082: return sessionDetails;
083: }
084:
085: public URLName urlFromEndpoint(ImmutableEndpoint endpoint) {
086: String inbox = endpoint.getEndpointURI().getPath();
087: if (inbox.length() == 0) {
088: inbox = getMailboxFolder();
089: } else {
090: inbox = inbox.substring(1);
091: }
092:
093: EndpointURI uri = endpoint.getEndpointURI();
094: return new URLName(uri.getScheme(), uri.getHost(), uri
095: .getPort(), inbox, uri.getUser(), uri.getPassword());
096: }
097:
098: /**
099: * Some protocols (eg secure extensions) extend a "base" protocol.
100: * Subclasses for such protocols should override this method.
101: *
102: * @return the underlying (eg non-secure) protocol
103: */
104: protected String getBaseProtocol() {
105: return getProtocol();
106: }
107:
108: /**
109: * Subclasses should extend this to add further properties.
110: * Synchronization is managed outside this call (so no need to synchronize further on properties)
111: *
112: * @param global system properties
113: * @param local local properties (specific to one session)
114: * @param url the endpoint url
115: */
116: protected void extendPropertiesForSession(Properties global,
117: Properties local, URLName url) {
118: int port = url.getPort();
119: if (port == -1) {
120: port = this .getDefaultPort();
121: }
122: local.setProperty("mail." + getBaseProtocol()
123: + ".socketFactory.port", Integer.toString(port));
124:
125: if (StringUtils.isNotBlank(url.getPassword())) {
126: local.setProperty("mail." + getBaseProtocol() + ".auth",
127: "true");
128: if (getAuthenticator() == null) {
129: setAuthenticator(new DefaultAuthenticator(url
130: .getUsername(), url.getPassword()));
131: if (logger.isDebugEnabled()) {
132: logger.debug("No Authenticator set on connector: "
133: + getName() + "; using default.");
134: }
135: }
136: } else {
137: local.setProperty("mail." + getBaseProtocol() + ".auth",
138: "false");
139: }
140:
141: // TODO - i'm not at all certain that these properties (especially the ones
142: // using the base protocol) are needed. they are inherited from old, gnarly
143: // code.
144:
145: if (StringUtils.isNotBlank(url.getHost())) {
146: local.setProperty("mail." + getBaseProtocol() + ".host",
147: url.getHost());
148: }
149: local.setProperty("mail." + getBaseProtocol()
150: + ".rsetbeforequit", "true");
151: }
152:
153: protected SessionDetails newSession(ImmutableEndpoint endpoint) {
154: URLName url = urlFromEndpoint(endpoint);
155:
156: Properties global = System.getProperties();
157: Properties local = new Properties();
158: Session session;
159:
160: // make sure we do not mess with authentication set via system properties
161: synchronized (global) {
162: extendPropertiesForSession(global, local, url);
163: session = Session.getInstance(local, getAuthenticator());
164: }
165:
166: if (logger.isDebugEnabled()) {
167: local.setProperty("mail.debug", "true");
168:
169: dumpProperties("MuleSession local properties", local, true);
170: dumpProperties("System global properties", global, true);
171: logger.debug("Creating mail session: host = "
172: + url.getHost() + ", port = " + url.getPort()
173: + ", user = " + url.getUsername() + ", pass = "
174: + url.getPassword());
175: }
176:
177: return new SessionDetails(session, url);
178: }
179:
180: protected void dumpProperties(String title, Properties properties,
181: boolean filter) {
182: int skipped = 0;
183: logger.debug(title + " =============");
184: Enumeration keys = properties.keys();
185: while (keys.hasMoreElements()) {
186: String key = (String) keys.nextElement();
187: if (!filter || key.startsWith("mule.")
188: || key.startsWith("mail.")
189: || key.startsWith("javax.")) {
190: String value = properties.getProperty(key);
191: logger.debug(key + ": " + value);
192: } else {
193: ++skipped;
194: }
195: }
196: if (filter) {
197: logger.debug("skipped " + skipped);
198: }
199: }
200:
201: // supply these here because sub-classes are very simple
202:
203: protected void doInitialise() throws InitialisationException {
204: // template method, nothing to do
205: }
206:
207: protected void doDispose() {
208: // template method, nothing to do
209: }
210:
211: protected void doConnect() throws Exception {
212: // template method, nothing to do
213: }
214:
215: protected void doDisconnect() throws Exception {
216: // template method, nothing to do
217: }
218:
219: protected void doStart() throws MuleException {
220: // template method, nothing to do
221: }
222:
223: protected void doStop() throws MuleException {
224: // template method, nothing to do
225: }
226:
227: }
|