//
//  ========================================================================
//  Copyright (c) 1995-2017 Mort Bay Consulting Pty. Ltd.
//  ------------------------------------------------------------------------
//  All rights reserved. This program and the accompanying materials
//  are made available under the terms of the Eclipse Public License v1.0
//  and Apache License v2.0 which accompanies this distribution.
//
//      The Eclipse Public License is available at
//      http://www.eclipse.org/legal/epl-v10.html
//
//      The Apache License v2.0 is available at
//      http://www.opensource.org/licenses/apache2.0.php
//
//  You may elect to redistribute this code under either of these licenses.
//  ========================================================================
//

package org.eclipse.jetty.xml;

import java.io.IOException;
import java.io.InputStream;
import java.io.StringReader;
import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.net.InetAddress;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.UnknownHostException;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Properties;
import java.util.Queue;
import java.util.ServiceLoader;
import java.util.Set;
import java.util.concurrent.atomic.AtomicReference;

import org.eclipse.jetty.util.ArrayQueue;
import org.eclipse.jetty.util.LazyList;
import org.eclipse.jetty.util.Loader;
import org.eclipse.jetty.util.StringUtil;
import org.eclipse.jetty.util.TypeUtil;
import org.eclipse.jetty.util.component.LifeCycle;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.util.resource.Resource;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

/**
 * <p>Configures objects from XML.</p>
 * <p>This class reads an XML file conforming to the configure.dtd DTD
 * and uses it to configure and object by calling set, put or other methods on the object.</p>
 * <p>The actual XML file format may be changed (eg to spring XML) by implementing the
 * {@link ConfigurationProcessorFactory} interface to be found by the
 * {@link ServiceLoader} by using the DTD and first tag element in the file.
 * Note that DTD will be null if validation is off.</p>
 * <p>
 * The configuration can be parameterised with properties that are looked up via the 
 * Property XML element and set on the configuration via the map returned from 
 * {@link #getProperties()}</p>
 * <p>
 * The configuration can create and lookup beans by ID.  If multiple configurations are used, then it
 * is good practise to copy the entries from the {@link #getIdMap()} of a configuration to the next 
 * configuration so that they can share an ID space for beans.</p>
 */
public class XmlConfiguration
{
    private static final Logger LOG = Log.getLogger(XmlConfiguration.class);
    private static final Class<?>[] __primitives =
            {Boolean.TYPE, Character.TYPE, Byte.TYPE, Short.TYPE, Integer.TYPE, Long.TYPE, Float.TYPE, Double.TYPE, Void.TYPE};
    private static final Class<?>[] __boxedPrimitives =
            {Boolean.class, Character.class, Byte.class, Short.class, Integer.class, Long.class, Float.class, Double.class, Void.class};
    private static final Class<?>[] __supportedCollections =
            {ArrayList.class, ArrayQueue.class, HashSet.class, Queue.class, List.class, Set.class, Collection.class};
    private static final Iterable<ConfigurationProcessorFactory> __factoryLoader = ServiceLoader.load(ConfigurationProcessorFactory.class);
    private static final XmlParser __parser = initParser();
    private static XmlParser initParser()
    {
        XmlParser parser = new XmlParser();
        URL config60 = Loader.getResource(XmlConfiguration.class, "org/eclipse/jetty/xml/configure_6_0.dtd");
        URL config76 = Loader.getResource(XmlConfiguration.class,"org/eclipse/jetty/xml/configure_7_6.dtd");
        URL config90 = Loader.getResource(XmlConfiguration.class,"org/eclipse/jetty/xml/configure_9_0.dtd");
        URL config93 = Loader.getResource(XmlConfiguration.class,"org/eclipse/jetty/xml/configure_9_3.dtd");
        parser.redirectEntity("configure.dtd",config90);
        parser.redirectEntity("configure_1_0.dtd",config60);
        parser.redirectEntity("configure_1_1.dtd",config60);
        parser.redirectEntity("configure_1_2.dtd",config60);
        parser.redirectEntity("configure_1_3.dtd",config60);
        parser.redirectEntity("configure_6_0.dtd",config60);
        parser.redirectEntity("configure_7_6.dtd",config76);
        parser.redirectEntity("configure_9_0.dtd",config90);
        parser.redirectEntity("configure_9_3.dtd",config93);

        parser.redirectEntity("http://jetty.mortbay.org/configure.dtd",config93);
        parser.redirectEntity("http://jetty.eclipse.org/configure.dtd",config93);
        parser.redirectEntity("http://www.eclipse.org/jetty/configure.dtd",config93);

        parser.redirectEntity("-//Mort Bay Consulting//DTD Configure//EN",config93);
        parser.redirectEntity("-//Jetty//Configure//EN",config93);

        return parser;
    }

    private final Map<String, Object> _idMap = new HashMap<>();
    private final Map<String, String> _propertyMap = new HashMap<>();
    private final URL _url;
    private final String _dtd;
    private ConfigurationProcessor _processor;

    /**
     * Reads and parses the XML configuration file.
     *
     * @param configuration the URL of the XML configuration
     * @throws IOException if the configuration could not be read
     * @throws SAXException if the configuration could not be parsed
     */
    public XmlConfiguration(URL configuration) throws SAXException, IOException
    {
        synchronized (__parser)
        {
            _url=configuration;
            setConfig(__parser.parse(configuration.toString()));
            _dtd=__parser.getDTD();
        }
    }

    /**
     * Reads and parses the XML configuration string.
     *
     * @param configuration String of XML configuration commands excluding the normal XML preamble.
     * The String should start with a "&lt;Configure ....&gt;" element.
     * @throws IOException if the configuration could not be read
     * @throws SAXException if the configuration could not be parsed
     */
    public XmlConfiguration(String configuration) throws SAXException, IOException
    {
        configuration = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!DOCTYPE Configure PUBLIC \"-//Jetty//Configure//EN\" \"http://eclipse.org/jetty/configure.dtd\">"
                + configuration;
        InputSource source = new InputSource(new StringReader(configuration));
        synchronized (__parser)
        {
            _url=null;
            setConfig( __parser.parse(source));
            _dtd=__parser.getDTD();
        }
    }

    /**
     * Reads and parses the XML configuration stream.
     *
     * @param configuration An input stream containing a complete configuration file
     * @throws IOException if the configuration could not be read
     * @throws SAXException if the configuration could not be parsed
     */
    public XmlConfiguration(InputStream configuration) throws SAXException, IOException
    {
        InputSource source = new InputSource(configuration);
        synchronized (__parser)
        {
            _url=null;
            setConfig(__parser.parse(source));
            _dtd=__parser.getDTD();
        }
    }

    private void setConfig(XmlParser.Node config)
    {
        if ("Configure".equals(config.getTag()))
        {
            _processor=new JettyXmlConfiguration();
        }
        else if (__factoryLoader!=null)
        {
            for (ConfigurationProcessorFactory factory : __factoryLoader)
            {
                _processor = factory.getConfigurationProcessor(_dtd, config.getTag());
                if (_processor!=null)
                    break;
            }

            if (_processor==null)
                throw new IllegalStateException("Unknown configuration type: "+config.getTag()+" in "+this);
        }
        else
        {
            throw new IllegalArgumentException("Unknown XML tag:"+config.getTag());
        }
        _processor.init(_url,config,this);
    }

    /* ------------------------------------------------------------ */
    /** Get the map of ID String to Objects that is used to hold
     * and lookup any objects by ID.  
     * <p>
     * A New, Get or Call XML element may have an
     * id attribute which will cause the resulting object to be placed into
     * this map.  A Ref XML element will lookup an object from this map.</p>
     * <p>
     * When chaining configuration files, it is good practise to copy the 
     * ID entries from the ID map to the map of the next configuration, so
     * that they may share an ID space
     * </p>
     *  
     * @return A modifiable map of ID strings to Objects
     */
    public Map<String, Object> getIdMap()
    {
        return _idMap;
    }

    /* ------------------------------------------------------------ */
    /**
     * Get the map of properties used by the Property XML element
     * to parameterise configuration. 
     * @return A modifiable map of properties.
     */
    public Map<String, String> getProperties()
    {
        return _propertyMap;
    }

    /**
     * Applies the XML configuration script to the given object.
     *
     * @param obj The object to be configured, which must be of a type or super type
     * of the class attribute of the &lt;Configure&gt; element.
     * @throws Exception if the configuration fails
     * @return the configured object
     */
    public Object configure(Object obj) throws Exception
    {
        return _processor.configure(obj);
    }

    /**
     * Applies the XML configuration script.
     * If the root element of the configuration has an ID, an object is looked up by ID and its type checked
     * against the root element's type.
     * Otherwise a new object of the type specified by the root element is created.
     *
     * @return The newly created configured object.
     * @throws Exception if the configuration fails
     */
    public Object configure() throws Exception
    {
        return _processor.configure();
    }
    
    /* ------------------------------------------------------------ */
    /** Initialize a new Object defaults.
     * <p>This method must be called by any {@link ConfigurationProcessor} when it 
     * creates a new instance of an object before configuring it, so that a derived 
     * XmlConfiguration class may inject default values.
     * @param object the object to initialize defaults on
     */
    public void initializeDefaults(Object object)
    {
    }
    

    private static class JettyXmlConfiguration implements ConfigurationProcessor
    {
        
        private String _url;
        XmlParser.Node _root;
        XmlConfiguration _configuration;

        public void init(URL url, XmlParser.Node root, XmlConfiguration configuration)
        {
            _url=url==null?null:url.toString();
            _root=root;
            _configuration=configuration;
        }

        public Object configure(Object obj) throws Exception
        {
            // Check the class of the object
            Class<?> oClass = nodeClass(_root);
            if (oClass != null && !oClass.isInstance(obj))
            {
                String loaders = (oClass.getClassLoader()==obj.getClass().getClassLoader())?"":"Object Class and type Class are from different loaders.";
                throw new IllegalArgumentException("Object of class '"+obj.getClass().getCanonicalName()+"' is not of type '" + oClass.getCanonicalName()+"'. "+loaders+" in "+_url);
            }
            String id=_root.getAttribute("id");
            if (id!=null)
                _configuration.getIdMap().put(id,obj);
            configure(obj,_root,0);
            return obj;
        }

        public Object configure() throws Exception
        {
            Class<?> oClass = nodeClass(_root);

            String id = _root.getAttribute("id");
            Object obj = id == null?null:_configuration.getIdMap().get(id);

            int index = 0;
            if (obj == null && oClass != null)
            {
                index = _root.size();
                Map<String, Object> namedArgMap = new HashMap<>();

                List<Object> arguments = new LinkedList<>();
                for (int i = 0; i < _root.size(); i++)
                {
                    Object o = _root.get(i);
                    if (o instanceof String)
                    {
                        continue;
                    }
                    XmlParser.Node node = (XmlParser.Node)o;

                    if (!(node.getTag().equals("Arg")))
                    {
                        index = i;
                        break;
                    }
                    else
                    {
                        String namedAttribute = node.getAttribute("name");
                        Object value=value(obj,(XmlParser.Node)o);
                        if (namedAttribute != null)
                            namedArgMap.put(namedAttribute,value);
                        arguments.add(value);
                    }
                }

                try
                {
                    if (namedArgMap.size() > 0)
                        obj = TypeUtil.construct(oClass, arguments.toArray(), namedArgMap);
                    else
                        obj = TypeUtil.construct(oClass, arguments.toArray());
                }
                catch (NoSuchMethodException x)
                {
                    throw new IllegalStateException(String.format("No constructor %s(%s,%s) in %s",oClass,arguments,namedArgMap,_url));
                }
            }
            if (id!=null)
                _configuration.getIdMap().put(id,obj);
                
            _configuration.initializeDefaults(obj);
            configure(obj, _root, index);
            return obj;
        }

        private static Class<?> nodeClass(XmlParser.Node node) throws ClassNotFoundException
        {
            String className = node.getAttribute("class");
            if (className == null)
                return null;

            return Loader.loadClass(XmlConfiguration.class,className);
        }

        /**
         * Recursive configuration routine.
         * This method applies the nested Set, Put, Call, etc. elements to the given object.
         *
         * @param obj the object to configure
         * @param cfg the XML nodes of the configuration
         * @param i the index of the XML nodes
         * @throws Exception if the configuration fails
         */
        public void configure(Object obj, XmlParser.Node cfg, int i) throws Exception
        {
            // Object already constructed so skip any arguments
            for (; i < cfg.size(); i++)
            {
                Object o = cfg.get(i);
                if (o instanceof String)
                    continue;
                XmlParser.Node node = (XmlParser.Node)o;
                if ("Arg".equals(node.getTag()))
                {
                    LOG.warn("Ignored arg: "+node);
                    continue;
                }
                break;
            }
            
            // Process real arguments
            for (; i < cfg.size(); i++)
            {
                Object o = cfg.get(i);
                if (o instanceof String)
                    continue;
                XmlParser.Node node = (XmlParser.Node)o;

                try
                {
                    String tag = node.getTag();
                    switch (tag)
                    {
                        case "Set":
                            set(obj, node);
                            break;
                        case "Put":
                            put(obj, node);
                            break;
                        case "Call":
                            call(obj, node);
                            break;
                        case "Get":
                            get(obj, node);
                            break;
                        case "New":
                            newObj(obj, node);
                            break;
                        case "Array":
                            newArray(obj, node);
                            break;
                        case "Map":
                            newMap(obj,node);
                            break;
                        case "Ref":
                            refObj(obj, node);
                            break;
                        case "Property":
                            propertyObj(node);
                            break;
                        case "SystemProperty":
                            systemPropertyObj(node);
                            break;
                        case "Env":
                            envObj(node);
                            break;
                        default:
                            throw new IllegalStateException("Unknown tag: " + tag + " in " + _url);
                    }
                }
                catch (Exception e)
                {
                    LOG.warn("Config error at " + node,e.toString()+" in "+_url);
                    throw e;
                }
            }
        }

        /*
         * Call a set method. This method makes a best effort to find a matching set method. The type of the value is used to find a suitable set method by 1.
         * Trying for a trivial type match. 2. Looking for a native type match. 3. Trying all correctly named methods for an auto conversion. 4. Attempting to
         * construct a suitable value from original value. @param obj
         *
         * @param node
         */
        private void set(Object obj, XmlParser.Node node) throws Exception
        {
            String attr = node.getAttribute("name");
            String name = "set" + attr.substring(0,1).toUpperCase(Locale.ENGLISH) + attr.substring(1);
            Object value = value(obj,node);
            Object[] arg =
            { value };

            Class<?> oClass = nodeClass(node);
            if (oClass != null)
                obj = null;
            else
                oClass = obj.getClass();

            Class<?>[] vClass =
            { Object.class };
            if (value != null)
                vClass[0] = value.getClass();

            if (LOG.isDebugEnabled())
                LOG.debug("XML " + (obj != null?obj.toString():oClass.getName()) + "." + name + "(" + value + ")");

            // Try for trivial match
            try
            {
                Method set = oClass.getMethod(name,vClass);
                set.invoke(obj,arg);
                return;
            }
            catch (IllegalArgumentException | IllegalAccessException | NoSuchMethodException e)
            {
                LOG.ignore(e);
            }

            // Try for native match
            try
            {
                Field type = vClass[0].getField("TYPE");
                vClass[0] = (Class<?>)type.get(null);
                Method set = oClass.getMethod(name,vClass);
                set.invoke(obj,arg);
                return;
            }
            catch (NoSuchFieldException | IllegalArgumentException | IllegalAccessException | NoSuchMethodException e)
            {
                LOG.ignore(e);
            }

            // Try a field
            try
            {
                Field field = oClass.getField(attr);
                if (Modifier.isPublic(field.getModifiers()))
                {
                    field.set(obj,value);
                    return;
                }
            }
            catch (NoSuchFieldException e)
            {
                LOG.ignore(e);
            }

            // Search for a match by trying all the set methods
            Method[] sets = oClass.getMethods();
            Method set = null;
            for (int s = 0; sets != null && s < sets.length; s++)
            {
                Class<?>[] paramTypes = sets[s].getParameterTypes();
                if (name.equals(sets[s].getName()) && paramTypes.length == 1)
                {
                    // lets try it
                    try
                    {
                        set = sets[s];
                        sets[s].invoke(obj,arg);
                        return;
                    }
                    catch (IllegalArgumentException | IllegalAccessException e)
                    {
                        LOG.ignore(e);
                    }

                    try
                    {
                        for (Class<?> c : __supportedCollections)
                            if (paramTypes[0].isAssignableFrom(c))
                            {
                                sets[s].invoke(obj,convertArrayToCollection(value,c));
                                return;
                            }
                    }
                    catch (IllegalAccessException e)
                    {
                        LOG.ignore(e);
                    }
                }
            }

            // Try converting the arg to the last set found.
            if (set != null)
            {
                try
                {
                    Class<?> sClass = set.getParameterTypes()[0];
                    if (sClass.isPrimitive())
                    {
                        for (int t = 0; t < __primitives.length; t++)
                        {
                            if (sClass.equals(__primitives[t]))
                            {
                                sClass = __boxedPrimitives[t];
                                break;
                            }
                        }
                    }
                    Constructor<?> cons = sClass.getConstructor(vClass);
                    arg[0] = cons.newInstance(arg);
                    _configuration.initializeDefaults(arg[0]);
                    set.invoke(obj,arg);
                    return;
                }
                catch (NoSuchMethodException | IllegalAccessException | InstantiationException e)
                {
                    LOG.ignore(e);
                }
            }

            // No Joy
            throw new NoSuchMethodException(oClass + "." + name + "(" + vClass[0] + ")");
        }

        /**
         * @param array the array to convert
         * @param collectionType the desired collection type
         * @return a collection of the desired type if the array can be converted
         */
        private static Collection<?> convertArrayToCollection(Object array, Class<?> collectionType)
        {
            Collection<?> collection = null;
            if (array.getClass().isArray())
            {
                if (collectionType.isAssignableFrom(ArrayList.class))
                    collection = convertArrayToArrayList(array);
                else if (collectionType.isAssignableFrom(HashSet.class))
                    collection = new HashSet<>(convertArrayToArrayList(array));
                else if (collectionType.isAssignableFrom(ArrayQueue.class))
                {
                    ArrayQueue<Object> q= new ArrayQueue<>();
                    q.addAll(convertArrayToArrayList(array));
                    collection=q;
                }
            }
            if (collection==null)
                throw new IllegalArgumentException("Can't convert \"" + array.getClass() + "\" to " + collectionType);
            return collection;
        }

        private static ArrayList<Object> convertArrayToArrayList(Object array)
        {
            int length = Array.getLength(array);
            ArrayList<Object> list = new ArrayList<>(length);
            for (int i = 0; i < length; i++)
                list.add(Array.get(array,i));
            return list;
        }

        /*
         * Call a put method.
         *
         * @param obj @param node
         */
        private void put(Object obj, XmlParser.Node node) throws Exception
        {
            if (!(obj instanceof Map))
                throw new IllegalArgumentException("Object for put is not a Map: " + obj);
            @SuppressWarnings("unchecked")
            Map<Object, Object> map = (Map<Object, Object>)obj;

            String name = node.getAttribute("name");
            Object value = value(obj, node);
            map.put(name,value);
            if (LOG.isDebugEnabled())
                LOG.debug("XML " + obj + ".put(" + name + "," + value + ")");
        }

        /*
         * Call a get method. Any object returned from the call is passed to the configure method to consume the remaining elements. @param obj @param node
         * If class attribute is given and the name is "class", then the class instance itself is returned.
         * @return @exception Exception
         */
        private Object get(Object obj, XmlParser.Node node) throws Exception
        {
            Class<?> oClass = nodeClass(node);
            if (oClass != null)
                obj = null;
            else
                oClass = obj.getClass();

            String name = node.getAttribute("name");
            String id = node.getAttribute("id");
            if (LOG.isDebugEnabled())
                LOG.debug("XML get " + name);

            try
            {
                // Handle getClass explicitly
                if ("class".equalsIgnoreCase(name))
                    obj=oClass;
                else
                {
                    // try calling a getXxx method.
                    Method method = oClass.getMethod("get" + name.substring(0,1).toUpperCase(Locale.ENGLISH) + name.substring(1),(java.lang.Class[])null);
                    obj = method.invoke(obj,(java.lang.Object[])null);
                }
                if (id!=null)
                    _configuration.getIdMap().put(id,obj);
                configure(obj,node,0);
            }
            catch (NoSuchMethodException nsme)
            {
                try
                {
                    Field field = oClass.getField(name);
                    obj = field.get(obj);
                    configure(obj,node,0);
                }
                catch (NoSuchFieldException nsfe)
                {
                    throw nsme;
                }
            }
            return obj;
        }

        /*
         * Call a method. A method is selected by trying all methods with matching names and number of arguments. Any object returned from the call is passed to
         * the configure method to consume the remaining elements. Note that if this is a static call we consider only methods declared directly in the given
         * class. i.e. we ignore any static methods in superclasses. @param obj
         *
         * @param node @return @exception Exception
         */
        private Object call(Object obj, XmlParser.Node node) throws Exception
        {
            AttrOrElementNode aoeNode=new AttrOrElementNode(obj,node,"Id","Name","Class","Arg");
            String id = aoeNode.getString("Id");
            String name = aoeNode.getString("Name");
            String clazz = aoeNode.getString("Class");
            List<Object> args = aoeNode.getList("Arg");
            
            
            Class<?> oClass;
            if (clazz!=null)
            {
                // static call
                oClass=Loader.loadClass(XmlConfiguration.class,clazz);
                obj=null;
            }
            else if (obj!=null)
            {
                oClass = obj.getClass();
            }
            else
                throw new IllegalArgumentException(node.toString());
           
            if (LOG.isDebugEnabled())
                LOG.debug("XML call " + name);

            try
            {
                Object nobj= TypeUtil.call(oClass,name,obj,args.toArray(new Object[args.size()]));
                if (id != null)
                    _configuration.getIdMap().put(id,nobj);
                configure(nobj,node,aoeNode.getNext());
                return nobj;
            }
            catch (NoSuchMethodException e)
            {
                IllegalStateException ise = new IllegalStateException("No Method: " + node + " on " + oClass);
                ise.initCause(e);
                throw ise;
            }
        }

        /*
         * Create a new value object.
         *
         * @param obj
         * @param node
         *
         * @return @exception Exception
         */
        private Object newObj(Object obj, XmlParser.Node node) throws Exception
        {
            AttrOrElementNode aoeNode=new AttrOrElementNode(obj,node,"Id","Class","Arg");
            String id = aoeNode.getString("Id");
            String clazz = aoeNode.getString("Class");
            List<XmlParser.Node> argNodes = aoeNode.getNodes("Arg");

            if (LOG.isDebugEnabled())
                LOG.debug("XML new " + clazz);
            
            Class<?> oClass = Loader.loadClass(XmlConfiguration.class,clazz);
            
            // Find the <Arg> elements
            Map<String, Object> namedArgMap = new HashMap<>();
            List<Object> arguments = new LinkedList<>();
            for (XmlParser.Node child : argNodes)
            {
                String namedAttribute = child.getAttribute("name");
                Object value=value(obj,child);
                if (namedAttribute != null)
                {
                    // named arguments
                    namedArgMap.put(namedAttribute,value);
                }
                // raw arguments
                arguments.add(value);
            }

            Object nobj;
            try
            {
                if (namedArgMap.size() > 0)
                {
                   LOG.debug("using named mapping");
                   nobj = TypeUtil.construct(oClass, arguments.toArray(), namedArgMap);
                }
                else
                {
                    LOG.debug("using normal mapping");
                    nobj = TypeUtil.construct(oClass, arguments.toArray());
                }
            }
            catch (NoSuchMethodException e)
            {
                throw new IllegalStateException("No suitable constructor: " + node + " on " + obj);
            }

            if (id != null)
                _configuration.getIdMap().put(id, nobj);
            
            _configuration.initializeDefaults(nobj);
            configure(nobj,node,aoeNode.getNext());
            return nobj;
        }

        /*
         * Reference an id value object.
         *
         * @param obj @param node @return @exception NoSuchMethodException @exception ClassNotFoundException @exception InvocationTargetException
         */
        private Object refObj(Object obj, XmlParser.Node node) throws Exception
        {
            String refid = node.getAttribute("refid");
            if (refid==null)
                refid = node.getAttribute("id");
            obj = _configuration.getIdMap().get(refid);
            if (obj == null && node.size()>0)
                throw new IllegalStateException("No object for refid=" + refid);
            configure(obj,node,0);
            return obj;
        }

        /*
         * Create a new array object.
         */
        private Object newArray(Object obj, XmlParser.Node node) throws Exception
        {
            AttrOrElementNode aoeNode=new AttrOrElementNode(obj,node,"Id","Type","Item");
            String id = aoeNode.getString("Id");
            String type = aoeNode.getString("Type");
            List<XmlParser.Node> items = aoeNode.getNodes("Item");
            
            // Get the type
            Class<?> aClass = java.lang.Object.class;
            if (type != null)
            {
                aClass = TypeUtil.fromName(type);
                if (aClass == null)
                {
                    switch (type)
                    {
                        case "String":
                            aClass = String.class;
                            break;
                        case "URL":
                            aClass = URL.class;
                            break;
                        case "InetAddress":
                            aClass = InetAddress.class;
                            break;
                        default:
                            aClass = Loader.loadClass(XmlConfiguration.class, type);
                            break;
                    }
                }
            }
            
            Object al = null;

            for (XmlParser.Node item : items)
            {
                String nid = item.getAttribute("id");
                Object v = value(obj,item);
                al = LazyList.add(al,(v == null && aClass.isPrimitive())?0:v);
                if (nid != null)
                    _configuration.getIdMap().put(nid,v);
            }

            Object array = LazyList.toArray(al,aClass);
            if (id != null)
                _configuration.getIdMap().put(id,array);
            return array;
        }

        /*
         * Create a new map object.
         */
        private Object newMap(Object obj, XmlParser.Node node) throws Exception
        {
            AttrOrElementNode aoeNode=new AttrOrElementNode(node,"Id","Entry");
            String id = aoeNode.getString("Id");
            List<XmlParser.Node> entries = aoeNode.getNodes("Entry");

            Map<Object, Object> map = new HashMap<>();
            if (id != null)
                _configuration.getIdMap().put(id, map);

            for (XmlParser.Node entry : entries)
            {
                if (!entry.getTag().equals("Entry"))
                    throw new IllegalStateException("Not an Entry");

                XmlParser.Node key = null;
                XmlParser.Node value = null;

                for (Object object : entry)
                {
                    if (object instanceof String)
                        continue;
                    XmlParser.Node item = (XmlParser.Node)object;
                    if (!item.getTag().equals("Item"))
                        throw new IllegalStateException("Not an Item");
                    if (key == null)
                        key = item;
                    else
                        value = item;
                }

                if (key == null || value == null)
                    throw new IllegalStateException("Missing Item in Entry");
                String kid = key.getAttribute("id");
                String vid = value.getAttribute("id");

                Object k = value(obj,key);
                Object v = value(obj,value);
                map.put(k,v);

                if (kid != null)
                    _configuration.getIdMap().put(kid,k);
                if (vid != null)
                    _configuration.getIdMap().put(vid,v);
            }

            return map;
        }

        /*
         * Get a Property.
         *
         * @param node
         * @return
         * @exception Exception
         */
        private Object propertyObj(XmlParser.Node node) throws Exception
        {
            AttrOrElementNode aoeNode=new AttrOrElementNode(node,"Id","Name","Deprecated","Default");
            String id = aoeNode.getString("Id");
            String name = aoeNode.getString("Name",true);
            List<Object> deprecated = aoeNode.getList("Deprecated");
            String dftValue = aoeNode.getString("Default");

            // Look for a value
            Map<String,String> properties = _configuration.getProperties();
            String value = properties.get(name);
            
            // Look for a deprecated name value

            String alternate=null;
            if (!deprecated.isEmpty())
            {
                for (Object d : deprecated)
                { 
                    String v = properties.get(StringUtil.valueOf(d));
                    if (v!=null)
                    {
                        if (value==null)
                            LOG.warn("Property '{}' is deprecated, use '{}' instead", d, name);
                        else
                            LOG.warn("Property '{}' is deprecated, value from '{}' used", d, name);
                    }
                    if (alternate==null)
                        alternate=v;;
                }
            }

            // use alternate from deprecated
            if (value==null)
                value=alternate;
            
            // use default value
            if (value==null)
                value=dftValue;

            // Set value if ID set
            if (id != null)
                _configuration.getIdMap().put(id, value);
            return value;
        }

        /*
         * Get a SystemProperty.
         *
         * @param node
         * @return
         * @exception Exception
         */
        private Object systemPropertyObj(XmlParser.Node node) throws Exception
        {
            AttrOrElementNode aoeNode=new AttrOrElementNode(node,"Id","Name","Deprecated","Default");
            String id = aoeNode.getString("Id");
            String name = aoeNode.getString("Name",true);
            List<Object> deprecated = aoeNode.getList("Deprecated");
            String dftValue = aoeNode.getString("Default");

            // Look for a value
            String value = System.getProperty(name);
            
            // Look for a deprecated name value
            String alternate=null;
            if (!deprecated.isEmpty())
            {
                for (Object d : deprecated)
                { 
                    String v = System.getProperty(StringUtil.valueOf(d));
                    if (v!=null)
                    {
                        if (value==null)
                            LOG.warn("SystemProperty '{}' is deprecated, use '{}' instead", d, name);
                        else
                            LOG.warn("SystemProperty '{}' is deprecated, value from '{}' used", d, name);
                    }
                    if (alternate==null)
                        alternate=v;;
                }
            }

            // use alternate from deprecated
            if (value==null)
                value=alternate;
            
            // use default value
            if (value==null)
                value=dftValue;

            // Set value if ID set
            if (id != null)
                _configuration.getIdMap().put(id, value);

            return value;
        }
        
        /*
         * Get a Environment Property.
         *
         * @param node
         * @return
         * @exception Exception
         */
        private Object envObj(XmlParser.Node node) throws Exception
        {
            AttrOrElementNode aoeNode=new AttrOrElementNode(node,"Id","Name","Deprecated","Default");
            String id = aoeNode.getString("Id");
            String name = aoeNode.getString("Name",true);
            List<Object> deprecated = aoeNode.getList("Deprecated");
            String dftValue = aoeNode.getString("Default");

            // Look for a value
            String value = System.getenv(name);
            
            // Look for a deprecated name value
            if (value==null && !deprecated.isEmpty())
            {
                for (Object d : deprecated)
                {
                    value = System.getenv(StringUtil.valueOf(d));
                    if (value!=null)
                    {
                        LOG.warn("Property '{}' is deprecated, use '{}' instead", d, name);
                        break;
                    }
                }
            }
            
            // use default value
            if (value==null)
                value=dftValue;

            // Set value if ID set
            if (id != null)
                _configuration.getIdMap().put(id, value);

            return value;
        }

        /*
         * Get the value of an element. If no value type is specified, then white space is trimmed out of the value. If it contains multiple value elements they
         * are added as strings before being converted to any specified type. @param node
         */
        private Object value(Object obj, XmlParser.Node node) throws Exception
        {
            Object value;

            // Get the type
            String type = node.getAttribute("type");

            // Try a ref lookup
            String ref = node.getAttribute("ref");
            if (ref != null)
            {
                value = _configuration.getIdMap().get(ref);
            }
            else
            {
                // handle trivial case
                if (node.size() == 0)
                {
                    if ("String".equals(type))
                        return "";
                    return null;
                }

                // Trim values
                int first = 0;
                int last = node.size() - 1;

                // Handle default trim type
                if (type == null || !"String".equals(type))
                {
                    // Skip leading white
                    Object item;
                    while (first <= last)
                    {
                        item = node.get(first);
                        if (!(item instanceof String))
                            break;
                        item = ((String)item).trim();
                        if (((String)item).length() > 0)
                            break;
                        first++;
                    }

                    // Skip trailing white
                    while (first < last)
                    {
                        item = node.get(last);
                        if (!(item instanceof String))
                            break;
                        item = ((String)item).trim();
                        if (((String)item).length() > 0)
                            break;
                        last--;
                    }

                    // All white, so return null
                    if (first > last)
                        return null;
                }

                if (first == last)
                    // Single Item value
                    value = itemValue(obj,node.get(first));
                else
                {
                    // Get the multiple items as a single string
                    StringBuilder buf = new StringBuilder();
                    for (int i = first; i <= last; i++)
                    {
                        Object item = node.get(i);
                        buf.append(itemValue(obj,item));
                    }
                    value = buf.toString();
                }
            }

            // Untyped or unknown
            if (value == null)
            {
                if ("String".equals(type))
                    return "";
                return null;
            }

            // Try to type the object
            if (type == null)
            {
                if (value instanceof String)
                    return ((String)value).trim();
                return value;
            }

            if (isTypeMatchingClass(type,String.class))
                return value.toString();

            Class<?> pClass = TypeUtil.fromName(type);
            if (pClass != null)
                return TypeUtil.valueOf(pClass,value.toString());

            if (isTypeMatchingClass(type,URL.class))
            {
                if (value instanceof URL)
                    return value;
                try
                {
                    return new URL(value.toString());
                }
                catch (MalformedURLException e)
                {
                    throw new InvocationTargetException(e);
                }
            }

            if (isTypeMatchingClass(type,InetAddress.class))
            {
                if (value instanceof InetAddress)
                    return value;
                try
                {
                    return InetAddress.getByName(value.toString());
                }
                catch (UnknownHostException e)
                {
                    throw new InvocationTargetException(e);
                }
            }

            for (Class<?> collectionClass : __supportedCollections)
            {
                if (isTypeMatchingClass(type,collectionClass))
                    return convertArrayToCollection(value,collectionClass);
            }

            throw new IllegalStateException("Unknown type " + type);
        }

        private static boolean isTypeMatchingClass(String type, Class<?> classToMatch)
        {
            return classToMatch.getSimpleName().equalsIgnoreCase(type) || classToMatch.getName().equals(type);
        }

        /*
         * Get the value of a single element. @param obj @param item @return @exception Exception
         */
        private Object itemValue(Object obj, Object item) throws Exception
        {
            // String value
            if (item instanceof String)
                return item;

            XmlParser.Node node = (XmlParser.Node)item;
            String tag = node.getTag();
            if ("Call".equals(tag))
                return call(obj,node);
            if ("Get".equals(tag))
                return get(obj,node);
            if ("New".equals(tag))
                return newObj(obj,node);
            if ("Ref".equals(tag))
                return refObj(obj,node);
            if ("Array".equals(tag))
                return newArray(obj,node);
            if ("Map".equals(tag))
                return newMap(obj,node);
            if ("Property".equals(tag))
                return propertyObj(node);
            if ("SystemProperty".equals(tag))
                return systemPropertyObj(node);
            if ("Env".equals(tag))
                return envObj(node);

            LOG.warn("Unknown value tag: " + node,new Throwable());
            return null;
        }
        

        private class AttrOrElementNode
        {
            final Object _obj;
            final XmlParser.Node _node;
            final Set<String> _elements = new HashSet<>();
            final int _next;

            AttrOrElementNode(XmlParser.Node node,String... elements )
            {
                this(null,node,elements);
            }
            
            AttrOrElementNode(Object obj, XmlParser.Node node,String... elements )
            {
                _obj=obj;
                _node=node;
                for (String e:elements)
                    _elements.add(e);
                
                int next=0;
                for (Object o: _node)
                {
                    if (o instanceof String)
                    {
                        if (((String)o).trim().length()==0)
                        {
                            next++;
                            continue;
                        }
                        break;
                    }
                    
                    if (!(o instanceof XmlParser.Node))
                        break;
                    
                    XmlParser.Node n = (XmlParser.Node)o;
                    if (!_elements.contains(n.getTag()))
                        break;
                    
                    next++;
                }
                _next=next;
            }

            public int getNext()
            {
                return _next;
            }

            public String getString(String elementName) throws Exception
            {
                return StringUtil.valueOf(get(elementName,false));
            }
            
            public String getString(String elementName, boolean manditory) throws Exception
            {
                return StringUtil.valueOf(get(elementName,manditory));
            }
            
            public Object get(String elementName, boolean manditory) throws Exception
            {
                String attrName=StringUtil.asciiToLowerCase(elementName);
                String attr = _node.getAttribute(attrName);
                Object value=attr;
                
                for (int i=0;i<_next;i++)
                {
                    Object o = _node.get(i);
                    if (!(o instanceof XmlParser.Node))
                        continue;
                    XmlParser.Node n = (XmlParser.Node)o;
                    if (elementName.equals(n.getTag()))
                    {
                        if (attr!=null)
                            throw new IllegalStateException("Cannot have attr '"+attrName+"' and element '"+elementName+"'");

                        value=value(_obj,n);
                        break;
                    }
                }
                
                if (manditory && value==null)
                    throw new IllegalStateException("Must have attr '"+attrName+"' or element '"+elementName+"'");
                
                return value;
            }

            public List<Object> getList(String elementName) throws Exception
            {
                return getList(elementName,false);
            }
            
            public List<Object> getList(String elementName, boolean manditory) throws Exception
            {
                String attrName=StringUtil.asciiToLowerCase(elementName);
                final List<Object> values=new ArrayList<>();
                
                String attr = _node.getAttribute(attrName);
                if (attr!=null)
                    values.addAll(StringUtil.csvSplit(null,attr,0,attr.length()));


                for (int i=0;i<_next;i++)
                {
                    Object o = _node.get(i);
                    if (!(o instanceof XmlParser.Node))
                        continue;
                    XmlParser.Node n = (XmlParser.Node)o;
                    
                    if (elementName.equals(n.getTag()))
                    {
                        if (attr!=null)
                            throw new IllegalStateException("Cannot have attr '"+attrName+"' and element '"+elementName+"'");

                        values.add(value(_obj,n));
                    }
                }
                
                if (manditory && values.isEmpty())
                    throw new IllegalStateException("Must have attr '"+attrName+"' or element '"+elementName+"'");

                return values;
            }
            
            public List<XmlParser.Node> getNodes(String elementName) throws Exception
            {
                String attrName=StringUtil.asciiToLowerCase(elementName);
                final List<XmlParser.Node> values=new ArrayList<>();
                
                String attr = _node.getAttribute(attrName);
                if (attr!=null)
                {
                    for (String a : StringUtil.csvSplit(null,attr,0,attr.length()))
                    {
                        // create a fake node
                        XmlParser.Node n = new XmlParser.Node(null,elementName,null);
                        n.add(a);
                        values.add(n);
                    }
                }

                for (int i=0;i<_next;i++)
                {
                    Object o = _node.get(i);
                    if (!(o instanceof XmlParser.Node))
                        continue;
                    XmlParser.Node n = (XmlParser.Node)o;
                    
                    if (elementName.equals(n.getTag()))
                    {
                        if (attr!=null)
                            throw new IllegalStateException("Cannot have attr '"+attrName+"' and element '"+elementName+"'");

                        values.add(n);
                    }
                }

                return values;
            }
        }
    }

    /**
     * Run the XML configurations as a main application. The command line is used to obtain properties files (must be named '*.properties') and XmlConfiguration
     * files.
     * <p>
     * Any property file on the command line is added to a combined Property instance that is passed to each configuration file via
     * {@link XmlConfiguration#getProperties()}.
     * <p>
     * Each configuration file on the command line is used to create a new XmlConfiguration instance and the {@link XmlConfiguration#configure()} method is used
     * to create the configured object. If the resulting object is an instance of {@link LifeCycle}, then it is started.
     * <p>
     * Any IDs created in a configuration are passed to the next configuration file on the command line using {@link #getIdMap()}.
     * This allows objects with IDs created in one config file to be referenced in subsequent config files on the command line.
     *
     * @param args
     *            array of property and xml configuration filenames or {@link Resource}s.
     * @throws Exception if the XML configurations cannot be run
     */
    public static void main(final String... args) throws Exception
    {
        final AtomicReference<Throwable> exception = new AtomicReference<>();

        AccessController.doPrivileged(new PrivilegedAction<Object>()
        {
            public Object run()
            {
                try
                {
                    Properties properties = null;

                    // Look for properties from start.jar
                    try
                    {
                        Class<?> config = XmlConfiguration.class.getClassLoader().loadClass("org.eclipse.jetty.start.Config");
                        properties = (Properties)config.getMethod("getProperties").invoke(null);
                        LOG.debug("org.eclipse.jetty.start.Config properties = {}",properties);
                    }
                    catch (NoClassDefFoundError | ClassNotFoundException e)
                    {
                        LOG.ignore(e);
                    }
                    catch (Exception e)
                    {
                        LOG.warn(e);
                    }

                    // If no start.config properties, use clean slate
                    if (properties == null)
                    {
                        // Add System Properties
                        properties = new Properties();
                        properties.putAll(System.getProperties());
                    }

                    // For all arguments, load properties
                    for (String arg : args)
                    {
                        if (arg.indexOf('=')>=0)
                        {
                            int i=arg.indexOf('=');
                            properties.put(arg.substring(0,i),arg.substring(i+1));
                        }
                        else if (arg.toLowerCase(Locale.ENGLISH).endsWith(".properties"))
                            properties.load(Resource.newResource(arg).getInputStream());
                    }

                    // For all arguments, parse XMLs
                    XmlConfiguration last = null;
                    Object[] obj = new Object[args.length];
                    for (int i = 0; i < args.length; i++)
                    {
                        if (!args[i].toLowerCase(Locale.ENGLISH).endsWith(".properties") && (args[i].indexOf('=')<0))
                        {
                            XmlConfiguration configuration = new XmlConfiguration(Resource.newResource(args[i]).getURI().toURL());
                            if (last != null)
                                configuration.getIdMap().putAll(last.getIdMap());
                            if (properties.size() > 0)
                            {
                                Map<String, String> props = new HashMap<>();
                                for (Object key : properties.keySet())
                                {
                                    props.put(key.toString(),String.valueOf(properties.get(key)));
                                }
                                configuration.getProperties().putAll(props);
                            }
                            obj[i] = configuration.configure();
                            last = configuration;
                        }
                    }

                    // For all objects created by XmlConfigurations, start them if they are lifecycles.
                    for (int i = 0; i < args.length; i++)
                    {
                        if (obj[i] instanceof LifeCycle)
                        {
                            LifeCycle lc = (LifeCycle)obj[i];
                            if (!lc.isRunning())
                                lc.start();
                        }
                    }
                }
                catch (Exception e)
                {
                    LOG.debug(Log.EXCEPTION,e);
                    exception.set(e);
                }
                return null;
            }
        });

        Throwable th = exception.get();
        if (th != null)
        {
            if (th instanceof RuntimeException)
                throw (RuntimeException)th;
            else if (th instanceof Exception)
                throw (Exception)th;
            else if (th instanceof Error)
                throw (Error)th;
            throw new Error(th);
        }
    }
}
