/*
 * Copyright 1999-2004 Sun Microsystems, Inc.  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.  Sun designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
 * CA 95054 USA or visit www.sun.com if you need additional information or
 * have any questions.
 */

package com.sun.jndi.ldap;

import javax.naming.*;
import javax.naming.spi.*;
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 {

        // ----------- 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;
        if (referrals != null) {
            referralCount = referrals.size();
        }

        if (debug) {
            for (int i = 0; i < referralCount; i++) {
                System.out.println("  [" + i + "] " + referrals.elementAt(i));
            }
        }
    }

    /**
     * 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();
    }
}
