001: /**
002: * $Id: NotesABSSOAdapter.java,v 1.16 2005/09/21 11:10:20 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.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.List;
031: import java.util.Locale;
032: import java.util.Properties;
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>abtype</b>: The Address Book type to open (pab - for Personal Address Book
062: * OR gal - for Global Address List). Defaults to pab.
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: * <li><b></b>:
073: * </ul>
074: *
075: * @version 1.0
076: * @see com.sun.ssoadapter.SSOAdapter
077: * @see com.sun.ssoadapter.SSOAdapterFactory
078: *
079: */
080:
081: public class NotesABSSOAdapter extends AbstractSSOAdapter {
082:
083: protected ABStore abStore = null;
084: protected ABSession abSession = null;
085:
086: private static String CLIENT_DEFAULT_PORT = "80";
087: private static String CLIENT_DEFAULT_PROTOCOL = "http";
088: private static String serviceClass = "com.sun.ssoadapter.ab.notes.NotesABStore";
089:
090: private static Logger logger = SSOAdapterLogger
091: .getLogger("com.sun.portal.ssoadapter.impl");
092:
093: /**
094: * Initialize and validate
095: *
096: * @param adapterName Used to identify the SSOAdapter
097: * @param token Used to identify the user on who's behalf the request is
098: * being processed.
099: * @param adapterProperties Contains the adapter information that will drive
100: * the operation of this instance of an SSOAdapter.
101: */
102: public void init(String adapterName, SSOToken token,
103: Properties adapterProperties, List userPropertiesList,
104: List encodedProperteisList, Locale locale)
105: throws SSOAdapterException {
106:
107: super .init(adapterName, token, adapterProperties,
108: userPropertiesList, encodedProperteisList, locale);
109:
110: if (logger.isLoggable(Level.INFO)) {
111: Properties dp = new Properties();
112: dp.putAll(adapterProperties);
113: dp.remove(PROP_PASSWORD_NAME);
114:
115: String[] param = new String[5];
116: param[0] = adapterName;
117: param[1] = (String) dp.toString();
118: param[2] = identifier;
119: param[3] = userPropertiesList.toString();
120: param[4] = encodedProperteisList.toString();
121:
122: logger.log(Level.INFO, "PSSA_CSSI0001", param);
123: }
124:
125: if (adapterProperties.getProperty("validate", "false").equals(
126: "true")) {
127: try {
128: validate();
129: } catch (ValidationException ve) {
130: throw new SSOAdapterException(ve.getLocalizedMessage(
131: "ssoadapter", locale), true);
132: }
133: }
134:
135: }
136:
137: /**
138: * Validates configuration.
139: */
140: public void validate() throws ValidationException {
141:
142: if (logger.isLoggable(Level.INFO)) {
143: logger.log(Level.INFO, "PSSA_CSSI0003", new String[] {
144: adapterName, identifier });
145: }
146:
147: String portString = adapterProperties
148: .getProperty(PROP_PORT_NAME);
149: if ((portString != null) && (portString.length() > 0)) {
150: try {
151: int portInt = Integer.parseInt(portString);
152: } catch (Exception e) {
153: ValidationException ve = new ValidationException();
154: ve.setErrorMessageID("invalidPort");
155: throw ve;
156: }
157: }
158:
159: String hostString = adapterProperties
160: .getProperty(PROP_HOST_NAME);
161: if (hostString == null) {
162: ValidationException ve = new ValidationException();
163: ve.setErrorMessageID("missingHost");
164: throw ve;
165: }
166:
167: String uidString = adapterProperties.getProperty(PROP_UID_NAME);
168: if (uidString == null) {
169: ValidationException ve = new ValidationException();
170: ve.setErrorMessageID("missingUid");
171: throw ve;
172: }
173:
174: String passwordString = adapterProperties
175: .getProperty(PROP_PASSWORD_NAME);
176: if (passwordString == null) {
177: ValidationException ve = new ValidationException();
178: ve.setErrorMessageID("missingPassword");
179: throw ve;
180: }
181:
182: String clientPortString = adapterProperties
183: .getProperty("clientPort");
184: if ((clientPortString != null)
185: && (clientPortString.length() > 0)) {
186: try {
187: int portInt = Integer.parseInt(clientPortString);
188: } catch (Exception e) {
189: ValidationException ve = new ValidationException();
190: ve.setErrorMessageID("invalidClientPort");
191: throw ve;
192: }
193: }
194:
195: }
196:
197: /**
198: * Adapter specific Connection.
199: */
200: public Object getConnection() {
201: Object obj = null;
202:
203: try {
204: obj = getABStore();
205: } catch (Exception e) {
206: if (logger.isLoggable(Level.INFO)) {
207: logger.log(Level.INFO, "PSSA_CSSI0050", new String[] {
208: adapterName, identifier });
209: logger.log(Level.INFO, "PSSA_CSSI0051", e);
210: }
211: return null;
212: }
213:
214: if (obj != null) {
215: if (logger.isLoggable(Level.INFO)) {
216: logger.log(Level.INFO, "PSSA_CSSI0052", new String[] {
217: adapterName, identifier });
218: }
219: }
220:
221: return obj;
222: }
223:
224: /**
225: * Returns a connected Ldap ABStore object.
226: */
227: public ABStore getABStore() throws Exception {
228: if (isAvailable()) {
229: return abStore;
230: }
231:
232: abSession = getABSession();
233:
234: if (abSession == null) {
235: return null;
236: }
237:
238: abStore = abSession.getABStore(serviceClass);
239: abStore.connect();
240: return abStore;
241: }
242:
243: /**
244: * Returns a JABAPI ABSession object.
245: */
246: public ABSession getABSession() throws Exception {
247: if (abSession != null) {
248: if (logger.isLoggable(Level.INFO)) {
249: logger.log(Level.INFO, "PSSA_CSSI0053", new String[] {
250: adapterName, identifier });
251: }
252: return abSession;
253: }
254:
255: // check for mandatory properties, if they are null then there's
256: // no point in trying to establish a connection
257: //
258: String host = adapterProperties.getProperty(PROP_HOST_NAME);
259:
260: if (host == null) {
261: if (logger.isLoggable(Level.INFO)) {
262: logger.log(Level.INFO, "PSSA_CSSI0056", new String[] {
263: adapterName, identifier });
264: }
265: return null;
266: }
267:
268: String uid = adapterProperties.getProperty(PROP_UID_NAME);
269: String port = adapterProperties.getProperty(PROP_PORT_NAME,
270: null);
271: String password = adapterProperties
272: .getProperty(PROP_PASSWORD_NAME);
273: String abType = adapterProperties.getProperty("abtype");
274: String protocol = adapterProperties
275: .getProperty(PROP_PROTOCOL_NAME);
276: Properties props = new Properties();
277:
278: if (uid == null || uid.equals("")) {
279: String ltpaToken = null;
280: if (protocol == null) {
281: protocol = CLIENT_DEFAULT_PROTOCOL;
282: }
283: RemoteDominoSession domSess = new RemoteDominoSession(
284: protocol, host, port, getSSOToken());
285: ltpaToken = domSess.getLTPAToken();
286: if (ltpaToken != null) {
287: props.put("lotus.ltpatoken.value", ltpaToken);
288: //Aligo throws exception when user is null, hence the following workaround
289: uid = "sso";
290: password = "sso";
291: }
292: }
293: if (host != null)
294: props.put("ab.host", host);
295: if (uid != null) {
296: props.put("ab.userName", uid);
297: props.put("ab.userMailBox", uid);
298: }
299: if (abType != null)
300: props.put("ab.type", abType);
301: if (port != null)
302: props.put("ab.port", port);
303: if (logger.isLoggable(Level.INFO))
304: props.put("ab.pim.debug", "true");
305:
306: if (logger.isLoggable(Level.INFO)) {
307: String[] param = new String[3];
308: param[0] = adapterName;
309: param[1] = (String) props.toString();
310: param[2] = identifier;
311: logger.log(Level.INFO, "PSSA_CSSI0055", param);
312: }
313:
314: if (password != null)
315: props.put("ab.userPassword", password);
316:
317: abSession = abSession.getInstance(props);
318:
319: return abSession;
320: }
321:
322: /**
323: * Tests service availability.
324: */
325: public boolean isAvailable() {
326: try {
327: if (abStore != null && abStore.isConnected()) {
328: if (logger.isLoggable(Level.INFO)) {
329: logger.log(Level.INFO, "PSSA_CSSI0057",
330: new String[] { adapterName, identifier });
331: }
332: return true;
333: } else {
334: return false;
335: }
336: } catch (ABStoreException abse) {
337: if (logger.isLoggable(Level.SEVERE)) {
338: logger.log(Level.SEVERE, "PSSA_CSSI0058", abse);
339: }
340: return false;
341: }
342: }
343:
344: /**
345: * Adapter specific Connection termination.
346: *
347: * @return true if the connection was terminated successfully.
348: */
349: public boolean closeConnection() {
350: boolean retval = true;
351:
352: try {
353: abStore.disconnect();
354: abStore = null;
355: abSession = null;
356: } catch (Exception e) {
357: retval = false;
358: }
359:
360: if (logger.isLoggable(Level.INFO)) {
361: logger.log(Level.INFO, "PSSA_CSSI0005", new String[] {
362: adapterName, identifier });
363: }
364:
365: return retval;
366: }
367:
368: /**
369: * Implements SSOTokenListener "ssoTokenChanged" method.
370: *
371: * The following are possible SSO token event types:
372: * <ul>
373: * <li>SSO_TOKEN_IDLE_TIMEOUT
374: * <li>SSO_TOKEN_MAX_TIMEOUT
375: * <li>SSO_TOKEN_DESTROY
376: * </ul>
377: *
378: * The event getType() method is used to ensure that one of the
379: * three types above are the basis for this event. If getType()
380: * returns a type not listed above, then an SSOException is thrown.
381: *
382: * @param evt SSOTokenEvent
383: */
384: public void ssoTokenChanged(SSOTokenEvent evt) {
385:
386: try {
387: int evtType = evt.getType();
388:
389: if (abStore != null) {
390: abStore.disconnect();
391: }
392:
393: abStore = null;
394: abSession = null;
395: } catch (Exception e) {
396: if (logger.isLoggable(Level.WARNING)) {
397: logger.log(Level.WARNING, "PSSA_CSSI0006", e);
398: }
399: return;
400: }
401:
402: if (logger.isLoggable(Level.INFO)) {
403: logger.log(Level.INFO, "PSSA_CSSI0002", new String[] {
404: adapterName, identifier });
405: }
406: }
407:
408: }
|