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