KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > ca > commons > jndi > ConnectionData


1 package com.ca.commons.jndi;
2
3 import javax.naming.NamingException JavaDoc;
4 import javax.naming.Context JavaDoc;
5 import java.util.*;
6
7 /**
8  * The ConnectionData inner class is used to pass
9  * connection data around. Not all fields are
10  * guaranteed to be valid values.
11  */

12
13 public class ConnectionData
14 {
15     /**
16      * The base to start browsing from, e.g.'o=Democorp,c=au'.
17      * (This is often reset to what the directory says the base
18      * is in practice).
19      */

20
21     public String JavaDoc baseDN = "";
22
23     /**
24      * The LDAP Version (2 or 3) being used.
25      */

26
27     public int version = 3; // default to 3...
28

29     /**
30      * Which protocol to use (currently "ldap", "dsml")
31      */

32
33     public static final String JavaDoc LDAP = "ldap";
34     public static final String JavaDoc DSML = "dsml";
35     public String JavaDoc protocol = LDAP; // default is always to use LDAP
36

37     /**
38      * A URL of the form ldap://hostname:portnumber.
39      */

40
41     public String JavaDoc url;
42
43     /**
44      * The Manager User's distinguished name (optionally null if not used).
45      */

46
47     public String JavaDoc userDN;
48
49     /**
50      * The Manager User's password - (is null if user is not manager).
51      */

52
53     public char[] pwd;
54
55     /**
56      * The jndi ldap referral type: [follow:ignore:throw] (may be null - defaults to 'follow').
57      */

58
59     public String JavaDoc referralType = "follow";
60
61     /**
62      * How aliases should be handled in searches ('always'|'never'|'find'|'search').
63      */

64
65     public String JavaDoc aliasType = "searching";
66
67     /**
68      * Whether to use SSL (either simple or client-authenticated).
69      */

70
71     public boolean useSSL;
72     
73     /**
74      * The file containing the trusted server certificates (no keys).
75      */

76
77     // XXX we may want to expand this later to 'SSL type'
78
public String JavaDoc cacerts;
79
80     /**
81      * The file containing client certificates and private key(s).
82      */

83
84     public String JavaDoc clientcerts;
85
86     /**
87      * The password to the ca's keystore (may be null for non-client authenticated ssl).
88      */

89
90     public char[] caKeystorePwd;
91
92     /**
93      * The password to the client's keystore (may be null for non-client authenticated ssl).
94      */

95
96     public char[] clientKeystorePwd;
97
98     /**
99      * The type of ca keystore file; e.g. 'JKS', or 'PKCS12'.
100      */

101
102     public String JavaDoc caKeystoreType;
103
104     /**
105      * The type of client keystore file; e.g. 'JKS', or 'PKCS12'.
106      */

107
108     public String JavaDoc clientKeystoreType;
109
110     /**
111      * The SSL connection socket factory. This defaults to com.ca.commons.jndi.JndiSocketFactory
112      */

113
114     public String JavaDoc sslSocketFactory = "com.ca.commons.jndi.JndiSocketFactory";
115
116     /**
117      * Whether to set BER tracing on or not. (This is a very verbose
118      * dump of all the raw ldap data as it streams past).
119      */

120
121     public boolean tracing;
122
123     /**
124      * Whether to set SSL tracing on or not. (This is a very verbose
125      * dump of all the SSL data as it streams past).
126      */

127
128     public boolean sslTracing;
129
130
131     private static final String JavaDoc DEFAULT_CTX = "com.sun.jndi.ldap.LdapCtxFactory";
132
133 // private static final String DEFAULT_DSML_CTX = "com.sun.jndi.dsmlv2.soap.DsmlSoapCtxFactory";
134
private static final String JavaDoc DEFAULT_DSML_CTX = "com.ca.jndiproviders.dsml.DsmlCtxFactory";
135
136
137     // Vadim: GSSAPI
138

139         /**
140          * Whether to use GSSAPI
141          */

142
143     public boolean useGSSAPI;
144
145     /**
146      * Any extra environment magic required; e.g. to make GSSAPI work
147      */

148     public Properties extraProperties;
149
150
151     /**
152      * Empty constructor - data fields are intended
153      * to be set directly.
154      */

155
156     public ConnectionData()
157     {
158     }
159
160     /**
161      * This sets up a full connection data object with the information needed to
162      * create a jndi environment properties object. Usually you won't need to use
163      * the full method, and can use one of the shorter versions that sets empty
164      * defaults for the unused bits.
165      *
166      * @param version
167      * @param url
168      * @param userDN
169      * @param pwd
170      * @param tracing
171      * @param referralType
172      * @param aliasType
173      * @param useSSL
174      * @param cacerts
175      * @param clientcerts
176      * @param caKeystorePwd
177      * @param clientKeystorePwd
178      * @param caKeystoreType
179      * @param clientKeystoreType
180      * @param useGSSAPI whether to use the GSSAPI protocol (e.g. for Kerberos support)
181      * @param extraProperties a 'get out of jail free' for any bizarre properties that haven't
182      * already been covered, or that are introduced in the future. Using this isn't really
183      * good coding practice, since we don't know what there properties are, but is sometimes
184      * required...
185      *
186      */

187     public ConnectionData(int version,
188                           String JavaDoc url,
189                           String JavaDoc userDN,
190                           char[] pwd,
191                           boolean tracing,
192                           String JavaDoc referralType,
193                           String JavaDoc aliasType,
194                           boolean useSSL,
195                           String JavaDoc cacerts,
196                           String JavaDoc clientcerts,
197                           char[] caKeystorePwd,
198                           char[] clientKeystorePwd,
199                           String JavaDoc caKeystoreType,
200                           String JavaDoc clientKeystoreType,
201                           boolean useGSSAPI,
202                           Properties extraProperties)
203     {
204         this.version = version;
205         this.url = url;
206         this.userDN = userDN;
207         this.pwd = pwd;
208         this.referralType = referralType;
209         this.aliasType = aliasType;
210         this.useSSL = useSSL;
211         this.cacerts = cacerts;
212         this.clientcerts = clientcerts;
213         this.caKeystorePwd = caKeystorePwd;
214         this.clientKeystorePwd = clientKeystorePwd;
215         this.caKeystoreType = caKeystoreType;
216         this.clientKeystoreType = clientKeystoreType;
217         this.tracing = tracing;
218
219         this.sslTracing = tracing; // XXX for the time being, BER tracing and SSL Tracing are entwined :-).
220

221         this.useGSSAPI = useGSSAPI;
222         this.extraProperties = extraProperties;
223     }
224
225     /**
226      * Utility method for test routines
227      *
228      * @param version
229      * @param url
230      * @param userDN
231      * @param pwd
232      * @param tracing
233      * @param referralType
234      * @param aliasType
235      */

236     public ConnectionData(int version,
237                           String JavaDoc url,
238                           String JavaDoc userDN,
239                           char[] pwd,
240                           boolean tracing,
241                           String JavaDoc referralType,
242                           String JavaDoc aliasType)
243     {
244         this.version = version;
245         this.url = url;
246         this.userDN = userDN;
247         this.pwd = pwd;
248         this.referralType = referralType;
249         this.aliasType = aliasType;
250         this.sslTracing = tracing; // XXX for the time being, BER tracing and SSL Tracing are entwined :-).
251
}
252
253
254     public void setProtocol(String JavaDoc newProtocol)
255     {
256         if (newProtocol.equalsIgnoreCase(LDAP))
257             protocol = LDAP;
258         else if (newProtocol.equalsIgnoreCase(DSML))
259             protocol = DSML;
260         else
261             System.err.println("Unknown Protocol " + newProtocol);
262     }
263
264     /**
265      * This should be used to clear all the passwords
266      * saved in this data object when they have been
267      * used and are no longer needed... make sure however
268      * that no references to the passwords remain to be
269      * used by other parts of the program first :-)!
270      * <p/>
271      * (nb - since JNDI uses the passwords as Strings, they
272      * can still be sniffed from JNDI :-( ).
273      */

274
275     public void clearPasswords()
276     {
277         if (pwd != null) for (int i = 0; i < pwd.length; i++) pwd[i] = ' '; //TE: null is incompatible.
278
if (caKeystorePwd != null) for (int i = 0; i < caKeystorePwd.length; i++) caKeystorePwd[i] = ' ';
279         if (clientKeystorePwd != null) for (int i = 0; i < clientKeystorePwd.length; i++) clientKeystorePwd[i] = ' ';
280
281         pwd = null;
282         caKeystorePwd = null;
283         clientKeystorePwd = null;
284     }
285
286
287     /**
288      * Sets the url from the host & port, e.g. "ldap://" + host + ":" + port".
289      * (NB: If the protocol is <i>NOT</i> LDAP, (e.g. DSML) this must be set first.
290      *
291      * @param host the host name to connect to, e.g. echidna or 168.10.5.122.
292      * @param port the host port to connect to, e.g. 19389.
293      */

294
295     public void setURL(String JavaDoc host, int port)
296     {
297         if (protocol == LDAP)
298             url = "ldap://" + host + ":" + port;
299         else if (protocol == DSML)
300             url = "http://" + host + ":" + port;
301
302     }
303
304     /**
305      * Sets the url from the host & port, e.g. "ldap://" + host + ":" + port".
306      * (NB: If the protocol is <i>NOT</i> LDAP, (e.g. DSML) this must be set first.
307      *
308      * @param URL The full URL to connect to
309      */

310
311     public void setURL(String JavaDoc URL)
312     {
313         if (protocol == LDAP)
314         {
315             if (URL.toLowerCase().startsWith("ldap://"))
316                 url = URL;
317             else
318                 url = "ldap://" + URL;
319         }
320         else if (protocol == DSML)
321         {
322             if (URL.toLowerCase().startsWith("http://"))
323                 url = URL;
324             else if (URL.toLowerCase().startsWith("dsml://"))
325                 url = "http://" + URL.substring(7);
326             else
327                 url = "http://" + URL;
328         }
329         else // not sure if this is necessary...
330
{
331             if (URL.toLowerCase().startsWith("ldap:"))
332             {
333                 protocol = LDAP;
334                 url = URL;
335             }
336             else if (URL.toLowerCase().startsWith("http:"))
337             {
338                 protocol = DSML;
339                 url = URL;
340             }
341             else if (URL.toLowerCase().startsWith("dsml:"))
342             {
343                 protocol = DSML;
344                 url = "http:" + URL.substring(5);
345             }
346         }
347     }
348
349     public String JavaDoc getURL()
350     {
351         return url;
352     }
353
354     /**
355      * Gets the host name from the url string.
356      *
357      * @return the host name for example: DEMOCORP.
358      */

359
360     // parse rules; the url is always of the form <protocol>://<hostname>:<port>[/server stuff (for dsml only)]
361

362     public String JavaDoc getHost()
363     {
364         if (url == null)
365             return null;
366
367         int protocolSeparator = url.indexOf("://") + 3;
368         int portSeparator = url.indexOf(":", protocolSeparator);
369         return url.substring(protocolSeparator, portSeparator);
370     }
371
372
373     /**
374      * Gets the port number from the url string.
375      *
376      * @return the port number for example: 19389.
377      */

378
379     public int getPort()
380     {
381         if (url == null)
382             return -1;
383
384         try
385         {
386             int protocolSeparator = url.indexOf("://") + 3;
387             int portSeparator = url.indexOf(":", protocolSeparator) + 1;
388             int serverDetails = url.indexOf("/", portSeparator);
389
390             String JavaDoc port = (serverDetails == -1) ? url.substring(portSeparator) : url.substring(portSeparator, serverDetails);
391             int portNumber = Integer.parseInt(port);
392             if (portNumber > 65536 || portNumber <= 0)
393                 return -1;
394
395             return portNumber;
396         }
397         catch (NumberFormatException JavaDoc nfe)
398         {
399             return -1;
400         }
401     }
402
403
404     /**
405      * Returns this data object as a string (doesn't include passwords)..
406      *
407      * @return the data object as a string.
408      */

409
410     public String JavaDoc toString()
411     {
412         return new String JavaDoc("baseDN: " + baseDN +
413                 "\nversion: " + Integer.toString(version) +
414                 "\nurl: " + url +
415                 "\nuserDN: " + userDN +
416                 "\nreferralType: " + referralType +
417                 "\naliasType: " + aliasType +
418                 "\nuseSSL: " + String.valueOf(useSSL) +
419                 "\ncacerts: " + cacerts +
420                 "\nclientcerts: " + clientcerts +
421                 "\ncaKeystoreType: " + caKeystoreType +
422                 "\nclientKeystoreType: " + clientKeystoreType +
423                 "\ncaKeystorePwd; " + new String JavaDoc(caKeystorePwd) +
424                 "\nclientKeystorePwd: " + new String JavaDoc(clientKeystorePwd) +
425                 "\ntracing: " + String.valueOf(tracing) +
426                 "\nprotocol: " + protocol +
427                 "\nsslSocketFactory: " + sslSocketFactory +
428                 "\nuseGSSAPI: " + String.valueOf(useGSSAPI));
429     }
430
431     /**
432      * This returns the connection data as a jndi env object suitable for
433      * use in opening a directory context.
434      *
435      * @return
436      * @throws NamingException a large range of exceptions, ranging from invalid data through
437      * to problems setting up the SSL connection.
438      */

439     public Hashtable getJNDIEnvironment()
440             throws NamingException JavaDoc
441     {
442 /*
443    These are the ConnectionData variables to be placed into the hash table...
444
445         version
446         url
447         userDN
448         pwd
449         referralType
450         aliasType
451         useSSL
452         cacerts
453         clientcerts
454         caKeystorePwd
455         clientKeystorePwd
456         caKeystoreType
457         clientKeystoreType
458         tracing
459         sslTracing
460         useGSSAPI
461
462         ... while 'extraProperties' is simply appended to the environment data
463 */

464         checkData(); // throws NamingException if data invalid.
465

466         Hashtable env = new Hashtable(); // an environment for jndi context parameters
467

468         if (protocol == DSML) //TE: set the protocol to DSML or LDAP.
469
env.put(Context.INITIAL_CONTEXT_FACTORY, DEFAULT_DSML_CTX);
470         else if (protocol == LDAP)
471             env.put(Context.INITIAL_CONTEXT_FACTORY, DEFAULT_CTX);
472
473         JNDIOps.setupBasicProperties(env, url, tracing, referralType, aliasType); // set up the bare minimum parameters
474

475
476         // XXX should we pass the security type through to here to avoid this implicit check??
477
// XXX evil warning - this sets Context.SECURITY_AUTHENTICATION to simple, it is over-ridden
478
// XXX by other types below.
479
if (pwd != null && userDN != null)
480         {
481             JNDIOps.setupSimpleSecurityProperties(env, userDN, pwd);
482         }
483         // add the SSL ('ca...') and possible SASL ('client...') parameters
484
if (useSSL)
485         {
486
487             if (tracing)
488                 sslTracing = true; // for the time being, bind tracing and sslTracing.
489

490             JNDIOps.setupSSLProperties(env, cacerts, clientcerts,
491                     caKeystorePwd, clientKeystorePwd,
492                     caKeystoreType, clientKeystoreType,
493                     sslTracing, sslSocketFactory);
494         }
495
496         // Vadim: GSSAPI
497

498         if (useGSSAPI)
499         {
500             env.put(Context.SECURITY_AUTHENTICATION, "GSSAPI");
501             //Maybe include something like JNDIOps.setupKerberosProperties here??
502
}
503
504         // Add any 'extra' properties to the list.
505
if (extraProperties!=null && extraProperties.size()>0)
506         {
507             Enumeration extraKeys = extraProperties.keys();
508             while (extraKeys.hasMoreElements())
509             {
510                 try
511                 {
512                     String JavaDoc key = (String JavaDoc)extraKeys.nextElement();
513                     String JavaDoc value = (String JavaDoc)extraProperties.getProperty(key);
514                     if (value != null)
515                         env.put(key, value);
516                 }
517                 catch (ClassCastException JavaDoc e) {} // do nothing, but skip non string properties (should never happen)
518
}
519         }
520
521         return env;
522     }
523
524     /**
525      * This method confirms that the data entered in the ConnectionData object is
526      * consistent, complete and valid.
527      *
528      * @throws NamingException thrown if the data is inconsistent or incomplete.
529      */

530     public void checkData() throws NamingException JavaDoc
531     {
532         // sanity check
533
if (url == null)
534             throw new NamingException JavaDoc("URL not specified in openContext()!");
535
536         if (version < 2 || version > 3)
537             throw new NamingException JavaDoc("Incorrect ldap Version! (was " + version + ")");
538
539         if (useSSL && (cacerts == null))
540             throw new NamingException JavaDoc("Cannot use SSL without a trusted CA certificates JKS file.");
541
542         if (referralType == null) referralType = "follow"; // not an error not to specify this.
543

544         if (aliasType == null) aliasType = "finding"; // not an error not to specify this
545

546         if ("followthrowignore".indexOf(referralType) == -1)
547             throw new NamingException JavaDoc("unknown referral type: " + referralType + " (setting to 'follow')");
548     }
549
550     public void putExtraProperty(String JavaDoc key, String JavaDoc property)
551     {
552         if (extraProperties==null)
553             extraProperties = new Properties();
554
555         extraProperties.put(key, property);
556     }
557 }
Popular Tags