1 /*
   2  * Copyright (c) 1999, 2001, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package com.sun.jndi.ldap;
  27 
  28 import javax.naming.*;
  29 import javax.naming.directory.*;
  30 import javax.naming.spi.*;
  31 import javax.naming.ldap.*;
  32 
  33 import java.util.Hashtable;
  34 import java.util.StringTokenizer;
  35 import com.sun.jndi.toolkit.dir.SearchFilter;
  36 
  37 /**
  38  * A context for handling referrals.
  39  *
  40  * @author Vincent Ryan
  41  */
  42 final class LdapReferralContext implements DirContext, LdapContext {
  43 
  44     private DirContext refCtx = null;
  45     private Name urlName = null;   // override the supplied name
  46     private String urlAttrs = null;  // override attributes
  47     private String urlScope = null;  // override scope
  48     private String urlFilter = null; // override filter
  49 
  50     private LdapReferralException refEx = null;
  51     private boolean skipThisReferral = false;
  52     private int hopCount = 1;
  53     private NamingException previousEx = null;
  54 
  55     LdapReferralContext(LdapReferralException ex, Hashtable env,
  56         Control[] connCtls,
  57         Control[] reqCtls,
  58         String nextName,
  59         boolean skipThisReferral,
  60         int handleReferrals) throws NamingException {
  61 
  62         refEx = ex;
  63 
  64         if (this.skipThisReferral = skipThisReferral) {
  65             return; // don't create a DirContext for this referral
  66         }
  67 
  68         String referral;
  69 
  70         // Make copies of environment and connect controls for our own use.
  71         if (env != null) {
  72             env = (Hashtable) env.clone();
  73             // Remove old connect controls from environment, unless we have new
  74             // ones that will override them anyway.
  75             if (connCtls == null) {
  76                 env.remove(LdapCtx.BIND_CONTROLS);
  77             }
  78         } else if (connCtls != null) {
  79             env = new Hashtable(5);
  80         }
  81         if (connCtls != null) {
  82             Control[] copiedCtls = new Control[connCtls.length];
  83             System.arraycopy(connCtls, 0, copiedCtls, 0, connCtls.length);
  84             // Add copied controls to environment, replacing any old ones.
  85             env.put(LdapCtx.BIND_CONTROLS, copiedCtls);
  86         }
  87 
  88         while (true) {
  89             try {
  90                 referral = refEx.getNextReferral();
  91                 if (referral == null) {
  92                     throw (NamingException)(previousEx.fillInStackTrace());
  93                 }
  94 
  95             } catch (LdapReferralException e) {
  96 
  97                 if (handleReferrals == LdapClient.LDAP_REF_THROW) {
  98                     throw e;
  99                 } else {
 100                     refEx = e;
 101                     continue;
 102                 }
 103             }
 104 
 105             // Create a Reference containing the referral URL.
 106             Reference ref = new Reference("javax.naming.directory.DirContext",
 107                                           new StringRefAddr("URL", referral));
 108 
 109             Object obj;
 110             try {
 111                 obj = NamingManager.getObjectInstance(ref, null, null, env);
 112 
 113             } catch (NamingException e) {
 114 
 115                 if (handleReferrals == LdapClient.LDAP_REF_THROW) {
 116                     throw e;
 117                 }
 118 
 119                 // mask the exception and save it for later
 120                 previousEx = e;
 121 
 122                 // follow another referral
 123                 continue;
 124 
 125             } catch (Exception e) {
 126                 NamingException e2 =
 127                     new NamingException(
 128                         "problem generating object using object factory");
 129                 e2.setRootCause(e);
 130                 throw e2;
 131             }
 132             if (obj instanceof DirContext) {
 133                 refCtx = (DirContext)obj;
 134                 if (refCtx instanceof LdapContext && reqCtls != null) {
 135                     ((LdapContext)refCtx).setRequestControls(reqCtls);
 136                 }
 137                 initDefaults(referral, nextName);
 138 
 139                 break;
 140             } else {
 141                 NamingException ne = new NotContextException(
 142                     "Cannot create context for: " + referral);
 143                 ne.setRemainingName((new CompositeName()).add(nextName));
 144                 throw ne;
 145             }
 146         }
 147     }
 148 
 149     private void initDefaults(String referral, String nextName)
 150         throws NamingException {
 151         String urlString;
 152         try {
 153             // parse URL
 154             LdapURL url = new LdapURL(referral);
 155             urlString = url.getDN();
 156             urlAttrs = url.getAttributes();
 157             urlScope = url.getScope();
 158             urlFilter = url.getFilter();
 159 
 160         } catch (NamingException e) {
 161             // Not an LDAP URL; use original URL
 162             urlString = referral;
 163             urlAttrs = urlScope = urlFilter = null;
 164         }
 165 
 166         // reuse original name if URL DN is absent
 167         if (urlString == null) {
 168             urlString = nextName;
 169         } else {
 170             // concatenate with remaining name if URL DN is present
 171             urlString = "";
 172         }
 173 
 174         if (urlString == null) {
 175             urlName = null;
 176         } else {
 177             urlName = urlString.equals("") ? new CompositeName() :
 178                 new CompositeName().add(urlString);
 179         }
 180     }
 181 
 182 
 183     public void close() throws NamingException {
 184         if (refCtx != null) {
 185             refCtx.close();
 186             refCtx = null;
 187         }
 188         refEx = null;
 189     }
 190 
 191     void setHopCount(int hopCount) {
 192         this.hopCount = hopCount;
 193         if ((refCtx != null) && (refCtx instanceof LdapCtx)) {
 194             ((LdapCtx)refCtx).setHopCount(hopCount);
 195         }
 196     }
 197 
 198     public Object lookup(String name) throws NamingException {
 199         return lookup(toName(name));
 200     }
 201 
 202     public Object lookup(Name name) throws NamingException {
 203         if (skipThisReferral) {
 204             throw (NamingException)
 205                 ((refEx.appendUnprocessedReferrals(null)).fillInStackTrace());
 206         }
 207 
 208         return refCtx.lookup(overrideName(name));
 209     }
 210 
 211     public void bind(String name, Object obj) throws NamingException {
 212         bind(toName(name), obj);
 213     }
 214 
 215     public void bind(Name name, Object obj) throws NamingException {
 216         if (skipThisReferral) {
 217             throw (NamingException)
 218                 ((refEx.appendUnprocessedReferrals(null)).fillInStackTrace());
 219         }
 220 
 221         refCtx.bind(overrideName(name), obj);
 222     }
 223 
 224     public void rebind(String name, Object obj) throws NamingException {
 225         rebind(toName(name), obj);
 226     }
 227 
 228     public void rebind(Name name, Object obj) throws NamingException {
 229         if (skipThisReferral) {
 230             throw (NamingException)
 231                 ((refEx.appendUnprocessedReferrals(null)).fillInStackTrace());
 232         }
 233 
 234         refCtx.rebind(overrideName(name), obj);
 235     }
 236 
 237     public void unbind(String name) throws NamingException {
 238         unbind(toName(name));
 239     }
 240 
 241     public void unbind(Name name) throws NamingException {
 242         if (skipThisReferral) {
 243             throw (NamingException)
 244                 ((refEx.appendUnprocessedReferrals(null)).fillInStackTrace());
 245         }
 246 
 247         refCtx.unbind(overrideName(name));
 248     }
 249 
 250     public void rename(String oldName, String newName) throws NamingException {
 251         rename(toName(oldName), toName(newName));
 252     }
 253 
 254     public void rename(Name oldName, Name newName) throws NamingException {
 255         if (skipThisReferral) {
 256             throw (NamingException)
 257                 ((refEx.appendUnprocessedReferrals(null)).fillInStackTrace());
 258         }
 259 
 260         refCtx.rename(overrideName(oldName), toName(refEx.getNewRdn()));
 261     }
 262 
 263     public NamingEnumeration list(String name) throws NamingException {
 264         return list(toName(name));
 265     }
 266 
 267     public NamingEnumeration list(Name name) throws NamingException {
 268         if (skipThisReferral) {
 269             throw (NamingException)
 270                 ((refEx.appendUnprocessedReferrals(null)).fillInStackTrace());
 271         }
 272         try {
 273             NamingEnumeration ne = null;
 274 
 275             if (urlScope != null && urlScope.equals("base")) {
 276                 SearchControls cons = new SearchControls();
 277                 cons.setReturningObjFlag(true);
 278                 cons.setSearchScope(SearchControls.OBJECT_SCOPE);
 279 
 280                 ne = refCtx.search(overrideName(name), "(objectclass=*)", cons);
 281 
 282             } else {
 283                 ne = refCtx.list(overrideName(name));
 284             }
 285 
 286             refEx.setNameResolved(true);
 287 
 288             // append (referrals from) the exception that generated this
 289             // context to the new search results, so that referral processing
 290             // can continue
 291             ((ReferralEnumeration)ne).appendUnprocessedReferrals(refEx);
 292 
 293             return (ne);
 294 
 295         } catch (LdapReferralException e) {
 296 
 297             // append (referrals from) the exception that generated this
 298             // context to the new exception, so that referral processing
 299             // can continue
 300 
 301             e.appendUnprocessedReferrals(refEx);
 302             throw (NamingException)(e.fillInStackTrace());
 303 
 304         } catch (NamingException e) {
 305 
 306             // record the exception if there are no remaining referrals
 307             if ((refEx != null) && (! refEx.hasMoreReferrals())) {
 308                 refEx.setNamingException(e);
 309             }
 310             if ((refEx != null) &&
 311                 (refEx.hasMoreReferrals() ||
 312                  refEx.hasMoreReferralExceptions())) {
 313                 throw (NamingException)
 314                     ((refEx.appendUnprocessedReferrals(null)).fillInStackTrace());
 315             } else {
 316                 throw e;
 317             }
 318         }
 319     }
 320 
 321     public NamingEnumeration listBindings(String name) throws NamingException {
 322         return listBindings(toName(name));
 323     }
 324 
 325     public NamingEnumeration listBindings(Name name) throws NamingException {
 326         if (skipThisReferral) {
 327             throw (NamingException)
 328                 ((refEx.appendUnprocessedReferrals(null)).fillInStackTrace());
 329         }
 330 
 331         try {
 332             NamingEnumeration be = null;
 333 
 334             if (urlScope != null && urlScope.equals("base")) {
 335                 SearchControls cons = new SearchControls();
 336                 cons.setReturningObjFlag(true);
 337                 cons.setSearchScope(SearchControls.OBJECT_SCOPE);
 338 
 339                 be = refCtx.search(overrideName(name), "(objectclass=*)", cons);
 340 
 341             } else {
 342                 be = refCtx.listBindings(overrideName(name));
 343             }
 344 
 345             refEx.setNameResolved(true);
 346 
 347             // append (referrals from) the exception that generated this
 348             // context to the new search results, so that referral processing
 349             // can continue
 350             ((ReferralEnumeration)be).appendUnprocessedReferrals(refEx);
 351 
 352             return (be);
 353 
 354         } catch (LdapReferralException e) {
 355 
 356             // append (referrals from) the exception that generated this
 357             // context to the new exception, so that referral processing
 358             // can continue
 359 
 360             e.appendUnprocessedReferrals(refEx);
 361             throw (NamingException)(e.fillInStackTrace());
 362 
 363         } catch (NamingException e) {
 364 
 365             // record the exception if there are no remaining referrals
 366             if ((refEx != null) && (! refEx.hasMoreReferrals())) {
 367                 refEx.setNamingException(e);
 368             }
 369             if ((refEx != null) &&
 370                 (refEx.hasMoreReferrals() ||
 371                  refEx.hasMoreReferralExceptions())) {
 372                 throw (NamingException)
 373                     ((refEx.appendUnprocessedReferrals(null)).fillInStackTrace());
 374             } else {
 375                 throw e;
 376             }
 377         }
 378     }
 379 
 380     public void destroySubcontext(String name) throws NamingException {
 381         destroySubcontext(toName(name));
 382     }
 383 
 384     public void destroySubcontext(Name name) throws NamingException {
 385         if (skipThisReferral) {
 386             throw (NamingException)
 387                 ((refEx.appendUnprocessedReferrals(null)).fillInStackTrace());
 388         }
 389 
 390         refCtx.destroySubcontext(overrideName(name));
 391     }
 392 
 393     public Context createSubcontext(String name) throws NamingException {
 394         return createSubcontext(toName(name));
 395     }
 396 
 397     public Context createSubcontext(Name name) throws NamingException {
 398         if (skipThisReferral) {
 399             throw (NamingException)
 400                 ((refEx.appendUnprocessedReferrals(null)).fillInStackTrace());
 401         }
 402 
 403         return refCtx.createSubcontext(overrideName(name));
 404     }
 405 
 406     public Object lookupLink(String name) throws NamingException {
 407         return lookupLink(toName(name));
 408     }
 409 
 410     public Object lookupLink(Name name) throws NamingException {
 411         if (skipThisReferral) {
 412             throw (NamingException)
 413                 ((refEx.appendUnprocessedReferrals(null)).fillInStackTrace());
 414         }
 415 
 416         return refCtx.lookupLink(overrideName(name));
 417     }
 418 
 419     public NameParser getNameParser(String name) throws NamingException {
 420         return getNameParser(toName(name));
 421     }
 422 
 423     public NameParser getNameParser(Name name) throws NamingException {
 424         if (skipThisReferral) {
 425             throw (NamingException)
 426                 ((refEx.appendUnprocessedReferrals(null)).fillInStackTrace());
 427         }
 428 
 429         return refCtx.getNameParser(overrideName(name));
 430     }
 431 
 432     public String composeName(String name, String prefix)
 433             throws NamingException {
 434                 return composeName(toName(name), toName(prefix)).toString();
 435     }
 436 
 437     public Name composeName(Name name, Name prefix) throws NamingException {
 438         if (skipThisReferral) {
 439             throw (NamingException)
 440                 ((refEx.appendUnprocessedReferrals(null)).fillInStackTrace());
 441         }
 442         return refCtx.composeName(name, prefix);
 443     }
 444 
 445     public Object addToEnvironment(String propName, Object propVal)
 446             throws NamingException {
 447         if (skipThisReferral) {
 448             throw (NamingException)
 449                 ((refEx.appendUnprocessedReferrals(null)).fillInStackTrace());
 450         }
 451 
 452         return refCtx.addToEnvironment(propName, propVal);
 453     }
 454 
 455     public Object removeFromEnvironment(String propName)
 456             throws NamingException {
 457         if (skipThisReferral) {
 458             throw (NamingException)
 459                 ((refEx.appendUnprocessedReferrals(null)).fillInStackTrace());
 460         }
 461 
 462         return refCtx.removeFromEnvironment(propName);
 463     }
 464 
 465     public Hashtable getEnvironment() throws NamingException {
 466         if (skipThisReferral) {
 467             throw (NamingException)
 468                 ((refEx.appendUnprocessedReferrals(null)).fillInStackTrace());
 469         }
 470 
 471         return refCtx.getEnvironment();
 472     }
 473 
 474     public Attributes getAttributes(String name) throws NamingException {
 475         return getAttributes(toName(name));
 476     }
 477 
 478     public Attributes getAttributes(Name name) throws NamingException {
 479         if (skipThisReferral) {
 480             throw (NamingException)
 481                 ((refEx.appendUnprocessedReferrals(null)).fillInStackTrace());
 482         }
 483 
 484         return refCtx.getAttributes(overrideName(name));
 485     }
 486 
 487     public Attributes getAttributes(String name, String[] attrIds)
 488             throws NamingException {
 489         return getAttributes(toName(name), attrIds);
 490     }
 491 
 492     public Attributes getAttributes(Name name, String[] attrIds)
 493             throws NamingException {
 494         if (skipThisReferral) {
 495             throw (NamingException)
 496                 ((refEx.appendUnprocessedReferrals(null)).fillInStackTrace());
 497         }
 498 
 499         return refCtx.getAttributes(overrideName(name), attrIds);
 500     }
 501 
 502     public void modifyAttributes(String name, int mod_op, Attributes attrs)
 503             throws NamingException {
 504         modifyAttributes(toName(name), mod_op, attrs);
 505     }
 506 
 507     public void modifyAttributes(Name name, int mod_op, Attributes attrs)
 508             throws NamingException {
 509         if (skipThisReferral) {
 510             throw (NamingException)
 511                 ((refEx.appendUnprocessedReferrals(null)).fillInStackTrace());
 512         }
 513 
 514         refCtx.modifyAttributes(overrideName(name), mod_op, attrs);
 515     }
 516 
 517     public void modifyAttributes(String name, ModificationItem[] mods)
 518             throws NamingException {
 519         modifyAttributes(toName(name), mods);
 520     }
 521 
 522     public void modifyAttributes(Name name, ModificationItem[] mods)
 523             throws NamingException {
 524         if (skipThisReferral) {
 525             throw (NamingException)
 526                 ((refEx.appendUnprocessedReferrals(null)).fillInStackTrace());
 527         }
 528 
 529         refCtx.modifyAttributes(overrideName(name), mods);
 530     }
 531 
 532     public void bind(String name, Object obj, Attributes attrs)
 533             throws NamingException {
 534         bind(toName(name), obj, attrs);
 535     }
 536 
 537     public void bind(Name name, Object obj, Attributes attrs)
 538             throws NamingException {
 539         if (skipThisReferral) {
 540             throw (NamingException)
 541                 ((refEx.appendUnprocessedReferrals(null)).fillInStackTrace());
 542         }
 543 
 544         refCtx.bind(overrideName(name), obj, attrs);
 545     }
 546 
 547     public void rebind(String name, Object obj, Attributes attrs)
 548             throws NamingException {
 549         rebind(toName(name), obj, attrs);
 550     }
 551 
 552     public void rebind(Name name, Object obj, Attributes attrs)
 553             throws NamingException {
 554         if (skipThisReferral) {
 555             throw (NamingException)
 556                 ((refEx.appendUnprocessedReferrals(null)).fillInStackTrace());
 557         }
 558 
 559         refCtx.rebind(overrideName(name), obj, attrs);
 560     }
 561 
 562     public DirContext createSubcontext(String name, Attributes attrs)
 563             throws NamingException {
 564         return createSubcontext(toName(name), attrs);
 565     }
 566 
 567     public DirContext createSubcontext(Name name, Attributes attrs)
 568             throws NamingException {
 569         if (skipThisReferral) {
 570             throw (NamingException)
 571                 ((refEx.appendUnprocessedReferrals(null)).fillInStackTrace());
 572         }
 573 
 574         return refCtx.createSubcontext(overrideName(name), attrs);
 575     }
 576 
 577     public DirContext getSchema(String name) throws NamingException {
 578         return getSchema(toName(name));
 579     }
 580 
 581     public DirContext getSchema(Name name) throws NamingException {
 582         if (skipThisReferral) {
 583             throw (NamingException)
 584                 ((refEx.appendUnprocessedReferrals(null)).fillInStackTrace());
 585         }
 586 
 587         return refCtx.getSchema(overrideName(name));
 588     }
 589 
 590     public DirContext getSchemaClassDefinition(String name)
 591             throws NamingException {
 592         return getSchemaClassDefinition(toName(name));
 593     }
 594 
 595     public DirContext getSchemaClassDefinition(Name name)
 596             throws NamingException {
 597         if (skipThisReferral) {
 598             throw (NamingException)
 599                 ((refEx.appendUnprocessedReferrals(null)).fillInStackTrace());
 600         }
 601 
 602       return refCtx.getSchemaClassDefinition(overrideName(name));
 603     }
 604 
 605     public NamingEnumeration search(String name,
 606                                     Attributes matchingAttributes)
 607             throws NamingException {
 608         return search(toName(name), SearchFilter.format(matchingAttributes),
 609             new SearchControls());
 610     }
 611 
 612     public NamingEnumeration search(Name name,
 613                                     Attributes matchingAttributes)
 614             throws NamingException {
 615         return search(name, SearchFilter.format(matchingAttributes),
 616             new SearchControls());
 617     }
 618 
 619     public NamingEnumeration search(String name,
 620                                     Attributes matchingAttributes,
 621                                     String[] attributesToReturn)
 622             throws NamingException {
 623         SearchControls cons = new SearchControls();
 624         cons.setReturningAttributes(attributesToReturn);
 625 
 626         return search(toName(name), SearchFilter.format(matchingAttributes),
 627             cons);
 628     }
 629 
 630     public NamingEnumeration search(Name name,
 631                                     Attributes matchingAttributes,
 632                                     String[] attributesToReturn)
 633             throws NamingException {
 634         SearchControls cons = new SearchControls();
 635         cons.setReturningAttributes(attributesToReturn);
 636 
 637         return search(name, SearchFilter.format(matchingAttributes), cons);
 638     }
 639 
 640     public NamingEnumeration search(String name,
 641                                     String filter,
 642                                     SearchControls cons)
 643             throws NamingException {
 644         return search(toName(name), filter, cons);
 645     }
 646 
 647     public NamingEnumeration search(Name name,
 648                                     String filter,
 649         SearchControls cons) throws NamingException {
 650 
 651         if (skipThisReferral) {
 652             throw (NamingException)
 653                 ((refEx.appendUnprocessedReferrals(null)).fillInStackTrace());
 654         }
 655 
 656         try {
 657             NamingEnumeration se = refCtx.search(overrideName(name),
 658                 overrideFilter(filter), overrideAttributesAndScope(cons));
 659 
 660             refEx.setNameResolved(true);
 661 
 662             // append (referrals from) the exception that generated this
 663             // context to the new search results, so that referral processing
 664             // can continue
 665             ((ReferralEnumeration)se).appendUnprocessedReferrals(refEx);
 666 
 667             return (se);
 668 
 669         } catch (LdapReferralException e) {
 670 
 671             // %%% VR - setNameResolved(true);
 672 
 673             // append (referrals from) the exception that generated this
 674             // context to the new exception, so that referral processing
 675             // can continue
 676 
 677             e.appendUnprocessedReferrals(refEx);
 678             throw (NamingException)(e.fillInStackTrace());
 679 
 680         } catch (NamingException e) {
 681 
 682             // record the exception if there are no remaining referrals
 683             if ((refEx != null) && (! refEx.hasMoreReferrals())) {
 684                 refEx.setNamingException(e);
 685             }
 686             if ((refEx != null) &&
 687                 (refEx.hasMoreReferrals() ||
 688                  refEx.hasMoreReferralExceptions())) {
 689                 throw (NamingException)
 690                     ((refEx.appendUnprocessedReferrals(null)).fillInStackTrace());
 691             } else {
 692                 throw e;
 693             }
 694         }
 695     }
 696 
 697     public NamingEnumeration search(String name,
 698                                     String filterExpr,
 699                                     Object[] filterArgs,
 700                                     SearchControls cons)
 701             throws NamingException {
 702         return search(toName(name), filterExpr, filterArgs, cons);
 703     }
 704 
 705     public NamingEnumeration search(Name name,
 706         String filterExpr,
 707         Object[] filterArgs,
 708         SearchControls cons) throws NamingException {
 709 
 710         if (skipThisReferral) {
 711             throw (NamingException)
 712                 ((refEx.appendUnprocessedReferrals(null)).fillInStackTrace());
 713         }
 714 
 715         try {
 716             NamingEnumeration se;
 717 
 718             if (urlFilter != null) {
 719                 se = refCtx.search(overrideName(name), urlFilter,
 720                 overrideAttributesAndScope(cons));
 721             } else {
 722                 se = refCtx.search(overrideName(name), filterExpr,
 723                 filterArgs, overrideAttributesAndScope(cons));
 724             }
 725 
 726             refEx.setNameResolved(true);
 727 
 728             // append (referrals from) the exception that generated this
 729             // context to the new search results, so that referral processing
 730             // can continue
 731             ((ReferralEnumeration)se).appendUnprocessedReferrals(refEx);
 732 
 733             return (se);
 734 
 735         } catch (LdapReferralException e) {
 736 
 737             // append (referrals from) the exception that generated this
 738             // context to the new exception, so that referral processing
 739             // can continue
 740 
 741             e.appendUnprocessedReferrals(refEx);
 742             throw (NamingException)(e.fillInStackTrace());
 743 
 744         } catch (NamingException e) {
 745 
 746             // record the exception if there are no remaining referrals
 747             if ((refEx != null) && (! refEx.hasMoreReferrals())) {
 748                 refEx.setNamingException(e);
 749             }
 750             if ((refEx != null) &&
 751                 (refEx.hasMoreReferrals() ||
 752                  refEx.hasMoreReferralExceptions())) {
 753                 throw (NamingException)
 754                     ((refEx.appendUnprocessedReferrals(null)).fillInStackTrace());
 755             } else {
 756                 throw e;
 757             }
 758         }
 759     }
 760 
 761     public String getNameInNamespace() throws NamingException {
 762         if (skipThisReferral) {
 763             throw (NamingException)
 764                 ((refEx.appendUnprocessedReferrals(null)).fillInStackTrace());
 765         }
 766         return urlName != null && !urlName.isEmpty() ? urlName.get(0) : "";
 767     }
 768 
 769     // ---------------------- LdapContext ---------------------
 770 
 771     public ExtendedResponse extendedOperation(ExtendedRequest request)
 772         throws NamingException {
 773 
 774         if (skipThisReferral) {
 775             throw (NamingException)
 776                 ((refEx.appendUnprocessedReferrals(null)).fillInStackTrace());
 777         }
 778 
 779         if (!(refCtx instanceof LdapContext)) {
 780             throw new NotContextException(
 781                 "Referral context not an instance of LdapContext");
 782         }
 783 
 784         return ((LdapContext)refCtx).extendedOperation(request);
 785     }
 786 
 787     public LdapContext newInstance(Control[] requestControls)
 788         throws NamingException {
 789 
 790         if (skipThisReferral) {
 791             throw (NamingException)
 792                 ((refEx.appendUnprocessedReferrals(null)).fillInStackTrace());
 793         }
 794 
 795         if (!(refCtx instanceof LdapContext)) {
 796             throw new NotContextException(
 797                 "Referral context not an instance of LdapContext");
 798         }
 799 
 800         return ((LdapContext)refCtx).newInstance(requestControls);
 801     }
 802 
 803     public void reconnect(Control[] connCtls) throws NamingException {
 804         if (skipThisReferral) {
 805             throw (NamingException)
 806                 ((refEx.appendUnprocessedReferrals(null)).fillInStackTrace());
 807         }
 808 
 809         if (!(refCtx instanceof LdapContext)) {
 810             throw new NotContextException(
 811                 "Referral context not an instance of LdapContext");
 812         }
 813 
 814         ((LdapContext)refCtx).reconnect(connCtls);
 815     }
 816 
 817     public Control[] getConnectControls() throws NamingException {
 818         if (skipThisReferral) {
 819             throw (NamingException)
 820                 ((refEx.appendUnprocessedReferrals(null)).fillInStackTrace());
 821         }
 822 
 823         if (!(refCtx instanceof LdapContext)) {
 824             throw new NotContextException(
 825                 "Referral context not an instance of LdapContext");
 826         }
 827 
 828         return ((LdapContext)refCtx).getConnectControls();
 829     }
 830 
 831     public void setRequestControls(Control[] requestControls)
 832         throws NamingException {
 833 
 834         if (skipThisReferral) {
 835             throw (NamingException)
 836                 ((refEx.appendUnprocessedReferrals(null)).fillInStackTrace());
 837         }
 838 
 839         if (!(refCtx instanceof LdapContext)) {
 840             throw new NotContextException(
 841                 "Referral context not an instance of LdapContext");
 842         }
 843 
 844         ((LdapContext)refCtx).setRequestControls(requestControls);
 845     }
 846 
 847     public Control[] getRequestControls() throws NamingException {
 848         if (skipThisReferral) {
 849             throw (NamingException)
 850                 ((refEx.appendUnprocessedReferrals(null)).fillInStackTrace());
 851         }
 852 
 853         if (!(refCtx instanceof LdapContext)) {
 854             throw new NotContextException(
 855                 "Referral context not an instance of LdapContext");
 856         }
 857         return ((LdapContext)refCtx).getRequestControls();
 858     }
 859 
 860     public Control[] getResponseControls() throws NamingException {
 861         if (skipThisReferral) {
 862             throw (NamingException)
 863                 ((refEx.appendUnprocessedReferrals(null)).fillInStackTrace());
 864         }
 865 
 866         if (!(refCtx instanceof LdapContext)) {
 867             throw new NotContextException(
 868                 "Referral context not an instance of LdapContext");
 869         }
 870         return ((LdapContext)refCtx).getResponseControls();
 871     }
 872 
 873     // ---------------------- Private methods  ---------------------
 874     private Name toName(String name) throws InvalidNameException {
 875         return name.equals("") ? new CompositeName() :
 876             new CompositeName().add(name);
 877     }
 878 
 879     /*
 880      * Use the DN component from the LDAP URL (if present) to override the
 881      * supplied DN.
 882      */
 883     private Name overrideName(Name name) throws InvalidNameException {
 884         return (urlName == null ? name : urlName);
 885     }
 886 
 887     /*
 888      * Use the attributes and scope components from the LDAP URL (if present)
 889      * to override the corrpesonding components supplied in SearchControls.
 890      */
 891     private SearchControls overrideAttributesAndScope(SearchControls cons) {
 892         SearchControls urlCons;
 893 
 894         if ((urlScope != null) || (urlAttrs != null)) {
 895             urlCons = new SearchControls(cons.getSearchScope(),
 896                                         cons.getCountLimit(),
 897                                         cons.getTimeLimit(),
 898                                         cons.getReturningAttributes(),
 899                                         cons.getReturningObjFlag(),
 900                                         cons.getDerefLinkFlag());
 901 
 902             if (urlScope != null) {
 903                 if (urlScope.equals("base")) {
 904                     urlCons.setSearchScope(SearchControls.OBJECT_SCOPE);
 905                 } else if (urlScope.equals("one")) {
 906                     urlCons.setSearchScope(SearchControls.ONELEVEL_SCOPE);
 907                 } else if (urlScope.equals("sub")) {
 908                     urlCons.setSearchScope(SearchControls.SUBTREE_SCOPE);
 909                 }
 910             }
 911 
 912             if (urlAttrs != null) {
 913                 StringTokenizer tokens = new StringTokenizer(urlAttrs, ",");
 914                 int count = tokens.countTokens();
 915                 String[] attrs = new String[count];
 916                 for (int i = 0; i < count; i ++) {
 917                     attrs[i] = tokens.nextToken();
 918                 }
 919                 urlCons.setReturningAttributes(attrs);
 920             }
 921 
 922             return urlCons;
 923 
 924         } else {
 925             return cons;
 926         }
 927     }
 928 
 929     /*
 930      * Use the filter component from the LDAP URL (if present) to override the
 931      * supplied filter.
 932      */
 933     private String overrideFilter(String filter) {
 934         return (urlFilter == null ? filter : urlFilter);
 935     }
 936 
 937 }