001: /*
002: * Copyright 1999-2004 Sun Microsystems, Inc. All Rights Reserved.
003: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004: *
005: * This code is free software; you can redistribute it and/or modify it
006: * under the terms of the GNU General Public License version 2 only, as
007: * published by the Free Software Foundation. Sun designates this
008: * particular file as subject to the "Classpath" exception as provided
009: * by Sun in the LICENSE file that accompanied this code.
010: *
011: * This code is distributed in the hope that it will be useful, but WITHOUT
012: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
014: * version 2 for more details (a copy is included in the LICENSE file that
015: * accompanied this code).
016: *
017: * You should have received a copy of the GNU General Public License version
018: * 2 along with this work; if not, write to the Free Software Foundation,
019: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020: *
021: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022: * CA 95054 USA or visit www.sun.com if you need additional information or
023: * have any questions.
024: */
025:
026: package com.sun.jndi.ldap;
027:
028: import javax.naming.*;
029: import javax.naming.spi.*;
030: import javax.naming.ldap.Control;
031:
032: import java.util.Hashtable;
033: import java.util.Vector;
034:
035: /**
036: * This exception is raised when a referral to an alternative context
037: * is encountered.
038: * <p>
039: * An <tt>LdapReferralException</tt> object contains one or more referrals.
040: * Each referral is an alternative location for the same target entry.
041: * For example, a referral may be an LDAP URL.
042: * The referrals are attempted in sequence until one is successful or
043: * all have failed. In the case of the latter then the exception generated
044: * by the final referral is recorded and presented later.
045: * <p>
046: * A referral may be skipped or may be retried. For example, in the case
047: * of an authentication error, a referral may be retried with different
048: * environment properties.
049: * <p>
050: * An <tt>LdapReferralException</tt> object may also contain a reference
051: * to a chain of unprocessed <tt>LdapReferralException</tt> objects.
052: * Once the current set of referrals have been exhausted and unprocessed
053: * <tt>LdapReferralException</tt> objects remain, then the
054: * <tt>LdapReferralException</tt> object referenced by the current
055: * object is thrown and the cycle continues.
056: * <p>
057: * If new <tt>LdapReferralException</tt> objects are generated while
058: * following an existing referral then these new objects are appended
059: * to the end of the chain of unprocessed <tt>LdapReferralException</tt>
060: * objects.
061: * <p>
062: * If an exception was recorded while processing a chain of
063: * <tt>LdapReferralException</tt> objects then is is throw once
064: * processing has completed.
065: *
066: * @author Vincent Ryan
067: */
068: final public class LdapReferralException extends
069: javax.naming.ldap.LdapReferralException {
070:
071: // ----------- fields initialized in constructor ---------------
072: private int handleReferrals;
073: private Hashtable envprops;
074: private String nextName;
075: private Control[] reqCtls;
076:
077: // ----------- fields that have defaults -----------------------
078: private Vector referrals = null; // alternatives,set by setReferralInfo()
079: private int referralIndex = 0; // index into referrals
080: private int referralCount = 0; // count of referrals
081: private boolean foundEntry = false; // will stop when entry is found
082: private boolean skipThisReferral = false;
083: private int hopCount = 1;
084: private NamingException errorEx = null;
085: private String newRdn = null;
086: private boolean debug = false;
087: LdapReferralException nextReferralEx = null; // referral ex. chain
088:
089: /**
090: * Constructs a new instance of LdapReferralException.
091: * @param resolvedName The part of the name that has been successfully
092: * resolved.
093: * @param resolvedObj The object to which resolution was successful.
094: * @param remainingName The remaining unresolved portion of the name.
095: * @param explanation Additional detail about this exception.
096: */
097: LdapReferralException(Name resolvedName, Object resolvedObj,
098: Name remainingName, String explanation, Hashtable envprops,
099: String nextName, int handleReferrals, Control[] reqCtls) {
100:
101: super (explanation);
102:
103: if (debug)
104: System.out.println("LdapReferralException constructor");
105:
106: setResolvedName(resolvedName);
107: setResolvedObj(resolvedObj);
108: setRemainingName(remainingName);
109: this .envprops = envprops;
110: this .nextName = nextName;
111: this .handleReferrals = handleReferrals;
112:
113: // If following referral, request controls are passed to referral ctx
114: this .reqCtls = (handleReferrals == LdapClient.LDAP_REF_FOLLOW ? reqCtls
115: : null);
116: }
117:
118: /**
119: * Gets a context at which to continue processing.
120: * The current environment properties are re-used.
121: */
122: public Context getReferralContext() throws NamingException {
123: return getReferralContext(envprops, null);
124: }
125:
126: /**
127: * Gets a context at which to continue processing.
128: * The supplied environment properties are used.
129: */
130: public Context getReferralContext(Hashtable<?, ?> newProps)
131: throws NamingException {
132: return getReferralContext(newProps, null);
133: }
134:
135: /**
136: * Gets a context at which to continue processing.
137: * The supplied environment properties and connection controls are used.
138: */
139: public Context getReferralContext(Hashtable<?, ?> newProps,
140: Control[] connCtls) throws NamingException {
141:
142: if (debug)
143: System.out
144: .println("LdapReferralException.getReferralContext");
145:
146: LdapReferralContext refCtx = new LdapReferralContext(this ,
147: newProps, connCtls, reqCtls, nextName,
148: skipThisReferral, handleReferrals);
149:
150: refCtx.setHopCount(hopCount + 1);
151:
152: if (skipThisReferral) {
153: skipThisReferral = false; // reset
154: }
155: return (Context) refCtx;
156: }
157:
158: /**
159: * Gets referral information.
160: */
161: public Object getReferralInfo() {
162: if (debug) {
163: System.out.println("LdapReferralException.getReferralInfo");
164: System.out.println(" referralIndex=" + referralIndex);
165: }
166:
167: if (hasMoreReferrals()) {
168: return referrals.elementAt(referralIndex);
169: } else {
170: return null;
171: }
172: }
173:
174: /**
175: * Marks the current referral as one to be retried.
176: */
177: public void retryReferral() {
178: if (debug)
179: System.out.println("LdapReferralException.retryReferral");
180:
181: if (referralIndex > 0)
182: referralIndex--; // decrement index
183: }
184:
185: /**
186: * Marks the current referral as one to be ignored.
187: * Returns false when there are no referrals remaining to be processed.
188: */
189: public boolean skipReferral() {
190: if (debug)
191: System.out.println("LdapReferralException.skipReferral");
192:
193: skipThisReferral = true;
194:
195: // advance to next referral
196: try {
197: getNextReferral();
198: } catch (ReferralException e) {
199: // mask the referral exception
200: }
201:
202: return (hasMoreReferrals() || hasMoreReferralExceptions());
203: }
204:
205: /**
206: * Sets referral information.
207: */
208: void setReferralInfo(Vector referrals, boolean continuationRef) {
209: // %%% continuationRef is currently ignored
210:
211: if (debug)
212: System.out.println("LdapReferralException.setReferralInfo");
213:
214: this .referrals = referrals;
215: if (referrals != null) {
216: referralCount = referrals.size();
217: }
218:
219: if (debug) {
220: for (int i = 0; i < referralCount; i++) {
221: System.out.println(" [" + i + "] "
222: + referrals.elementAt(i));
223: }
224: }
225: }
226:
227: /**
228: * Gets the next referral. When the current set of referrals have
229: * been exhausted then the next referral exception is thrown, if available.
230: */
231: String getNextReferral() throws ReferralException {
232:
233: if (debug)
234: System.out.println("LdapReferralException.getNextReferral");
235:
236: if (hasMoreReferrals()) {
237: return (String) referrals.elementAt(referralIndex++);
238: } else if (hasMoreReferralExceptions()) {
239: throw nextReferralEx;
240: } else {
241: return null;
242: }
243: }
244:
245: /**
246: * Appends the supplied (chain of) referral exception onto the end of
247: * the current (chain of) referral exception. Spent referral exceptions
248: * are trimmed off.
249: */
250: LdapReferralException appendUnprocessedReferrals(
251: LdapReferralException back) {
252:
253: if (debug) {
254: System.out
255: .println("LdapReferralException.appendUnprocessedReferrals");
256: dump();
257: if (back != null) {
258: back.dump();
259: }
260: }
261:
262: LdapReferralException front = this ;
263:
264: if (!front.hasMoreReferrals()) {
265: front = nextReferralEx; // trim
266:
267: if ((errorEx != null) && (front != null)) {
268: front.setNamingException(errorEx); //advance the saved exception
269: }
270: }
271:
272: // don't append onto itself
273: if (this == back) {
274: return front;
275: }
276:
277: if ((back != null) && (!back.hasMoreReferrals())) {
278: back = back.nextReferralEx; // trim
279: }
280:
281: if (back == null) {
282: return front;
283: }
284:
285: // Locate the end of the current chain
286: LdapReferralException ptr = front;
287: while (ptr.nextReferralEx != null) {
288: ptr = ptr.nextReferralEx;
289: }
290: ptr.nextReferralEx = back; // append
291:
292: return front;
293: }
294:
295: /**
296: * Tests if there are any referrals remaining to be processed.
297: * If name resolution has already completed then any remaining
298: * referrals (in the current referral exception) will be ignored.
299: */
300: boolean hasMoreReferrals() {
301: if (debug)
302: System.out
303: .println("LdapReferralException.hasMoreReferrals");
304:
305: return (!foundEntry) && (referralIndex < referralCount);
306: }
307:
308: /**
309: * Tests if there are any referral exceptions remaining to be processed.
310: */
311: boolean hasMoreReferralExceptions() {
312: if (debug)
313: System.out
314: .println("LdapReferralException.hasMoreReferralExceptions");
315:
316: return (nextReferralEx != null);
317: }
318:
319: /**
320: * Sets the counter which records the number of hops that result
321: * from following a sequence of referrals.
322: */
323: void setHopCount(int hopCount) {
324: if (debug)
325: System.out.println("LdapReferralException.setHopCount");
326:
327: this .hopCount = hopCount;
328: }
329:
330: /**
331: * Sets the flag to indicate that the target name has been resolved.
332: */
333: void setNameResolved(boolean resolved) {
334: if (debug)
335: System.out.println("LdapReferralException.setNameResolved");
336:
337: foundEntry = resolved;
338: }
339:
340: /**
341: * Sets the exception generated while processing a referral.
342: * Only the first exception is recorded.
343: */
344: void setNamingException(NamingException e) {
345: if (debug)
346: System.out
347: .println("LdapReferralException.setNamingException");
348:
349: if (errorEx == null) {
350: e.setRootCause(this ); //record the referral exception that caused it
351: errorEx = e;
352: }
353: }
354:
355: /**
356: * Gets the new RDN name.
357: */
358: String getNewRdn() {
359: if (debug)
360: System.out.println("LdapReferralException.getNewRdn");
361:
362: return newRdn;
363: }
364:
365: /**
366: * Sets the new RDN name so that the rename operation can be completed
367: * (when a referral is being followed).
368: */
369: void setNewRdn(String newRdn) {
370: if (debug)
371: System.out.println("LdapReferralException.setNewRdn");
372:
373: this .newRdn = newRdn;
374: }
375:
376: /**
377: * Gets the exception generated while processing a referral.
378: */
379: NamingException getNamingException() {
380: if (debug)
381: System.out
382: .println("LdapReferralException.getNamingException");
383:
384: return errorEx;
385: }
386:
387: /**
388: * Display the state of each element in a chain of LdapReferralException
389: * objects.
390: */
391: void dump() {
392:
393: System.out.println();
394: System.out.println("LdapReferralException.dump");
395: LdapReferralException ptr = this ;
396: while (ptr != null) {
397: ptr.dumpState();
398: ptr = ptr.nextReferralEx;
399: }
400: }
401:
402: /**
403: * Display the state of this LdapReferralException object.
404: */
405: private void dumpState() {
406: System.out.println("LdapReferralException.dumpState");
407: System.out.println(" hashCode=" + hashCode());
408: System.out.println(" foundEntry=" + foundEntry);
409: System.out.println(" skipThisReferral=" + skipThisReferral);
410: System.out.println(" referralIndex=" + referralIndex);
411:
412: if (referrals != null) {
413: System.out.println(" referrals:");
414: for (int i = 0; i < referralCount; i++) {
415: System.out.println(" [" + i + "] "
416: + referrals.elementAt(i));
417: }
418: } else {
419: System.out.println(" referrals=null");
420: }
421:
422: System.out.println(" errorEx=" + errorEx);
423:
424: if (nextReferralEx == null) {
425: System.out.println(" nextRefEx=null");
426: } else {
427: System.out.println(" nextRefEx="
428: + nextReferralEx.hashCode());
429: }
430: System.out.println();
431: }
432: }
|