/* |
|
* Copyright (c) 1999, 2017, 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 || |
|
handleReferrals == LdapClient.LDAP_REF_FOLLOW_SCHEME ? 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(); |
|
} |
|
} |