001: /**
002: * $Id: ExchangeABSSOAdapter.java,v 1.17 2006/04/25 20:14:36 rakeshn 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.AbstractSSOAdapter;
017: import com.sun.ssoadapter.SSOAdapterException;
018: import com.sun.addressbook.*;
019: import com.sun.ssoadapter.SSOAdapterLogger;
020: import com.iplanet.sso.SSOToken;
021: import com.iplanet.sso.SSOTokenEvent;
022: import com.iplanet.sso.SSOException;
023: import java.net.MalformedURLException;
024: import java.net.HttpURLConnection;
025: import java.net.URL;
026: import java.io.*;
027: import javax.mail.MessagingException;
028: import javax.mail.AuthenticationFailedException;
029: import javax.mail.Store;
030: import java.util.Properties;
031: import java.util.List;
032: import java.util.Locale;
033: import java.util.Enumeration;
034: import java.util.logging.Level;
035: import java.util.logging.Logger;
036:
037: import javax.servlet.http.*;
038:
039: /**
040: * This class implements ABSSOAdapter and ApplicationAdapter functionality
041: * specific to the Sun One Portal and iMS PAB service.
042: * <p>Specific features include:
043: * <ul>
044: * <li>Support for username/password style authentication.</li>
045: * <li>Ability to generate web application URLs for the following:
046: * <ul>
047: * <li>Messenger Express</li>
048: * <li>MAP JSP Addressbook application. The URL generated in this
049: * case will specify a configuration index via the
050: * query string parameter: "ai".</li>
051: * </ul>
052: * </li>
053: * </ul>
054: * <p>At the present time, username/password is stored in the clear.
055: * <p>This ABSSOAdapter implementation consumes the following
056: * Configuration properties:
057: * <ul>
058: * <li><b>uid</b>: Required value. Username (uid) of imap user.
059: * <li><b>password</b>: Required value. Password of imap user.
060: * <li><b>host</b>: Required value. Name of host providing PAB service.
061: * <li><b>winDomain</b>: Required value. NT domain to which user belongs.
062: * <li><b>abtype</b>: The Address Book type to open (pab - for Personal Address Book
063: * OR gal - for Global Address List). Defaults to pab.
064: * <li><b>ocxhost</b>: The server running the OCXHost (defaults to host).
065: * <li><b>authhost</b>: The server running the Aligo Auth Module (defaults to ocxhost).
066: * <li><b>clientProtocol</b>: Protocol to specify within URLs that activate
067: * web application functionality. Defaults to "http".
068: * <li><b>clientPort</b>: Port to specify within URLs that that activate web
069: * application functionality. Defaults to "80".
070: * <li><b>pimInterfaceType</b>: CDO or Webdav implementation to use to connect
071: * to Exchange server. CDO works with both Exchange
072: * 5.5 and Exchange 2000. Group support works only
073: * with WebDav.
074: * <li><b>jspContextPath</b>: The "request context path" to use when forming a URL
075: * that activates MAP JSP application functionality.
076: * Defaults to request.getContextPath().
077: * <li><b>jspLaunch</b>: The document path to use when forming a URL
078: * that activates MAP JSP application functionality.
079: * Defaults to "/jsp/default/launchAB.jsp".
080: * <li><b>exchangeContextPath</b>: The "request context path" to use when forming a URL
081: * that activates Exchange OWA functionality.
082: * Defaults to "/exchange".
083: * <li><b>exchangeOperation</b>: The operation to be invoked within Exchange OWA.
084: * Defaults to null, but should be set to "contacts"
085: * for Exchange 2000 installations.
086: * <li><b></b>:
087: * </ul>
088: *
089: * @version 1.0
090: * @see com.sun.ssoadapter.SSOAdapter
091: * @see com.sun.ssoadapter.SSOAdapterFactory
092: *
093: */
094:
095: public class ExchangeABSSOAdapter extends AbstractSSOAdapter {
096:
097: protected ABStore abStore = null;
098: protected ABSession abSession = null;
099:
100: protected static String serviceClass = "com.sun.ssoadapter.ab.exchange.ExchangeABStore";
101:
102: protected static String CLIENT_DEFAULT_PORT = "80";
103: protected static String CLIENT_DEFAULT_PROTOCOL = "http";
104: private static Logger logger = SSOAdapterLogger
105: .getLogger("com.sun.portal.ssoadapter.impl");
106:
107: /**
108: * Initialize and validate
109: *
110: * @param adapterName Used to identify the SSOAdapter
111: * @param token Used to identify the user on who's behalf the request is
112: * being processed.
113: * @param adapterProperties Contains the adapter information that will drive
114: * the operation of this instance of an SSOAdapter.
115: */
116: public void init(String adapterName, SSOToken token,
117: Properties adapterProperties, List userPropertiesList,
118: List encodedProperteisList, Locale locale)
119: throws SSOAdapterException {
120:
121: super .init(adapterName, token, adapterProperties,
122: userPropertiesList, encodedProperteisList, locale);
123:
124: if (logger.isLoggable(Level.INFO)) {
125: Properties dp = new Properties();
126: dp.putAll(adapterProperties);
127: dp.remove(PROP_PASSWORD_NAME);
128:
129: String[] param = new String[5];
130: param[0] = adapterName;
131: param[1] = (String) dp.toString();
132: param[2] = identifier;
133: param[3] = userPropertiesList.toString();
134: param[4] = encodedProperteisList.toString();
135:
136: logger.log(Level.INFO, "PSSA_CSSI0001", param);
137: }
138:
139: if (adapterProperties.getProperty("validate", "false").equals(
140: "true")) {
141: try {
142: validate();
143: } catch (ValidationException ve) {
144: throw new SSOAdapterException(ve.getLocalizedMessage(
145: "ssoadapter", locale), true);
146: }
147: }
148:
149: }
150:
151: /**
152: * Validates configuration.
153: */
154: public void validate() throws ValidationException {
155:
156: if (logger.isLoggable(Level.INFO)) {
157: logger.log(Level.INFO, "PSSA_CSSI0003", new String[] {
158: adapterName, identifier });
159: }
160:
161: String portString = adapterProperties
162: .getProperty(PROP_PORT_NAME);
163: if ((portString != null) && (portString.length() > 0)) {
164: try {
165: int portInt = Integer.parseInt(portString);
166: } catch (Exception e) {
167: ValidationException ve = new ValidationException();
168: ve.setErrorMessageID("invalidPort");
169: throw ve;
170: }
171: }
172:
173: String hostString = adapterProperties
174: .getProperty(PROP_HOST_NAME);
175: if (hostString == null) {
176: ValidationException ve = new ValidationException();
177: ve.setErrorMessageID("missingHost");
178: throw ve;
179: }
180:
181: String uidString = adapterProperties.getProperty(PROP_UID_NAME);
182: if (uidString == null) {
183: ValidationException ve = new ValidationException();
184: ve.setErrorMessageID("missingUid");
185: throw ve;
186: }
187:
188: String passwordString = adapterProperties
189: .getProperty(PROP_PASSWORD_NAME);
190: if (passwordString == null) {
191: ValidationException ve = new ValidationException();
192: ve.setErrorMessageID("missingPassword");
193: throw ve;
194: }
195:
196: String winDomainString = adapterProperties
197: .getProperty("winDomain");
198: if (winDomainString == null) {
199: ValidationException ve = new ValidationException();
200: ve.setErrorMessageID("missingWinDomain");
201: throw ve;
202: }
203:
204: String clientPortString = adapterProperties
205: .getProperty("clientPort");
206: if ((clientPortString != null)
207: && (clientPortString.length() > 0)) {
208: try {
209: int portInt = Integer.parseInt(clientPortString);
210: } catch (Exception e) {
211: ValidationException ve = new ValidationException();
212: ve.setErrorMessageID("invalidClientPort");
213: throw ve;
214: }
215: }
216:
217: }
218:
219: /**
220: * Adapter specific Connection.
221: */
222: public Object getConnection() {
223: Object obj = null;
224:
225: try {
226: obj = getABStore();
227: } catch (Exception e) {
228: if (logger.isLoggable(Level.INFO)) {
229: logger.log(Level.INFO, "PSSA_CSSI0050", new String[] {
230: adapterName, identifier });
231: logger.log(Level.INFO, "PSSA_CSSI0051", e);
232: }
233: return null;
234: }
235:
236: if (obj != null) {
237: if (logger.isLoggable(Level.INFO)) {
238: logger.log(Level.INFO, "PSSA_CSSI0052", new String[] {
239: adapterName, identifier });
240: }
241: }
242:
243: return obj;
244: }
245:
246: /**
247: * Returns a connected Ldap ABStore object.
248: */
249: public ABStore getABStore() throws Exception {
250:
251: if (isAvailable()) {
252: return abStore;
253: }
254:
255: abSession = getABSession();
256:
257: if (abSession == null) {
258: return null;
259: }
260:
261: abStore = abSession.getABStore(serviceClass);
262: abStore.connect();
263: return abStore;
264: }
265:
266: /**
267: * Returns a JABAPI ABSession object.
268: */
269: public ABSession getABSession() throws Exception {
270: if (abSession != null) {
271: if (logger.isLoggable(Level.INFO)) {
272: logger.log(Level.INFO, "PSSA_CSSI0053", new String[] {
273: adapterName, identifier });
274: }
275: return abSession;
276: }
277:
278: // check for mandatory properties, if they are null then there's
279: // no point in trying to establish a connection
280: //
281: String host = adapterProperties.getProperty(PROP_HOST_NAME);
282:
283: if (host == null) {
284: if (logger.isLoggable(Level.INFO)) {
285: logger.log(Level.INFO, "PSSA_CSSI0056", new String[] {
286: adapterName, identifier });
287: }
288: return null;
289: }
290:
291: String uid = adapterProperties.getProperty(PROP_UID_NAME);
292: String password = adapterProperties
293: .getProperty(PROP_PASSWORD_NAME);
294: String domain = adapterProperties.getProperty("winDomain");
295: String port = adapterProperties.getProperty(PROP_PORT_NAME,
296: null);
297: String abType = adapterProperties.getProperty("abtype");
298: String pimInterfaceType = adapterProperties
299: .getProperty("pimInterfaceType");
300: String ocxHost = adapterProperties.getProperty("ocxhost");
301: String authHost = adapterProperties.getProperty("authhost");
302: String usersBaseDn = adapterProperties
303: .getProperty("usersBaseDn");
304: Properties props = new Properties();
305:
306: if (host != null)
307: props.put("ab.host", host);
308: if (uid != null) {
309: props.put("ab.userName", uid);
310: props.put("ab.userMailBox", uid);
311: }
312: if (domain != null)
313: props.put("ab.userDomain", domain);
314: if (port != null)
315: props.put("ab.port", port);
316: if (abType != null)
317: props.put("ab.type", abType);
318: if (pimInterfaceType != null)
319: props.put("ab.pimInterfaceType", pimInterfaceType);
320: if (ocxHost != null)
321: props.put("ab.ocxhost", ocxHost);
322: if (authHost != null)
323: props.put("ab.authhost", authHost);
324: if (usersBaseDn != null)
325: props.put("ab.usersBaseDn", usersBaseDn);
326:
327: if (logger.isLoggable(Level.INFO))
328: props.put("ab.pim.debug", "true");
329:
330: if (logger.isLoggable(Level.INFO)) {
331: String[] param = new String[3];
332: param[0] = adapterName;
333: param[1] = (String) props.toString();
334: param[2] = identifier;
335: logger.log(Level.INFO, "PSSA_CSSI0055", param);
336: }
337:
338: if (password != null)
339: props.put("ab.userPassword", password);
340:
341: abSession = abSession.getInstance(props);
342:
343: return abSession;
344: }
345:
346: /**
347: * Tests service availability.
348: */
349: public boolean isAvailable() {
350: try {
351: if (abStore != null && abStore.isConnected()) {
352: if (logger.isLoggable(Level.INFO)) {
353: logger.log(Level.INFO, "PSSA_CSSI0057",
354: new String[] { adapterName, identifier });
355: }
356: return true;
357: } else {
358: return false;
359: }
360: } catch (ABStoreException abse) {
361: if (logger.isLoggable(Level.SEVERE)) {
362: logger.log(Level.SEVERE, "PSSA_CSSI0058", abse);
363: }
364: return false;
365: }
366: }
367:
368: /**
369: * Adapter specific Connection termination.
370: *
371: * @return true if the connection was terminated successfully.
372: */
373: public boolean closeConnection() {
374: boolean retval = true;
375:
376: try {
377: abStore.disconnect();
378: abStore = null;
379: abSession = null;
380: } catch (Exception e) {
381: retval = false;
382: }
383:
384: if (logger.isLoggable(Level.INFO)) {
385: logger.log(Level.INFO, "PSSA_CSSI0005", new String[] {
386: adapterName, identifier });
387: }
388:
389: return retval;
390: }
391:
392: /**
393: * Implements SSOTokenListener "ssoTokenChanged" method.
394: *
395: * The following are possible SSO token event types:
396: * <ul>
397: * <li>SSO_TOKEN_IDLE_TIMEOUT
398: * <li>SSO_TOKEN_MAX_TIMEOUT
399: * <li>SSO_TOKEN_DESTROY
400: * </ul>
401: *
402: * The event getType() method is used to ensure that one of the
403: * three types above are the basis for this event. If getType()
404: * returns a type not listed above, then an SSOException is thrown.
405: *
406: * @param evt SSOTokenEvent
407: */
408: public void ssoTokenChanged(SSOTokenEvent evt) {
409:
410: try {
411: int evtType = evt.getType();
412:
413: if (abStore != null) {
414: abStore.disconnect();
415: }
416:
417: abStore = null;
418: abSession = null;
419: } catch (Exception e) {
420: if (logger.isLoggable(Level.WARNING)) {
421: logger.log(Level.WARNING, "PSSA_CSSI0006", e);
422: }
423: return;
424: }
425:
426: if (logger.isLoggable(Level.INFO)) {
427: logger.log(Level.INFO, "PSSA_CSSI0002", new String[] {
428: adapterName, identifier });
429: }
430:
431: }
432:
433: }
|