Project

General

Profile

1
/**
2
 *  '$RCSfile$'
3
 *    Purpose: An implementation of the AuthInterface interface that
4
 *             allows Metacat to use the LDAP protocol for
5
 *             directory services
6
 *  Copyright: 2000 Regents of the University of California and the
7
 *             National Center for Ecological Analysis and Synthesis
8
 *    Authors: Matt Jones
9
 *    Release: @release@
10
 *
11
 *   '$Author: sgarg $'
12
 *     '$Date: 2006-07-19 08:56:59 -0700 (Wed, 19 Jul 2006) $'
13
 * '$Revision: 3023 $'
14
 *
15
 * This program is free software; you can redistribute it and/or modify
16
 * it under the terms of the GNU General Public License as published by
17
 * the Free Software Foundation; either version 2 of the License, or
18
 * (at your option) any later version.
19
 *
20
 * This program is distributed in the hope that it will be useful,
21
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
23
 * GNU General Public License for more details.
24
 *
25
 * You should have received a copy of the GNU General Public License
26
 * along with this program; if not, write to the Free Software
27
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
28
 */
29

    
30
package edu.ucsb.nceas.metacat;
31

    
32
import java.net.ConnectException;
33
import javax.naming.AuthenticationException;
34
import javax.naming.Context;
35
import javax.naming.NamingEnumeration;
36
import javax.naming.NamingException;
37
import javax.naming.SizeLimitExceededException;
38
import javax.naming.directory.InvalidSearchFilterException;
39
import javax.naming.directory.Attribute;
40
import javax.naming.directory.Attributes;
41
import javax.naming.directory.DirContext;
42
import javax.naming.directory.InitialDirContext;
43
import javax.naming.directory.SearchResult;
44
import javax.naming.directory.SearchControls;
45
import javax.naming.ReferralException;
46
import javax.naming.ldap.InitialLdapContext;
47
import javax.naming.ldap.LdapContext;
48
import javax.naming.ldap.StartTlsRequest;
49
import javax.naming.ldap.StartTlsResponse;
50
import javax.net.ssl.SSLSession;
51

    
52
import org.apache.log4j.Logger;
53

    
54
import java.net.URLDecoder;
55
import java.util.Iterator;
56
import java.util.HashMap;
57
import java.util.Hashtable;
58
import java.util.Enumeration;
59
import java.util.Set;
60
import java.util.Vector;
61

    
62
/**
63
 * An implementation of the AuthInterface interface that
64
 * allows Metacat to use the LDAP protocol for directory services.
65
 * The LDAP authentication service is used to determine if a user
66
 * is authenticated, and whether they are a member of a particular group.
67
 */
68
public class AuthLdap
69
    implements AuthInterface, Runnable {
70
  private MetaCatUtil util = new MetaCatUtil();
71
  private String ldapUrl;
72
  private String ldapsUrl;
73
  private String ldapBase;
74
  private String referral;
75
  private Context referralContext;
76
  Hashtable env = new Hashtable(11);
77
  private Context rContext;
78
  private String userName;
79
  private String userPassword;
80
  ReferralException refExc;
81

    
82
  private static Logger logMetacat = Logger.getLogger(AuthLdap.class);
83
  
84
  /**
85
   * Construct an AuthLdap
86
   */
87
  public AuthLdap() {
88
    // Read LDAP URI for directory service information
89
    this.ldapUrl = MetaCatUtil.getOption("ldapurl");
90
    this.ldapsUrl = MetaCatUtil.getOption("ldapsurl");
91
    this.ldapBase = MetaCatUtil.getOption("ldapbase");
92
    this.referral = MetaCatUtil.getOption("referral");
93
  }
94

    
95
  /**
96
   * Determine if a user/password are valid according to the authentication
97
   * service.
98
   *
99
   * @param user the name of the principal to authenticate
100
   * @param password the password to use for authentication
101
   * @returns boolean true if authentication successful, false otherwise
102
   */
103
  
104
  public boolean authenticate(String user, String password) throws
105
      ConnectException {
106
    String ldapUrl = this.ldapUrl;
107
    String ldapsUrl = this.ldapsUrl;
108
    String ldapBase = this.ldapBase;
109
    boolean authenticated = false;
110
    String identifier = user;
111
    
112
    //get uid here.
113
    String uid=user.substring(0, user.indexOf(","));
114
    user = user.substring(user.indexOf(","), user.length());
115

    
116
    logMetacat.debug("identifier: " + identifier);
117
    logMetacat.debug("uid: " + uid);
118
    logMetacat.debug("user: " + user);
119
    
120
    try {
121
    	// Check the usename as passed in
122
        logMetacat.info("Calling ldapAuthenticate");
123
        logMetacat.info("with user as identifier: " + identifier);
124

    
125
        authenticated = ldapAuthenticate(identifier, password, 
126
        		(new Boolean(MetaCatUtil.getOption("onlySecureLDAPConnection"))).booleanValue());
127
        // if not found, try looking up a valid DN then auth again
128
        if (!authenticated) {
129
        	logMetacat.info("Not Authenticated");
130
        	logMetacat.info("Looking up DN for: " + identifier);
131
        	identifier = getIdentifyingName(identifier, ldapUrl, ldapBase);
132
        	if(identifier == null){
133
        		logMetacat.info("No DN found from getIdentifyingName");
134
        		return authenticated;
135
        	}
136
        	
137
           	logMetacat.info("DN found from getIdentifyingName: " + identifier);
138
        	String decoded = URLDecoder.decode(identifier);
139
        	logMetacat.info("DN decoded: " + decoded);
140
        	identifier = decoded;
141
        	String refUrl = "";
142
        	String refBase = "";
143
        	if (identifier.startsWith("ldap")) {
144
        		logMetacat.debug("identifier starts with ldap");
145

    
146
        		refUrl = identifier.substring(0, identifier.lastIndexOf("/") + 1);
147
        		int position = identifier.indexOf(",");
148
        		int position2 = identifier.indexOf(",", position + 1);
149
        		
150
        		refBase = identifier.substring(position2 + 1);
151
        		identifier = identifier.substring(identifier.lastIndexOf("/") + 1);
152
        		
153
        		logMetacat.info("Calling ldapAuthenticate");
154
        		logMetacat.info("with user as identifier: " + identifier);
155
        		logMetacat.info("and refUrl as: " + refUrl);
156
        		logMetacat.info("and refBase as: " + refBase);
157

    
158
        		authenticated = ldapAuthenticate(identifier, password, refUrl, refBase,
159
                		(new Boolean(MetaCatUtil.getOption("onlySecureLDAPReferalsConnection")))
160
                			.booleanValue());
161
        	} else {
162
        		logMetacat.info("identifier doesnt start with ldap");
163
        		identifier = identifier + "," + ldapBase;
164
        		
165
        		logMetacat.info("Calling ldapAuthenticate");
166
        		logMetacat.info("with user as identifier: " + identifier);
167
        		
168
        		authenticated = ldapAuthenticate(identifier, password,
169
            		(new Boolean(MetaCatUtil.getOption("onlySecureLDAPConnection"))).booleanValue());
170
        	}
171
        }
172
    }
173
    catch (NullPointerException e) {
174
    	logMetacat.error("NullPointerException while authenticating in " +
175
                        "AuthLdap.authenticate: " + e);
176
    	e.printStackTrace();
177

    
178
    	throw new ConnectException(
179
          "NullPointerException while authenticating in " +
180
          "AuthLdap.authenticate: " + e);
181
    } catch (NamingException e) {
182
    	logMetacat.error("Naming exception while authenticating in " +
183
                        "AuthLdap.authenticate: " + e);
184
    	e.printStackTrace();
185
    } catch (Exception e) {
186
    	logMetacat.error(e.getMessage());
187
    }
188
    
189
    return authenticated;
190
  }
191

    
192
  /**
193
   * Connect to the LDAP directory and do the authentication using the
194
   * username and password as passed into the routine.
195
   *
196
   * @param identifier the distinguished name to check against LDAP
197
   * @param password the password for authentication
198
   */
199
  private boolean ldapAuthenticate(String identifier, String password, 
200
		  boolean secureConnectionOnly) throws ConnectException, NamingException, 
201
		  NullPointerException {
202
    return ldapAuthenticate(identifier, password,
203
                            this.ldapsUrl, this.ldapBase, secureConnectionOnly);
204
  }
205

    
206
  /**
207
   * Connect to the LDAP directory and do the authentication using the
208
   * username and password as passed into the routine.
209
   *
210
   * @param identifier the distinguished name to check against LDAP
211
   * @param password the password for authentication
212
   */
213
  
214
  private boolean ldapAuthenticate(String dn, String password, String rootServer, 
215
		  String rootBase, boolean secureConnectionOnly){
216
	  
217
	  boolean authenticated = false;
218
		
219
	  String server = "";
220
	  String userDN = "";
221
	  logMetacat.info("dn is: " + dn);
222

    
223
	  int position = dn.lastIndexOf("/");
224
      logMetacat.debug("position is: " + position);
225
	  if (position == -1) {
226
		  server = rootServer;
227
		  if(dn.indexOf(userDN) < 0){
228
			  userDN = dn + "," + rootBase;
229
		  } else {
230
			  userDN = dn;
231
		  }
232
		  logMetacat.info("userDN is: " + userDN);
233

    
234
       } else {
235
		  server = dn.substring(0, position+1);
236
		  userDN = dn.substring(position+1);
237
		  logMetacat.info("server is: " + server);
238
		  logMetacat.info("userDN is: " + userDN);
239
	   }
240
		          
241
	   logMetacat.warn("Trying to authenticate: " + userDN);
242
	   logMetacat.warn("          Using server: " + server);
243
		          
244
	   LdapContext ctx = null;
245
	   double startTime;
246
	   double stopTime;
247
	   try {
248
		   Hashtable env = new Hashtable();
249
		   env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
250
		   env.put(Context.PROVIDER_URL, server);
251
		   env.put(Context.REFERRAL, "throw");
252

    
253
		   try {
254
			   
255
			   startTime = System.currentTimeMillis();
256
			   ctx = new InitialLdapContext(env, null);
257
			   
258
			   // Start up TLS here so that we don't pass our jewels in cleartext
259
		       StartTlsResponse tls =
260
		              (StartTlsResponse)ctx.extendedOperation(new StartTlsRequest());
261
		       //tls.setHostnameVerifier(new SampleVerifier());
262
		       SSLSession sess = tls.negotiate();
263
			   
264
		       ctx.addToEnvironment(Context.SECURITY_AUTHENTICATION, "simple");
265
			   ctx.addToEnvironment(Context.SECURITY_PRINCIPAL, userDN);
266
			   ctx.addToEnvironment(Context.SECURITY_CREDENTIALS, password);
267
			   ctx.reconnect(null);
268
			   
269
			   stopTime = System.currentTimeMillis();
270
			   logMetacat.info("Connection time thru " + ldapsUrl + " was: " +
271
                       	(stopTime - startTime) / 1000 + " seconds.");
272
			   
273
			   authenticated = true;
274
		   } catch (java.io.IOException ioe) {
275
			   logMetacat.warn("Caught IOException in login while negotiating TLS: "
276
	                                 + ioe.getMessage());
277
			   
278
			   if(secureConnectionOnly){
279
			   	  
280
				   return authenticated;
281
			   
282
			   } else {
283

    
284
				   logMetacat.info("Trying to authenticate without TLS");
285
				   env.put(Context.SECURITY_AUTHENTICATION, "simple");
286
				   env.put(Context.SECURITY_PRINCIPAL, userDN);
287
				   env.put(Context.SECURITY_CREDENTIALS, password);
288
				   
289
				   startTime = System.currentTimeMillis();
290
				   ctx = new InitialLdapContext(env, null);				
291
				   stopTime = System.currentTimeMillis();
292
				   logMetacat.info("Connection time thru " + ldapsUrl + " was: " +
293
	                       	(stopTime - startTime) / 1000 + " seconds.");
294
				   
295
				   authenticated = true;
296
			   }
297
		   }
298
	   } catch (AuthenticationException ae) {
299
		   authenticated = false;
300
	   } catch (javax.naming.InvalidNameException ine) {
301
	        logMetacat.error("An invalid DN was provided!");
302
	   } catch (NamingException e) {
303
		   logMetacat.warn("Caught NamingException in login: " + e.getClass().getName());
304
		   logMetacat.info(e.toString() + "  " + e.getRootCause());
305
       }
306

    
307
       return authenticated;
308
  }
309

    
310

    
311
  /**
312
   * Get the identifying name for a given userid or name.  This is the name
313
   * that is used in conjunction withthe LDAP BaseDN to create a
314
   * distinguished name (dn) for the record
315
   *
316
   * @param user the user for which the identifying name is requested
317
   * @returns String the identifying name for the user,
318
   *          or null if not found
319
   */
320
  private String getIdentifyingName(String user, String ldapUrl,
321
          String ldapBase) throws NamingException {
322
	  
323
      String identifier = null;
324
      Hashtable env = new Hashtable();
325
      env.put(Context.INITIAL_CONTEXT_FACTORY,
326
              "com.sun.jndi.ldap.LdapCtxFactory");
327
      env.put(Context.REFERRAL, "throw");
328
      env.put(Context.PROVIDER_URL, ldapUrl + ldapBase);
329
      try {
330
    	  int position = user.indexOf(",");
331
          String uid = user.substring(user.indexOf("=") + 1, position);
332
          logMetacat.info("uid is: " + uid);
333
          String org = user.substring(user.indexOf("=", position + 1) + 1,
334
                                        user.indexOf(",", position + 1));
335
          logMetacat.info("org is: " + org);
336
           
337
          DirContext sctx = new InitialDirContext(env);
338
          SearchControls ctls = new SearchControls();
339
          ctls.setSearchScope(SearchControls.SUBTREE_SCOPE);
340
          String filter = "(&(uid=" + uid + ")(o=" + org + "))";
341
          logMetacat.warn("Searching for DNs with following filter: " + filter);
342
          
343
          for (boolean moreReferrals = true; moreReferrals;) {
344
              try {
345
                  // Perform the search
346
                  NamingEnumeration answer = 
347
                      sctx.search("", filter, ctls);
348

    
349
                  // Return the answer
350
                  while (answer.hasMore()) {
351
                      SearchResult sr = (SearchResult)answer.next();
352
                      identifier = sr.getName();
353
                      return identifier;
354
                  }
355
                  // The search completes with no more referrals
356
                  moreReferrals = false;
357
              } catch (ReferralException e) {
358
            	  logMetacat.info("Got referral: " + e.getReferralInfo());
359
            	  // Point to the new context from the referral
360
                  if (moreReferrals) {
361
                      sctx = (DirContext) e.getReferralContext();
362
                  }
363
              }
364
          }
365
      } catch (NamingException e) {
366
    	     logMetacat.error("Naming exception while getting dn: " + e);
367
    	      throw new NamingException(
368
    	          "Naming exception in AuthLdap.getIdentifyingName: " + e);
369
    	      }
370
      return identifier;
371
  }
372
  
373
  /**
374
   * Get all users from the authentication service
375
   *
376
   * @param user the user for authenticating against the service
377
   * @param password the password for authenticating against the service
378
   * @returns string array of all of the user names
379
   */
380
  public String[][] getUsers(String user, String password) throws
381
      ConnectException {
382
    String[][] users = null;
383

    
384
    // Identify service provider to use
385
    Hashtable env = new Hashtable(11);
386
    env.put(Context.INITIAL_CONTEXT_FACTORY,
387
            "com.sun.jndi.ldap.LdapCtxFactory");
388
    env.put(Context.REFERRAL, referral);
389
    env.put(Context.PROVIDER_URL, ldapUrl);
390

    
391
    try {
392

    
393
      // Create the initial directory context
394
      DirContext ctx = new InitialDirContext(env);
395

    
396
      // Specify the attributes to match.
397
      // Users are objects that have the attribute objectclass=InetOrgPerson.
398
      SearchControls ctls = new SearchControls();
399
      String[] attrIDs = {
400
          "dn", "cn", "o", "ou", "mail"};
401
      ctls.setReturningAttributes(attrIDs);
402
      ctls.setSearchScope(SearchControls.SUBTREE_SCOPE);
403
      //ctls.setCountLimit(1000);
404
      String filter = "(objectClass=inetOrgPerson)";
405
      NamingEnumeration namingEnum = ctx.search(ldapBase, filter, ctls);
406

    
407
      // Store the users in a vector
408
      Vector uvec = new Vector();
409
      Vector uname = new Vector();
410
      Vector uorg = new Vector();
411
      Vector uou = new Vector();
412
      Vector umail = new Vector();
413
      Attributes tempAttr = null;
414
      try {
415
        while (namingEnum.hasMore()) {
416
          SearchResult sr = (SearchResult) namingEnum.next();
417
          tempAttr = sr.getAttributes();
418

    
419
          if ( (tempAttr.get("cn") + "").startsWith("cn: ")) {
420
            uname.add( (tempAttr.get("cn") + "").substring(4));
421
          }
422
          else {
423
            uname.add(tempAttr.get("cn") + "");
424
          }
425

    
426
          if ( (tempAttr.get("o") + "").startsWith("o: ")) {
427
            uorg.add( (tempAttr.get("o") + "").substring(3));
428
          }
429
          else {
430
            uorg.add(tempAttr.get("o") + "");
431
          }
432

    
433
          if ( (tempAttr.get("ou") + "").startsWith("ou: ")) {
434
            uou.add( (tempAttr.get("ou") + "").substring(4));
435
          }
436
          else {
437
            uou.add(tempAttr.get("ou") + "");
438
          }
439

    
440
          if ( (tempAttr.get("mail") + "").startsWith("mail: ")) {
441
            umail.add( (tempAttr.get("mail") + "").substring(6));
442
          }
443
          else {
444
            umail.add(tempAttr.get("mail") + "");
445
          }
446

    
447
          uvec.add(sr.getName() + "," + ldapBase);
448
        }
449
      }
450
      catch (SizeLimitExceededException slee) {
451
        logMetacat.error("LDAP Server size limit exceeded. " +
452
                          "Returning incomplete record set.");
453
      }
454

    
455
      // initialize users[]; fill users[]
456
      users = new String[uvec.size()][5];
457
      for (int i = 0; i < uvec.size(); i++) {
458
        users[i][0] = (String) uvec.elementAt(i);
459
        users[i][1] = (String) uname.elementAt(i);
460
        users[i][2] = (String) uorg.elementAt(i);
461
        users[i][3] = (String) uorg.elementAt(i);
462
        users[i][4] = (String) umail.elementAt(i);
463
      }
464

    
465
      // Close the context when we're done
466
      ctx.close();
467

    
468
    }
469
    catch (NamingException e) {
470
      logMetacat.error("Problem getting users in AuthLdap.getUsers:" + e);
471
      //e.printStackTrace(System.err);
472
      throw new ConnectException(
473
          "Problem getting users in AuthLdap.getUsers:" + e);
474
    }
475

    
476
    return users;
477
  }
478

    
479
  
480
  /**
481
   * Get all users from the authentication service
482
   *
483
   * @param user the user for authenticating against the service
484
   * @param password the password for authenticating against the service
485
   * @returns string array of all of the user names
486
   */
487
  public String[] getUserInfo(String user, String password) throws
488
      ConnectException {
489
    String[] userinfo = new String[3];
490

    
491
    // Identify service provider to use
492
    Hashtable env = new Hashtable(11);
493
    env.put(Context.INITIAL_CONTEXT_FACTORY,
494
            "com.sun.jndi.ldap.LdapCtxFactory");
495
    env.put(Context.REFERRAL, referral);
496
    env.put(Context.PROVIDER_URL, ldapUrl);
497

    
498
    try {
499
      
500
      // Create the initial directory context
501
      DirContext ctx = new InitialDirContext(env);
502
      // Specify the attributes to match.
503
      // Users are objects that have the attribute objectclass=InetOrgPerson.
504
      SearchControls ctls = new SearchControls();
505
      String[] attrIDs = {
506
          "cn", "o", "mail"};
507
      ctls.setReturningAttributes(attrIDs);
508
      ctls.setSearchScope(SearchControls.SUBTREE_SCOPE);
509
      //ctls.setCountLimit(1000);
510
      // create the filter based on the uid
511
      
512
      String filter = null;
513
      
514
      if(user.indexOf("o=")>0){
515
    	  String tempStr = user.substring(user.indexOf("o="));
516
    	  filter = "(&(" + user.substring(0, user.indexOf(",")) 
517
			+ ")(" + tempStr.substring(0, tempStr.indexOf(",")) 
518
			+ "))";      
519
      } else{
520
    	  filter = "(&(" + user.substring(0, user.indexOf(",")) 
521
			+ "))";          		  
522
      }
523
   	  filter = "(&(" + user.substring(0, user.indexOf(",")) 
524
		+ "))";          		  
525

    
526
      NamingEnumeration namingEnum = ctx.search(user, filter, ctls);
527
      
528
      Attributes tempAttr = null;
529
      try {
530
        while (namingEnum.hasMore()) {
531
          SearchResult sr = (SearchResult) namingEnum.next();
532
          tempAttr = sr.getAttributes();
533

    
534
          if ( (tempAttr.get("cn") + "").startsWith("cn: ")) {
535
        	  userinfo[0] = (tempAttr.get("cn") + "").substring(4);
536
          }
537
          else {
538
        	  userinfo[0] = (tempAttr.get("cn") + "");
539
          }
540

    
541
          if ( (tempAttr.get("o") + "").startsWith("o: ")) {
542
        	  userinfo[1] = (tempAttr.get("o") + "").substring(3);
543
          }
544
          else {
545
        	  userinfo[1] = (tempAttr.get("o") + "");
546
          }
547

    
548
          if ( (tempAttr.get("mail") + "").startsWith("mail: ")) {
549
        	  userinfo[2] =  (tempAttr.get("mail") + "").substring(6);
550
          }
551
          else {
552
        	  userinfo[2] = (tempAttr.get("mail") + "");
553
          }
554
        }
555
      }
556
      catch (SizeLimitExceededException slee) {
557
        logMetacat.error("LDAP Server size limit exceeded. " +
558
                          "Returning incomplete record set.");
559
      }
560

    
561
      // Close the context when we're done
562
      ctx.close();
563

    
564
    }
565
    catch (NamingException e) {
566
      logMetacat.error("Problem getting users in AuthLdap.getUsers:" + e);
567
      //e.printStackTrace(System.err);
568
      throw new ConnectException(
569
          "Problem getting users in AuthLdap.getUsers:" + e);
570
    }
571

    
572
    return userinfo;
573
  }
574

    
575
  /**
576
   * Get the users for a particular group from the authentication service
577
   *
578
   * @param user the user for authenticating against the service
579
   * @param password the password for authenticating against the service
580
   * @param group the group whose user list should be returned
581
   * @returns string array of the user names belonging to the group
582
   */
583
  public String[] getUsers(String user, String password, String group) throws
584
      ConnectException {
585
    String[] users = null;
586

    
587
    // Identify service provider to use
588
    Hashtable env = new Hashtable(11);
589
    env.put(Context.INITIAL_CONTEXT_FACTORY,
590
            "com.sun.jndi.ldap.LdapCtxFactory");
591
    env.put(Context.REFERRAL, referral);
592
    env.put(Context.PROVIDER_URL, ldapUrl);
593

    
594
    try {
595

    
596
      // Create the initial directory context
597
      DirContext ctx = new InitialDirContext(env);
598

    
599
      // Specify the ids of the attributes to return
600
      String[] attrIDs = {
601
          "uniqueMember"};
602

    
603
      Attributes answer = ctx.getAttributes(group, attrIDs);
604

    
605
      Vector uvec = new Vector();
606
      try {
607
        for (NamingEnumeration ae = answer.getAll(); ae.hasMore(); ) {
608
          Attribute attr = (Attribute) ae.next();
609
          for (NamingEnumeration e = attr.getAll();
610
               e.hasMore();
611
               uvec.add(e.next())
612
               ) {
613
            ;
614
          }
615
        }
616
      }
617
      catch (SizeLimitExceededException slee) {
618
        logMetacat.error("LDAP Server size limit exceeded. " +
619
                          "Returning incomplete record set.");
620
      }
621

    
622
      // initialize users[]; fill users[]
623
      users = new String[uvec.size()];
624
      for (int i = 0; i < uvec.size(); i++) {
625
        users[i] = (String) uvec.elementAt(i);
626
      }
627

    
628
      // Close the context when we're done
629
      ctx.close();
630

    
631
    }
632
    catch (NamingException e) {
633
      logMetacat.error("Problem getting users for a group in " +
634
                        "AuthLdap.getUsers:" + e);
635
      throw new ConnectException(
636
          "Problem getting users for a group in AuthLdap.getUsers:" + e);
637
    }
638

    
639
    return users;
640
  }
641

    
642
  /**
643
   * Get all groups from the authentication service
644
   *
645
   * @param user the user for authenticating against the service
646
   * @param password the password for authenticating against the service
647
   * @returns string array of the group names
648
   */
649
  public String[][] getGroups(String user, String password) throws
650
      ConnectException {
651
    return getGroups(user, password, null);
652
  }
653

    
654
  /**
655
   * Get the groups for a particular user from the authentication service
656
   *
657
   * @param user the user for authenticating against the service
658
   * @param password the password for authenticating against the service
659
   * @param foruser the user whose group list should be returned
660
   * @returns string array of the group names
661
   */
662
  public String[][] getGroups(String user, String password, String foruser) throws
663
      ConnectException {
664
    Vector gvec = new Vector();
665
    Vector desc = new Vector();
666
    Attributes tempAttr = null;
667

    
668
    //Pass the username and password to run() method
669
    userName = user;
670
    userPassword = password;
671
    // Identify service provider to use
672
    env.put(Context.INITIAL_CONTEXT_FACTORY,
673
            "com.sun.jndi.ldap.LdapCtxFactory");
674
    env.put(Context.REFERRAL, "throw");
675
    env.put(Context.PROVIDER_URL, ldapUrl);
676
    try {
677
      // Create the initial directory context
678
      DirContext ctx = new InitialDirContext(env);
679
      // Specify the ids of the attributes to return
680
      String[] attrIDs = {
681
          "cn", "o", "description"};
682
      // Specify the attributes to match.
683
      // Groups are objects with attribute objectclass=groupofuniquenames.
684
      // and have attribute uniquemember: uid=foruser,ldapbase.
685
      SearchControls ctls = new SearchControls();
686
      ctls.setReturningAttributes(attrIDs);
687
      ctls.setSearchScope(SearchControls.SUBTREE_SCOPE);
688

    
689
      String filter = null;
690
      String gfilter = "(objectClass=groupOfUniqueNames)";
691
      if (null == foruser) {
692
        filter = gfilter;
693
      }
694
      else {
695
        filter = "(& " + gfilter + "(uniqueMember=" + foruser + "))";
696
      }
697
      logMetacat.info("searching for groups: " + filter);
698
      NamingEnumeration namingEnum = ctx.search(ldapBase, filter, ctls);
699

    
700
      // Print the groups
701
      logMetacat.info("getting group results.");
702
      while (namingEnum.hasMore()) {
703
        SearchResult sr = (SearchResult) namingEnum.next();
704
        tempAttr = sr.getAttributes();
705

    
706
        if ( (tempAttr.get("description") + "").startsWith("description: ")) {
707
          desc.add( (tempAttr.get("description") + "").substring(13));
708
        }
709
        else {
710
          desc.add(tempAttr.get("description") + "");
711
        }
712

    
713
        gvec.add(sr.getName() + "," + ldapBase);
714
        logMetacat.info("group " + sr.getName() +
715
                                 " added to Group vector");
716
      }
717
      // Close the context when we're done
718
      ctx.close();
719

    
720
    }
721
    catch (ReferralException re) {
722
      refExc = re;
723
      Thread t = new Thread(new GetGroup());
724
      logMetacat.info("Starting thread...");
725
      t.start();
726
      logMetacat.info("sleeping for 5 seconds.");
727
      try {
728
        Thread.sleep(5000);
729
      }
730
      catch (InterruptedException ie) {
731
        logMetacat.error("main thread interrupted: " + ie.getMessage());
732
      }
733
      //this is a manual override of jndi's hideously long time
734
      //out period.
735
      logMetacat.info("Awake after 5 seconds.");
736
      if (referralContext == null) {
737
        logMetacat.info("thread timed out...returning groups: " +
738
                          gvec.toString());
739
        String groups[][] = new String[gvec.size()][2];
740
        for (int i = 0; i < gvec.size(); i++) {
741
          groups[i][0] = (String) gvec.elementAt(i);
742
          groups[i][1] = (String) desc.elementAt(i);
743
        }
744
        t.interrupt();
745
        return groups;
746
      }
747
      DirContext dc = (DirContext) referralContext;
748
      String[] attrIDs = {
749
          "cn", "o", "description"};
750
      // Specify the attributes to match.
751
      // Groups are objects with attribute objectclass=groupofuniquenames.
752
      // and have attribute uniquemember: uid=foruser,ldapbase.
753
      SearchControls ctls = new SearchControls();
754
      ctls.setReturningAttributes(attrIDs);
755
      ctls.setSearchScope(SearchControls.SUBTREE_SCOPE);
756

    
757
      String filter = null;
758
      String gfilter = "(objectClass=groupOfUniqueNames)";
759
      if (null == foruser) {
760
        filter = gfilter;
761
      }
762
      else {
763
        filter = "(& " + gfilter + "(uniqueMember=" + foruser + "))";
764
      }
765

    
766
      try {
767
        NamingEnumeration namingEnum = dc.search(ldapBase, filter, ctls);
768
        // Print the groups
769
        while (namingEnum.hasMore()) {
770
          SearchResult sr = (SearchResult) namingEnum.next();
771
          tempAttr = sr.getAttributes();
772

    
773
          if ( (tempAttr.get("description") + "").startsWith("description: ")) {
774
            desc.add( (tempAttr.get("description") + "").substring(13));
775
          }
776
          else {
777
            desc.add(tempAttr.get("description") + "");
778
          }
779

    
780
          gvec.add(sr.getName() + "," + ldapBase);
781
        }
782

    
783
        referralContext.close();
784
        dc.close();
785
      }
786
      catch (NamingException ne) {
787
        logMetacat.info("Naming Exception in AuthLdap.getGroups for referals" +
788
                                 ne.getExplanation() + ne.getMessage());
789
      }
790
    }
791
    catch (NamingException e) {
792
      e.printStackTrace(System.err);
793
      String groups[][] = new String[gvec.size()][2];
794
      for (int i = 0; i < gvec.size(); i++) {
795
        groups[i][0] = (String) gvec.elementAt(i);
796
        groups[i][1] = (String) desc.elementAt(i);
797
      }
798
      return groups;
799
      /*throw new ConnectException(
800
             "Problem getting groups for a user in AuthLdap.getGroups:" + e);*/
801
    }
802

    
803
    logMetacat.warn("The user is in the following groups: " +
804
                             gvec.toString());
805
    String groups[][] = new String[gvec.size()][2];
806
    for (int i = 0; i < gvec.size(); i++) {
807
      groups[i][0] = (String) gvec.elementAt(i);
808
      groups[i][1] = (String) desc.elementAt(i);
809
    }
810
    return groups;
811
  }
812

    
813
  /**
814
   * Get attributes describing a user or group
815
   *
816
   * @param foruser the user for which the attribute list is requested
817
   * @returns HashMap a map of attribute name to a Vector of values
818
   */
819
  public HashMap getAttributes(String foruser) throws ConnectException {
820
    return getAttributes(null, null, foruser);
821
  }
822

    
823
  /**
824
   * Get attributes describing a user or group
825
   *
826
   * @param user the user for authenticating against the service
827
   * @param password the password for authenticating against the service
828
   * @param foruser the user whose attributes should be returned
829
   * @returns HashMap a map of attribute name to a Vector of values
830
   */
831
  public HashMap getAttributes(String user, String password, String foruser) throws
832
      ConnectException {
833
    HashMap attributes = new HashMap();
834
    String ldapUrl = this.ldapUrl;
835
    String ldapBase = this.ldapBase;
836
    String userident = foruser;
837

    
838
    // Identify service provider to use
839
    Hashtable env = new Hashtable(11);
840
    env.put(Context.INITIAL_CONTEXT_FACTORY,
841
            "com.sun.jndi.ldap.LdapCtxFactory");
842
    env.put(Context.REFERRAL, referral);
843
    env.put(Context.PROVIDER_URL, ldapUrl);
844

    
845
    try {
846

    
847
      // Create the initial directory context
848
      DirContext ctx = new InitialDirContext(env);
849

    
850
      // Ask for all attributes of the user
851
      //Attributes attrs = ctx.getAttributes(userident);
852
      Attributes attrs = ctx.getAttributes(foruser);
853

    
854
      // Print all of the attributes
855
      NamingEnumeration en = attrs.getAll();
856
      while (en.hasMore()) {
857
        Attribute att = (Attribute) en.next();
858
        Vector values = new Vector();
859
        String attName = att.getID();
860
        NamingEnumeration attvalues = att.getAll();
861
        while (attvalues.hasMore()) {
862
          String value = (String) attvalues.next();
863
          values.add(value);
864
        }
865
        attributes.put(attName, values);
866
      }
867

    
868
      // Close the context when we're done
869
      ctx.close();
870
    }
871
    catch (NamingException e) {
872
      logMetacat.error("Problem getting attributes in " +
873
                        "AuthLdap.getAttributes:" + e);
874
      throw new ConnectException(
875
          "Problem getting attributes in AuthLdap.getAttributes:" + e);
876
    }
877

    
878
    return attributes;
879
  }
880

    
881
  /**
882
   * Get list of all subtrees holding Metacat's groups and users
883
   * starting from the Metacat LDAP root,
884
   * i.e. ldap://dev.nceas.ucsb.edu/dc=ecoinformatics,dc=org
885
   */
886
  private Hashtable getSubtrees(String user, String password,
887
                                String ldapUrl, String ldapBase) throws
888
      ConnectException {
889
    Hashtable trees = new Hashtable();
890

    
891
    // Identify service provider to use
892
    Hashtable env = new Hashtable(11);
893
    env.put(Context.INITIAL_CONTEXT_FACTORY,
894
            "com.sun.jndi.ldap.LdapCtxFactory");
895
    // env.put(Context.REFERRAL, referral);
896
    // Using 'ignore' here instead of 'follow' as 'ignore' seems
897
    // to do the job better. 'follow' was not bringing up the UCNRS
898
    // and PISCO tree whereas 'ignore' brings up the tree.
899

    
900
    env.put(Context.REFERRAL, "ignore");
901
    env.put(Context.PROVIDER_URL, ldapUrl + ldapBase);
902

    
903
    try {
904

    
905
      // Create the initial directory context
906
      DirContext ctx = new InitialDirContext(env);
907

    
908
      // Specify the ids of the attributes to return
909
      String[] attrIDs = {
910
          "o", "ref"};
911
      SearchControls ctls = new SearchControls();
912
      ctls.setReturningAttributes(attrIDs);
913
      ctls.setSearchScope(SearchControls.SUBTREE_SCOPE);
914

    
915
      // Specify the attributes to match.
916
      // Subtrees from the main server are found as objects with attribute
917
      // objectclass=organization or objectclass=referral to the subtree
918
      // resided on other server.
919
      String filter = "(|(objectclass=organization)(objectclass=referral))";
920

    
921
      // Search for objects in the current context
922
      NamingEnumeration namingEnum = ctx.search("", filter, ctls);
923

    
924
      // Print the subtrees' <ldapURL, baseDN>
925
      while (namingEnum.hasMore()) {
926

    
927
        SearchResult sr = (SearchResult) namingEnum.next();
928

    
929
        Attributes attrs = sr.getAttributes();
930
        NamingEnumeration enum1 = attrs.getAll(); // "dc" and "ref" attrs
931

    
932
        if (enum1.hasMore()) {
933
          Attribute attr = (Attribute) enum1.next();
934
          String attrValue = (String) attr.get();
935
          String attrName = (String) attr.getID();
936

    
937
          if (enum1.hasMore()) {
938
            attr = (Attribute) enum1.next();
939
            String refValue = (String) attr.get();
940
            String refName = (String) attr.getID();
941
            if (ldapBase.startsWith(refName + "=" + refValue)) {
942
              trees.put(ldapBase,
943
                        attrValue.substring(0, attrValue.lastIndexOf("/") + 1));
944
            }
945
            else {
946
              // this is a referral - so organization name is appended in
947
              // front of the ldapbase.... later it is stripped out
948
              // in getPrincipals
949
              trees.put("[" + refName + "=" + refValue + "]" +
950
                        attrValue.substring(attrValue.lastIndexOf("/") + 1,
951
                                            attrValue.length()),
952
                        attrValue.substring(0, attrValue.lastIndexOf("/") + 1));
953

    
954
              // trees.put(refName + "=" + refValue + "," + ldapBase,
955
              //           attrValue.substring(0, attrValue.lastIndexOf("/") + 1));
956
            }
957

    
958
          }
959
          else if (ldapBase.startsWith(attrName + "=" + attrValue)) {
960
            trees.put(ldapBase, ldapUrl);
961
          }
962
          else {
963
            if (sr.isRelative()) {
964
              trees.put(attrName + "=" + attrValue + "," + ldapBase, ldapUrl);
965
            }
966
            else {
967
              String referenceURL = sr.getName();
968
              referenceURL = referenceURL.substring(0,
969
                  referenceURL.lastIndexOf("/") + 1);
970
              trees.put(attrName + "=" + attrValue + "," + ldapBase,
971
                        referenceURL);
972
            }
973

    
974
          }
975
        }
976
      }
977

    
978
      // Close the context when we're done
979
      ctx.close();
980

    
981
    }
982
    catch (NamingException e) {
983
      logMetacat.error("Problem getting subtrees in AuthLdap.getSubtrees:"
984
                        + e);
985
      throw new ConnectException(
986
          "Problem getting subtrees in AuthLdap.getSubtrees:" + e);
987
    }
988

    
989
    return trees;
990
  }
991

    
992
  /**
993
   * Get all groups and users from authentication scheme.
994
   * The output is formatted in XML.
995
   * @param user the user which requests the information
996
   * @param password the user's password
997
   */
998
  public String getPrincipals(String user, String password) throws
999
      ConnectException {
1000
    StringBuffer out = new StringBuffer();
1001
   
1002
    out.append("<?xml version=\"1.0\" encoding=\"US-ASCII\"?>\n");
1003
    out.append("<principals>\n");
1004

    
1005
    /*
1006
     * get all subtrees first in the current dir context
1007
     * and then the Metacat users under them
1008
     */
1009
    Hashtable subtrees = getSubtrees(user, password, this.ldapUrl,
1010
                                     this.ldapBase);
1011

    
1012
    Enumeration keyEnum = subtrees.keys();
1013
    while (keyEnum.hasMoreElements()) {
1014
      this.ldapBase = (String) keyEnum.nextElement();
1015
      this.ldapUrl = (String) subtrees.get(ldapBase);
1016

    
1017
      /*
1018
       * code to get the organization name from ldapBase
1019
       */
1020
      String orgName = this.ldapBase;
1021
      if (orgName.startsWith("[")) {
1022
        // if orgName starts with [ then it is a referral URL...
1023
        // (see code in getSubtress)
1024
        // hence orgName can be retrieved  by getting the string between
1025
        // 'o=' and ']'
1026
        // also the string between [ and ] needs to be striped out from
1027
        // this.ldapBase
1028
        this.ldapBase = orgName.substring(orgName.indexOf("]") + 1);
1029
        if (orgName != null && orgName.indexOf("o=") > -1) {
1030
          orgName = orgName.substring(orgName.indexOf("o=") + 2);
1031
          orgName = orgName.substring(0, orgName.indexOf("]"));
1032
        }
1033
      }
1034
      else {
1035
        // else it is not referral
1036
        // hence orgName can be retrieved  by getting the string between
1037
        // 'o=' and ','
1038
        if (orgName != null && orgName.indexOf("o=") > -1) {
1039
          orgName = orgName.substring(orgName.indexOf("o=") + 2);
1040
          if (orgName.indexOf(",") > -1) {
1041
            orgName = orgName.substring(0, orgName.indexOf(","));
1042
          }
1043
        }
1044
      }
1045

    
1046
      out.append("  <authSystem URI=\"" +
1047
                 this.ldapUrl + this.ldapBase + "\" organization=\"" + orgName +
1048
                 "\">\n");
1049

    
1050
      // get all groups for directory context
1051
      String[][] groups = getGroups(user, password);
1052
      String[][] users = getUsers(user, password);
1053
      int userIndex = 0;
1054

    
1055
      // for the groups and users that belong to them
1056
      if (groups != null && groups.length > 0) {
1057
        for (int i = 0; i < groups.length; i++) {
1058
          out.append("    <group>\n");
1059
          out.append("      <groupname>" + groups[i][0] + "</groupname>\n");
1060
          out.append("      <description>" + groups[i][1] + "</description>\n");
1061
          String[] usersForGroup = getUsers(user, password, groups[i][0]);
1062
          for (int j = 0; j < usersForGroup.length; j++) {
1063
            
1064
            userIndex = searchUser(usersForGroup[j], users);
1065
            out.append("      <user>\n");
1066

    
1067
            if (userIndex < 0) {
1068
              out.append("        <username>" + usersForGroup[j] +
1069
                         "</username>\n");
1070
            }
1071
            else {
1072
              out.append("        <username>" + users[userIndex][0] +
1073
                         "</username>\n");
1074
              out.append("        <name>" + users[userIndex][1] + "</name>\n");
1075
              out.append("        <organization>" + users[userIndex][2] +
1076
                         "</organization>\n");
1077
              if (users[userIndex][3].compareTo("null") != 0) {
1078
                out.append("      <organizationUnitName>" + users[userIndex][3] +
1079
                           "</organizationUnitName>\n");
1080
              }
1081
              out.append("        <email>" + users[userIndex][4] + "</email>\n");
1082
            }
1083

    
1084
            out.append("      </user>\n");
1085
          }
1086
          out.append("    </group>\n");
1087
        }
1088
      }
1089

    
1090
      // for the users not belonging to any grou8p
1091
      for (int j = 0; j < users.length; j++) {
1092
          out.append("    <user>\n");
1093
          out.append("      <username>" + users[j][0] + "</username>\n");
1094
          out.append("      <name>" + users[j][1] + "</name>\n");
1095
          out.append("      <organization>" + users[j][2] +
1096
                     "</organization>\n");
1097
          if (users[j][3].compareTo("null") != 0) {
1098
            out.append("      <organizationUnitName>" + users[j][3] +
1099
                       "</organizationUnitName>\n");
1100
          }
1101
          out.append("      <email>" + users[j][4] + "</email>\n");
1102
          out.append("    </user>\n");
1103
      }
1104

    
1105
      out.append("  </authSystem>\n");
1106
    }
1107
    out.append("</principals>");
1108
    return out.toString();
1109
  }
1110

    
1111
  /**
1112
   * Method for getting index of user DN in User info array
1113
   */
1114
  int searchUser(String user, String userGroup[][]) {
1115
    for (int j = 0; j < userGroup.length; j++) {
1116
      if (user.compareTo(userGroup[j][0]) == 0) {
1117
        return j;
1118
      }
1119
    }
1120
    return -1;
1121
  }
1122

    
1123
  /**
1124
   * Test method for the class
1125
   */
1126
  public static void main(String[] args) {
1127

    
1128
    // Provide a user, such as: "Matt Jones", or "jones"
1129
    String user = args[0];
1130
    String password = args[1];
1131

    
1132
    logMetacat.warn("Creating session...");
1133
    AuthLdap authservice = new AuthLdap();
1134
    logMetacat.warn("Session exists...");
1135

    
1136
    boolean isValid = false;
1137
    try {
1138
      logMetacat.warn("Authenticating...");
1139
      isValid = authservice.authenticate(user, password);
1140
      if (isValid) {
1141
    	  logMetacat.warn("Authentication successful for: " + user);
1142
      }
1143
      else {
1144
        logMetacat.warn("Authentication failed for: " + user);
1145
      }
1146

    
1147
      // Get attributes for the user
1148
      if (isValid) {
1149
        logMetacat.info("\nGetting attributes for user....");
1150
        HashMap userInfo = authservice.getAttributes(user, password, user);
1151
        // Print all of the attributes
1152
        Iterator attList = (Iterator) ( ( (Set) userInfo.keySet()).iterator());
1153
        while (attList.hasNext()) {
1154
          String att = (String) attList.next();
1155
          Vector values = (Vector) userInfo.get(att);
1156
          Iterator attvalues = values.iterator();
1157
          while (attvalues.hasNext()) {
1158
            String value = (String) attvalues.next();
1159
            logMetacat.warn(att + ": " + value);
1160
          }
1161
        }
1162
      }
1163

    
1164
      // get the groups
1165
      if (isValid) {
1166
        logMetacat.warn("\nGetting all groups....");
1167
        String[][] groups = authservice.getGroups(user, password);
1168
        logMetacat.info("Groups found: " + groups.length);
1169
        for (int i = 0; i < groups.length; i++) {
1170
          logMetacat.info("Group " + i + ": " + groups[i][0]);
1171
        }
1172
      }
1173

    
1174
      // get the groups for the user
1175
      String savedGroup = null;
1176
      if (isValid) {
1177
        logMetacat.warn("\nGetting groups for user....");
1178
        String[][] groups = authservice.getGroups(user, password, user);
1179
        logMetacat.info("Groups found: " + groups.length);
1180
        for (int i = 0; i < groups.length; i++) {
1181
          logMetacat.info("Group " + i + ": " + groups[i][0]);
1182
          savedGroup = groups[i][0];
1183
        }
1184
      }
1185

    
1186
      // get the users for a group
1187
      if (isValid) {
1188
        logMetacat.warn("\nGetting users for group....");
1189
        logMetacat.info("Group: " + savedGroup);
1190
        String[] users = authservice.getUsers(user, password, savedGroup);
1191
        logMetacat.info("Users found: " + users.length);
1192
        for (int i = 0; i < users.length; i++) {
1193
          logMetacat.warn("User " + i + ": " + users[i]);
1194
        }
1195
      }
1196

    
1197
      // get all users
1198
      if (isValid) {
1199
        logMetacat.warn("\nGetting all users ....");
1200
        String[][] users = authservice.getUsers(user, password);
1201
        logMetacat.info("Users found: " + users.length);
1202

    
1203
      }
1204

    
1205
      // get the whole list groups and users in XML format
1206
      if (isValid) {
1207
        logMetacat.warn("\nTrying principals....");
1208
        authservice = new AuthLdap();
1209
        String out = authservice.getPrincipals(user, password);
1210
        java.io.File f = new java.io.File("principals.xml");
1211
        java.io.FileWriter fw = new java.io.FileWriter(f);
1212
        java.io.BufferedWriter buff = new java.io.BufferedWriter(fw);
1213
        buff.write(out);
1214
        buff.flush();
1215
        buff.close();
1216
        fw.close();
1217
        logMetacat.warn("\nFinished getting principals.");
1218
      }
1219

    
1220
    }
1221
    catch (ConnectException ce) {
1222
      logMetacat.error(ce.getMessage());
1223
    }
1224
    catch (java.io.IOException ioe) {
1225
      logMetacat.error("I/O Error writing to file principals.txt");
1226
    }
1227
  }
1228

    
1229
  /**
1230
   * This method will be called by start a thread.
1231
   * It can handle if a referral exception happend.
1232
   */
1233
  public void run() {
1234
    referralContext = null;
1235
    DirContext refDirContext = null;
1236
    boolean moreReferrals = true;
1237
    String referralInfo = null;
1238
    //set a while loop is because we don't know if a referral excption contains
1239
    //another referral exception
1240
    while (moreReferrals) {
1241
      try {
1242
        //revise environment variable
1243
        referralInfo = (String) refExc.getReferralInfo();
1244
        logMetacat.info("Processing referral (pr0): ");
1245
        logMetacat.info("PROVIDER_URL set to (pr1): " + referralInfo);
1246
        //env.put(Context.PROVIDER_URL,referralInfo);
1247
        //env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
1248
        //env.put(Context.SECURITY_PRINCIPAL, userName);
1249
        //env.put(Context.SECURITY_CREDENTIALS, userPassword);
1250
        //env.put(Context.REFERRAL, "throw");
1251
        //logMetacat.info("Processing referral (pr1.info): " + userName,35);
1252
        //logMetacat.info("Processing referral (pr2)",35);
1253
        //rContext = refExc.getReferralContext(env);
1254
        rContext = refExc.getReferralContext();
1255
        logMetacat.info("Processing referral (pr3)");
1256
        //casting the context to dircontext and it will create a
1257
        //autherntication or naming exception if DN and password is incorrect
1258
        referralContext = rContext;
1259
        refDirContext = (DirContext) rContext;
1260
        refDirContext.close();
1261
        //get context and jump out the while loop
1262
        moreReferrals = false;
1263
        logMetacat.info("Processing referral (pr4)");
1264
      } //try
1265
      //if referral have another referral excption
1266
      catch (ReferralException re) {
1267
        logMetacat.warn("GOT referral exception (re1): " + re.getMessage());
1268
        logMetacat.warn("RE details (re2): " + re.toString(true));
1269
        //keep running in while loop
1270
        moreReferrals = true;
1271
        //assign refExc to new referral exception re
1272
        refExc = re;
1273
      }
1274
      //catch a authentication exception
1275
      catch (AuthenticationException ae) {
1276
        logMetacat.error("Error running referral handler thread (ae1): " +
1277
                          ae.getMessage());
1278
        //check if has another referral
1279
        moreReferrals = refExc.skipReferral();
1280
        //don't get the context
1281
        referralContext = null;
1282
      }
1283
      //catch a naming exception
1284
      catch (NamingException ne) {
1285
        logMetacat.error("Error running referral handler thread (ne1): " +
1286
                          ne.getMessage());
1287
        //check if has another referral
1288
        moreReferrals = refExc.skipReferral();
1289
        //don't get context
1290
        referralContext = null;
1291
      }
1292
    } //while
1293
  } //run()
1294

    
1295
  private class GetGroup
1296
      implements Runnable {
1297
    public void run() {
1298
      referralContext = null;
1299
      logMetacat.info("getting groups context");
1300
      DirContext refDirContext = null;
1301
      boolean moreReferrals = true;
1302
      //set a while loop is because we don't know if a referral excption
1303
      //contains another referral exception
1304
      while (moreReferrals) {
1305
        try {
1306
          //revise environment variable
1307
          String refInfo = null;
1308
          refInfo = (String) refExc.getReferralInfo();
1309
          if (refInfo != null) {
1310
            logMetacat.info("Referral in thread to: " +
1311
                                     refInfo.toString());
1312
          }
1313
          else {
1314
            logMetacat.info("getting refInfo Manually");
1315
            refInfo = (String) refExc.getReferralContext().getEnvironment().
1316
                get(Context.PROVIDER_URL);
1317
          }
1318
          logMetacat.info("refInfo: " + refInfo);
1319

    
1320
          env.put(Context.INITIAL_CONTEXT_FACTORY,
1321
                  "com.sun.jndi.ldap.LdapCtxFactory");
1322
          env.put(Context.REFERRAL, "throw");
1323
          env.put(Context.PROVIDER_URL, refInfo);
1324

    
1325
          logMetacat.info("creating referralContext");
1326
          referralContext = new InitialDirContext(env);
1327
          logMetacat.info("referralContext created");
1328
          //get context and jump out the while loop
1329
          moreReferrals = false;
1330
        } //try
1331
        catch (ReferralException re) {
1332
          //keep running in while loop
1333
          moreReferrals = true;
1334
          //assign refExc to new referral exception re
1335
          refExc = re;
1336
        }
1337
        catch (AuthenticationException ae) {
1338
          logMetacat.error("Error running referral handler thread (ae2): " +
1339
                            ae.getMessage());
1340
          //check if has another referral
1341
          moreReferrals = refExc.skipReferral();
1342
          //don't get the context
1343
          referralContext = null;
1344
        }
1345
        catch (NamingException ne) {
1346
          logMetacat.error("Error running referral handler thread (ne2): " +
1347
                            ne.getMessage());
1348
          //check if has another referral
1349
          moreReferrals = refExc.skipReferral();
1350
          //don't get context
1351
          referralContext = null;
1352
        }
1353
      } //while
1354
    } //run()
1355
  }
1356
}
(11-11/65)