001: /**
002: * $Id: ExchangeMailSSOAdapter.java,v 1.13 2005/09/21 11:10:07 dg154973 Exp $
003: * Copyright 2002 Sun Microsystems, Inc. All
004: * rights reserved. Use of this product is subject
005: * to license terms. Federal Acquisitions:
006: * Commercial Software -- Government Users
007: * Subject to Standard License Terms and
008: * Conditions.
009: *
010: * Sun, Sun Microsystems, the Sun logo, and iPlanet
011: * are trademarks or registered trademarks of Sun Microsystems,
012: * Inc. in the United States and other countries.
013: */package com.sun.ssoadapter.impl;
014:
015: import com.sun.ssoadapter.SSOAdapter;
016: import com.sun.ssoadapter.SSOAdapterException;
017:
018: import com.sun.ssoadapter.SSOAdapterLogger;
019:
020: import com.iplanet.sso.SSOToken;
021: import com.iplanet.sso.SSOTokenEvent;
022: import com.iplanet.sso.SSOException;
023:
024: import javax.mail.*;
025: import javax.mail.internet.*;
026: import javax.servlet.http.*;
027: import java.util.*;
028: import java.net.*;
029: import java.io.*;
030:
031: import java.util.logging.Level;
032: import java.util.logging.Logger;
033: import java.util.logging.LogRecord;
034:
035: /**
036: * This class implements MailSSOHelper and MailApplicationHelper functionality
037: * specific to the Sun One Portal and Mail services.
038: * <p>Specific features include:
039: * <ul>
040: * <li>Support for username/password style authentication.</li>
041: * <li>Ability to generate web application URLs for the following:
042: * <ul>
043: * <li>Messenger Express</li>
044: * <li>MAP JSP Mail application. The URL generated in this
045: * case will specify a configuration index via the
046: * query string parameter: "mi". </li>
047: * </ul>
048: * </li>
049: * </ul>
050: * <p>At the present time, username/password is stored in the clear.
051: * <p>This MailSSOHelper implementation consumes the following
052: * Configuration properties:
053: * <ul>
054: * <li><b>protocol</b>: Required value. Must be either "imap" or "pop3".
055: * <li><b>uid</b>: Required value. Username (uid) of imap user.
056: * <li><b>password</b>: Required value. Password of imap user.
057: * <li><b>host</b>: Required value. Name of host providing IMAP service.
058: * <li><b>winDomain</b>: Optional value. NT domain to which user belongs.
059: * <li><b>port</b>: Optional value. Port number of IMAP server. Defaults to "143"
060: * when protocol is "imap", and "110" when protocol is "pop3".
061: * <li><b>smtpServer</b>: Optional value. Specifies name of outgoing mail server.
062: * Defaults to value of host property.
063: * <li><b>clientProtocol</b>: Protocol to specify within URLs that activate
064: * web application functionality. Defaults to "http".
065: * <li><b>clientPort</b>: Port to specify within URLs that that activate web
066: * application functionality. Defaults to "80".
067: * <li><b>jspContextPath</b>: The "request context path" to use when forming a URL
068: * that activates MAP JSP application functionality.
069: * Defaults to request.getContextPath().
070: * <li><b>jspLaunch</b>: The document path to use when forming a URL
071: * that activates MAP JSP application functionality.
072: * Defaults to "/jsp/default/launchMail.jsp".
073: * <li><b>exchangeContextPath</b>: The "request context path" to use when forming a URL
074: * that activates Exchange OWA functionality.
075: * Defaults to "/exchange".
076: * <li><b>exchangeOperation</b>: The operation to be invoked within Exchange OWA.
077: * Defaults to null, but should be set to "inbox"
078: * for Exchange 2000 installations.
079: * </ul>
080: *
081: * @version 1.0
082: * @see com.sun.ssoadapter.SSOAdapter
083: * @see com.sun.ssoadapter.SSOAdapterFactory
084: *
085: */
086:
087: public class ExchangeMailSSOAdapter extends JavaMailSSOAdapter {
088:
089: //
090: // Mail Store
091: //
092: protected javax.mail.Store mailStore = null;
093:
094: //
095: // Mail Session
096: //
097: protected javax.mail.Session mailSession = null;
098:
099: private static Logger logger = SSOAdapterLogger
100: .getLogger("com.sun.portal.ssoadapter.impl");
101:
102: /**
103: * Initialize and validate.
104: *
105: * @param adapterName Used to identify the SSOAdapter
106: * @param token Used to identify the user on who's behalf the request is
107: * being processed.
108: * @param adapterProperties Contains the adapter information that will drive
109: * the operation of this instance of an SSOAdapter.
110: */
111: public void init(String adapterName, SSOToken token,
112: Properties adapterProperties, List userPropertiesList,
113: List encodedProperteisList, Locale locale)
114: throws SSOAdapterException {
115:
116: super .init(adapterName, token, adapterProperties,
117: userPropertiesList, encodedProperteisList, locale);
118:
119: if (logger.isLoggable(Level.INFO)) {
120: Properties dp = new Properties();
121: dp.putAll(adapterProperties);
122: dp.remove(PROP_PASSWORD_NAME);
123:
124: String[] param = new String[5];
125: param[0] = adapterName;
126: param[1] = (String) dp.toString();
127: param[2] = identifier;
128: param[3] = userPropertiesList.toString();
129: param[4] = encodedProperteisList.toString();
130:
131: logger.log(Level.INFO, "PSSA_CSSI0001", param);
132: }
133:
134: if (adapterProperties.getProperty("validate", "false").equals(
135: "true")) {
136: try {
137: validate();
138: } catch (ValidationException ve) {
139: throw new SSOAdapterException(ve.getLocalizedMessage(
140: "ssoadapter", locale), true);
141: }
142: }
143:
144: }
145:
146: /**
147: * Validates configuration.
148: */
149: public void validate() throws ValidationException {
150:
151: if (logger.isLoggable(Level.INFO)) {
152: logger.log(Level.INFO, "PSSA_CSSI0003", new String[] {
153: adapterName, identifier });
154: }
155:
156: String protocolString = adapterProperties
157: .getProperty(PROP_PROTOCOL_NAME);
158: if (protocolString == null
159: || (!protocolString.equals("imap") && !protocolString
160: .equals("pop3"))) {
161: ValidationException ve = new ValidationException();
162: ve.setErrorMessageID("invalidProtocol");
163: throw ve;
164: }
165:
166: String portString = adapterProperties
167: .getProperty(PROP_PORT_NAME);
168: if ((portString != null) && (portString.length() > 0)) {
169: try {
170: int portInt = Integer.parseInt(portString);
171: } catch (Exception e) {
172: ValidationException ve = new ValidationException();
173: ve.setErrorMessageID("invalidPort");
174: throw ve;
175: }
176: }
177:
178: String hostString = adapterProperties
179: .getProperty(PROP_HOST_NAME);
180: if (hostString == null) {
181: ValidationException ve = new ValidationException();
182: ve.setErrorMessageID("missingHost");
183: throw ve;
184: }
185:
186: String uidString = adapterProperties.getProperty(PROP_UID_NAME);
187: if (uidString == null) {
188: ValidationException ve = new ValidationException();
189: ve.setErrorMessageID("missingUid");
190: throw ve;
191: }
192:
193: String passwordString = adapterProperties
194: .getProperty(PROP_PASSWORD_NAME);
195: if (passwordString == null) {
196: ValidationException ve = new ValidationException();
197: ve.setErrorMessageID("missingPassword");
198: throw ve;
199: }
200:
201: //
202: // TODO: winDomain may eventually have some meaning
203: // wrt ExchangeMailSSOAdapter. But for now, it's
204: // not required.
205: //String winDomainString = adapterProperties.getProperty("winDomain");
206: //if (winDomainString == null) {
207: //ValidationException ve = new ValidationException();
208: //ve.setErrorMessageID("missingWinDomain");
209: //throw ve;
210: //}
211:
212: String clientPortString = adapterProperties
213: .getProperty("clientPort");
214: if ((clientPortString != null)
215: && (clientPortString.length() > 0)) {
216: try {
217: int portInt = Integer.parseInt(clientPortString);
218: } catch (Exception e) {
219: ValidationException ve = new ValidationException();
220: ve.setErrorMessageID("invalidClientPort");
221: throw ve;
222: }
223: }
224:
225: }
226:
227: /**
228: * Adapter specific Connection.
229: */
230: public Object getConnection() {
231: Object obj = null;
232:
233: try {
234: obj = getStore();
235: } catch (Exception e) {
236: if (logger.isLoggable(Level.INFO)) {
237: logger.log(Level.INFO, "PSSA_CSSI0031", new String[] {
238: adapterName, identifier });
239: logger.log(Level.INFO, "PSSA_CSSI0032", e);
240: }
241: return null;
242: }
243:
244: if (obj != null) {
245: if (logger.isLoggable(Level.INFO)) {
246: logger.log(Level.INFO, "PSSA_CSSI0033", new String[] {
247: adapterName, identifier });
248: }
249: }
250:
251: return obj;
252: }
253:
254: /**
255: * Returns a JavaMail Store object.
256: */
257: public javax.mail.Store getStore() throws Exception {
258: if (isAvailable()) {
259: return mailStore;
260: }
261:
262: Session mailSession = getSession();
263:
264: if (mailSession == null) {
265: return null;
266: }
267:
268: String protocolString = adapterProperties
269: .getProperty(PROP_PROTOCOL_NAME);
270: mailStore = mailSession.getStore(protocolString);
271:
272: String portString = adapterProperties.getProperty(
273: PROP_PORT_NAME, protocolString.equals("pop3") ? "110"
274: : "143");
275:
276: if (logger.isLoggable(Level.INFO)) {
277: logger.log(Level.INFO, "PSSA_CSSI0039", new String[] {
278: adapterName, portString, identifier });
279: }
280:
281: mailStore.connect(
282: adapterProperties.getProperty(PROP_HOST_NAME), Integer
283: .parseInt(portString), adapterProperties
284: .getProperty(PROP_UID_NAME), adapterProperties
285: .getProperty(PROP_PASSWORD_NAME));
286:
287: return mailStore;
288: }
289:
290: /**
291: * Returns a JavaMail Session object.
292: */
293: public javax.mail.Session getSession() throws Exception {
294: if (mailSession != null) {
295: if (logger.isLoggable(Level.INFO)) {
296: logger.log(Level.INFO, "PSSA_CSSI0035", new String[] {
297: adapterName, identifier });
298: }
299: return mailSession;
300: }
301:
302: // check for mandatory properties, if they are null then there's
303: // no point in trying to establish a connection
304: //
305: String host = adapterProperties.getProperty(PROP_HOST_NAME);
306:
307: if (host == null) {
308: if (logger.isLoggable(Level.INFO)) {
309: logger.log(Level.INFO, "PSSA_CSSI0036", new String[] {
310: adapterName, identifier });
311: }
312: return null;
313: }
314:
315: String smtpPort = adapterProperties.getProperty("smtpPort");
316: Properties props = new Properties();
317:
318: props.put("mail.store.pkgs", "com.sun.mail");
319: props.put("mail.transport.protocol", "smtp");
320: props.put("mail.imap.fetchsize", "16384");
321: props.put("mail.smtp.host", adapterProperties.getProperty(
322: "smtpServer", host));
323:
324: if (smtpPort != null) {
325: props.put("mail.smtp.port", smtpPort);
326: }
327:
328: if (logger.isLoggable(Level.INFO)) {
329: String[] param = new String[3];
330: param[0] = adapterName;
331: param[1] = (String) props.toString();
332: param[2] = identifier;
333: logger.log(Level.INFO, "PSSA_CSSI0038", param);
334: }
335:
336: mailSession = javax.mail.Session.getInstance(props, null);
337:
338: return mailSession;
339: }
340:
341: /**
342: * Tests service availability.
343: */
344: public boolean isAvailable() {
345: if (mailStore != null && mailStore.isConnected()) {
346: if (logger.isLoggable(Level.INFO)) {
347: logger.log(Level.INFO, "PSSA_CSSI0034", new String[] {
348: adapterName, identifier });
349: }
350: return true;
351: } else {
352: return false;
353: }
354: }
355:
356: /**
357: * Adapter specific Connection termination.
358: *
359: * @return true if the connection was terminated successfully.
360: */
361: public boolean closeConnection() {
362: boolean retval = true;
363:
364: try {
365: mailStore.close();
366: mailStore = null;
367: mailSession = null;
368: } catch (Exception e) {
369: retval = false;
370: }
371:
372: if (logger.isLoggable(Level.INFO)) {
373: logger.log(Level.INFO, "PSSA_CSSI0005", new String[] {
374: adapterName, identifier });
375: }
376:
377: return retval;
378: }
379:
380: /**
381: * Implements SSOTokenListener "ssoTokenChanged" method.
382: *
383: * The following are possible SSO token event types:
384: * <ul>
385: * <li>SSO_TOKEN_IDLE_TIMEOUT
386: * <li>SSO_TOKEN_MAX_TIMEOUT
387: * <li>SSO_TOKEN_DESTROY
388: * </ul>
389: *
390: * The event getType() method is used to ensure that one of the
391: * three types above are the basis for this event. If getType()
392: * returns a type not listed above, then an SSOException is thrown.
393: *
394: * @param evt SSOTokenEvent
395: */
396: public void ssoTokenChanged(SSOTokenEvent evt) {
397:
398: try {
399: int evtType = evt.getType();
400:
401: if (mailStore != null) {
402: mailStore.close();
403: }
404:
405: mailStore = null;
406: mailSession = null;
407: } catch (Exception e) {
408: if (logger.isLoggable(Level.WARNING)) {
409: logger.log(Level.WARNING, "PSSA_CSSI0006", e);
410: }
411: return;
412: }
413:
414: if (logger.isLoggable(Level.INFO)) {
415: logger.log(Level.INFO, "PSSA_CSSI0002", new String[] {
416: adapterName, identifier });
417: }
418: }
419:
420: }
|