| /* |
| * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved. |
| * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
| * |
| * This code is free software; you can redistribute it and/or modify it |
| * under the terms of the GNU General Public License version 2 only, as |
| * published by the Free Software Foundation. Oracle designates this |
| * particular file as subject to the "Classpath" exception as provided |
| * by Oracle in the LICENSE file that accompanied this code. |
| * |
| * This code is distributed in the hope that it will be useful, but WITHOUT |
| * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
| * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
| * version 2 for more details (a copy is included in the LICENSE file that |
| * accompanied this code). |
| * |
| * You should have received a copy of the GNU General Public License version |
| * 2 along with this work; if not, write to the Free Software Foundation, |
| * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
| * |
| * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
| * or visit www.oracle.com if you need additional information or have any |
| * questions. |
| */ |
| |
| package com.sun.jndi.ldap; |
| |
| import javax.naming.*; |
| import javax.naming.ldap.Control; |
| |
| import java.util.Hashtable; |
| import java.util.Vector; |
| |
| /** |
| * This exception is raised when a referral to an alternative context |
| * is encountered. |
| * <p> |
| * An <tt>LdapReferralException</tt> object contains one or more referrals. |
| * Each referral is an alternative location for the same target entry. |
| * For example, a referral may be an LDAP URL. |
| * The referrals are attempted in sequence until one is successful or |
| * all have failed. In the case of the latter then the exception generated |
| * by the final referral is recorded and presented later. |
| * <p> |
| * A referral may be skipped or may be retried. For example, in the case |
| * of an authentication error, a referral may be retried with different |
| * environment properties. |
| * <p> |
| * An <tt>LdapReferralException</tt> object may also contain a reference |
| * to a chain of unprocessed <tt>LdapReferralException</tt> objects. |
| * Once the current set of referrals have been exhausted and unprocessed |
| * <tt>LdapReferralException</tt> objects remain, then the |
| * <tt>LdapReferralException</tt> object referenced by the current |
| * object is thrown and the cycle continues. |
| * <p> |
| * If new <tt>LdapReferralException</tt> objects are generated while |
| * following an existing referral then these new objects are appended |
| * to the end of the chain of unprocessed <tt>LdapReferralException</tt> |
| * objects. |
| * <p> |
| * If an exception was recorded while processing a chain of |
| * <tt>LdapReferralException</tt> objects then is is throw once |
| * processing has completed. |
| * |
| * @author Vincent Ryan |
| */ |
| final public class LdapReferralException extends |
| javax.naming.ldap.LdapReferralException { |
| private static final long serialVersionUID = 627059076356906399L; |
| |
| // ----------- fields initialized in constructor --------------- |
| private int handleReferrals; |
| private Hashtable<?,?> envprops; |
| private String nextName; |
| private Control[] reqCtls; |
| |
| // ----------- fields that have defaults ----------------------- |
| private Vector<?> referrals = null; // alternatives,set by setReferralInfo() |
| private int referralIndex = 0; // index into referrals |
| private int referralCount = 0; // count of referrals |
| private boolean foundEntry = false; // will stop when entry is found |
| private boolean skipThisReferral = false; |
| private int hopCount = 1; |
| private NamingException errorEx = null; |
| private String newRdn = null; |
| private boolean debug = false; |
| LdapReferralException nextReferralEx = null; // referral ex. chain |
| |
| /** |
| * Constructs a new instance of LdapReferralException. |
| * @param resolvedName The part of the name that has been successfully |
| * resolved. |
| * @param resolvedObj The object to which resolution was successful. |
| * @param remainingName The remaining unresolved portion of the name. |
| * @param explanation Additional detail about this exception. |
| */ |
| LdapReferralException(Name resolvedName, |
| Object resolvedObj, |
| Name remainingName, |
| String explanation, |
| Hashtable<?,?> envprops, |
| String nextName, |
| int handleReferrals, |
| Control[] reqCtls) { |
| |
| super(explanation); |
| |
| if (debug) |
| System.out.println("LdapReferralException constructor"); |
| |
| setResolvedName(resolvedName); |
| setResolvedObj(resolvedObj); |
| setRemainingName(remainingName); |
| this.envprops = envprops; |
| this.nextName = nextName; |
| this.handleReferrals = handleReferrals; |
| |
| // If following referral, request controls are passed to referral ctx |
| this.reqCtls = |
| (handleReferrals == LdapClient.LDAP_REF_FOLLOW ? reqCtls : null); |
| } |
| |
| /** |
| * Gets a context at which to continue processing. |
| * The current environment properties are re-used. |
| */ |
| public Context getReferralContext() throws NamingException { |
| return getReferralContext(envprops, null); |
| } |
| |
| /** |
| * Gets a context at which to continue processing. |
| * The supplied environment properties are used. |
| */ |
| public Context getReferralContext(Hashtable<?,?> newProps) throws |
| NamingException { |
| return getReferralContext(newProps, null); |
| } |
| |
| /** |
| * Gets a context at which to continue processing. |
| * The supplied environment properties and connection controls are used. |
| */ |
| public Context getReferralContext(Hashtable<?,?> newProps, Control[] connCtls) |
| throws NamingException { |
| |
| if (debug) |
| System.out.println("LdapReferralException.getReferralContext"); |
| |
| LdapReferralContext refCtx = new LdapReferralContext( |
| this, newProps, connCtls, reqCtls, |
| nextName, skipThisReferral, handleReferrals); |
| |
| refCtx.setHopCount(hopCount + 1); |
| |
| if (skipThisReferral) { |
| skipThisReferral = false; // reset |
| } |
| return (Context)refCtx; |
| } |
| |
| /** |
| * Gets referral information. |
| */ |
| public Object getReferralInfo() { |
| if (debug) { |
| System.out.println("LdapReferralException.getReferralInfo"); |
| System.out.println(" referralIndex=" + referralIndex); |
| } |
| |
| if (hasMoreReferrals()) { |
| return referrals.elementAt(referralIndex); |
| } else { |
| return null; |
| } |
| } |
| |
| /** |
| * Marks the current referral as one to be retried. |
| */ |
| public void retryReferral() { |
| if (debug) |
| System.out.println("LdapReferralException.retryReferral"); |
| |
| if (referralIndex > 0) |
| referralIndex--; // decrement index |
| } |
| |
| /** |
| * Marks the current referral as one to be ignored. |
| * Returns false when there are no referrals remaining to be processed. |
| */ |
| public boolean skipReferral() { |
| if (debug) |
| System.out.println("LdapReferralException.skipReferral"); |
| |
| skipThisReferral = true; |
| |
| // advance to next referral |
| try { |
| getNextReferral(); |
| } catch (ReferralException e) { |
| // mask the referral exception |
| } |
| |
| return (hasMoreReferrals() || hasMoreReferralExceptions()); |
| } |
| |
| |
| /** |
| * Sets referral information. |
| */ |
| void setReferralInfo(Vector<?> referrals, boolean continuationRef) { |
| // %%% continuationRef is currently ignored |
| |
| if (debug) |
| System.out.println("LdapReferralException.setReferralInfo"); |
| |
| this.referrals = referrals; |
| referralCount = (referrals == null) ? 0 : referrals.size(); |
| |
| if (debug) { |
| if (referrals != null) { |
| for (int i = 0; i < referralCount; i++) { |
| System.out.println(" [" + i + "] " + referrals.elementAt(i)); |
| } |
| } else { |
| System.out.println("setReferralInfo : referrals == null"); |
| } |
| } |
| } |
| |
| /** |
| * Gets the next referral. When the current set of referrals have |
| * been exhausted then the next referral exception is thrown, if available. |
| */ |
| String getNextReferral() throws ReferralException { |
| |
| if (debug) |
| System.out.println("LdapReferralException.getNextReferral"); |
| |
| if (hasMoreReferrals()) { |
| return (String)referrals.elementAt(referralIndex++); |
| } else if (hasMoreReferralExceptions()) { |
| throw nextReferralEx; |
| } else { |
| return null; |
| } |
| } |
| |
| /** |
| * Appends the supplied (chain of) referral exception onto the end of |
| * the current (chain of) referral exception. Spent referral exceptions |
| * are trimmed off. |
| */ |
| LdapReferralException |
| appendUnprocessedReferrals(LdapReferralException back) { |
| |
| if (debug) { |
| System.out.println( |
| "LdapReferralException.appendUnprocessedReferrals"); |
| dump(); |
| if (back != null) { |
| back.dump(); |
| } |
| } |
| |
| LdapReferralException front = this; |
| |
| if (! front.hasMoreReferrals()) { |
| front = nextReferralEx; // trim |
| |
| if ((errorEx != null) && (front != null)) { |
| front.setNamingException(errorEx); //advance the saved exception |
| } |
| } |
| |
| // don't append onto itself |
| if (this == back) { |
| return front; |
| } |
| |
| if ((back != null) && (! back.hasMoreReferrals())) { |
| back = back.nextReferralEx; // trim |
| } |
| |
| if (back == null) { |
| return front; |
| } |
| |
| // Locate the end of the current chain |
| LdapReferralException ptr = front; |
| while (ptr.nextReferralEx != null) { |
| ptr = ptr.nextReferralEx; |
| } |
| ptr.nextReferralEx = back; // append |
| |
| return front; |
| } |
| |
| /** |
| * Tests if there are any referrals remaining to be processed. |
| * If name resolution has already completed then any remaining |
| * referrals (in the current referral exception) will be ignored. |
| */ |
| boolean hasMoreReferrals() { |
| if (debug) |
| System.out.println("LdapReferralException.hasMoreReferrals"); |
| |
| return (! foundEntry) && (referralIndex < referralCount); |
| } |
| |
| /** |
| * Tests if there are any referral exceptions remaining to be processed. |
| */ |
| boolean hasMoreReferralExceptions() { |
| if (debug) |
| System.out.println( |
| "LdapReferralException.hasMoreReferralExceptions"); |
| |
| return (nextReferralEx != null); |
| } |
| |
| /** |
| * Sets the counter which records the number of hops that result |
| * from following a sequence of referrals. |
| */ |
| void setHopCount(int hopCount) { |
| if (debug) |
| System.out.println("LdapReferralException.setHopCount"); |
| |
| this.hopCount = hopCount; |
| } |
| |
| /** |
| * Sets the flag to indicate that the target name has been resolved. |
| */ |
| void setNameResolved(boolean resolved) { |
| if (debug) |
| System.out.println("LdapReferralException.setNameResolved"); |
| |
| foundEntry = resolved; |
| } |
| |
| /** |
| * Sets the exception generated while processing a referral. |
| * Only the first exception is recorded. |
| */ |
| void setNamingException(NamingException e) { |
| if (debug) |
| System.out.println("LdapReferralException.setNamingException"); |
| |
| if (errorEx == null) { |
| e.setRootCause(this); //record the referral exception that caused it |
| errorEx = e; |
| } |
| } |
| |
| /** |
| * Gets the new RDN name. |
| */ |
| String getNewRdn() { |
| if (debug) |
| System.out.println("LdapReferralException.getNewRdn"); |
| |
| return newRdn; |
| } |
| |
| /** |
| * Sets the new RDN name so that the rename operation can be completed |
| * (when a referral is being followed). |
| */ |
| void setNewRdn(String newRdn) { |
| if (debug) |
| System.out.println("LdapReferralException.setNewRdn"); |
| |
| this.newRdn = newRdn; |
| } |
| |
| /** |
| * Gets the exception generated while processing a referral. |
| */ |
| NamingException getNamingException() { |
| if (debug) |
| System.out.println("LdapReferralException.getNamingException"); |
| |
| return errorEx; |
| } |
| |
| /** |
| * Display the state of each element in a chain of LdapReferralException |
| * objects. |
| */ |
| void dump() { |
| |
| System.out.println(); |
| System.out.println("LdapReferralException.dump"); |
| LdapReferralException ptr = this; |
| while (ptr != null) { |
| ptr.dumpState(); |
| ptr = ptr.nextReferralEx; |
| } |
| } |
| |
| /** |
| * Display the state of this LdapReferralException object. |
| */ |
| private void dumpState() { |
| System.out.println("LdapReferralException.dumpState"); |
| System.out.println(" hashCode=" + hashCode()); |
| System.out.println(" foundEntry=" + foundEntry); |
| System.out.println(" skipThisReferral=" + skipThisReferral); |
| System.out.println(" referralIndex=" + referralIndex); |
| |
| if (referrals != null) { |
| System.out.println(" referrals:"); |
| for (int i = 0; i < referralCount; i++) { |
| System.out.println(" [" + i + "] " + referrals.elementAt(i)); |
| } |
| } else { |
| System.out.println(" referrals=null"); |
| } |
| |
| System.out.println(" errorEx=" + errorEx); |
| |
| if (nextReferralEx == null) { |
| System.out.println(" nextRefEx=null"); |
| } else { |
| System.out.println(" nextRefEx=" + nextReferralEx.hashCode()); |
| } |
| System.out.println(); |
| } |
| } |