/**
 * Copyright (c) 2005-2012 EBM WebSourcing, 2012-2015 Linagora
 * 
 * This program/library is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 2.1 of the License, or (at your
 * option) any later version.
 * 
 * This program/library 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 Lesser General Public License
 * for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program/library; If not, see <http://www.gnu.org/licenses/>
 * for the GNU Lesser General Public License version 2.1.
 */
package org.ow2.petals.microkernel.util;

import java.util.Map;
import java.util.Map.Entry;

import javax.naming.Binding;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.LinkRef;
import javax.naming.NameClassPair;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;

/**
 * This utility class is used to help us to manage JNDI directories.
 * @author ddesjardins - EBM WebSourcing
 */
public final class JNDIUtil {

    private JNDIUtil() {
        super();
    }

    /**
     * Browse the JNDI server.
     * 
     * @param initialContext
     *            The InitialContext connected to the JNDI server
     * @param host
     *            The JNDI host. Can be {@code null}
     * @param port
     *            The JNDI port
     * @return
     * @throws NamingException
     */
    public static String browseJNDI(InitialContext initialContext, String host, int port)
            throws NamingException {
        StringBuilder result = new StringBuilder();

        if (host == null) {
            result.append("JNDI directory local \n<== / ==>\n");
        } else {
            result.append("JNDI directory on " + host + ":" + port + "\n<== / ==>\n");
        }

        recurseBindings(initialContext, initialContext.listBindings("/"), "\t", result);

        return result.toString().replaceAll("&47;", "/");
    }

    /**
     * Recurse the contexts
     * 
     * @param bindings
     * @throws NamingException
     */
    protected static void recurseBindings(Context context, NamingEnumeration<Binding> bindings,
            String tabs, StringBuilder result) throws NamingException {

        while (bindings.hasMoreElements()) {

            Binding binding = bindings.next();

            Object object = binding.getObject();

            if (object instanceof Context) {
                result.append("\n" + tabs + "<=" + binding.getName() + "=>\n");
                try {
                    recurseBindings((Context) object, context.listBindings(binding.getName()), tabs
                            + "\t", result);
                } catch (Exception e) {
                    recurseNames((Context) object, context.list(binding.getName()), tabs + "\t",
                            result);
                }
            } else if (object instanceof Map) {
                result.append(tabs + "-> " + binding.getName() + "\n");
                Map<?, ?> map = (Map<?, ?>) object;
                for (Entry<?, ?> entry : map.entrySet()) {
                    result.append(tabs + "\t" + "-> (" + entry.getKey() + ") " + entry.getValue()
                            + "\n");
                }
            } else if (object instanceof LinkRef) {
                LinkRef linkRef = (LinkRef) binding.getObject();
                result.append(tabs + "-> " + binding.getName() + " [Link to "
                        + linkRef.getLinkName() + "]\n");
            } else {
                result.append(tabs + "-> " + binding.getObject() + "\n");
            }
        }
    }

    /**
     * Recurse the contexts
     * 
     * @param bindings
     * @throws NamingException
     */
    protected static void recurseNames(Context context, NamingEnumeration<NameClassPair> names,
            String tabs, StringBuilder result) throws NamingException {

        while (names.hasMoreElements()) {
            NameClassPair name = names.next();
            result.append(tabs + "-> " + name.getName() + "\n");
        }
    }
}
