103928aee4356845252ac6b662d5c72c29903813eJake Slack//
203928aee4356845252ac6b662d5c72c29903813eJake Slack//  ========================================================================
303928aee4356845252ac6b662d5c72c29903813eJake Slack//  Copyright (c) 1995-2014 Mort Bay Consulting Pty. Ltd.
403928aee4356845252ac6b662d5c72c29903813eJake Slack//  ------------------------------------------------------------------------
503928aee4356845252ac6b662d5c72c29903813eJake Slack//  All rights reserved. This program and the accompanying materials
603928aee4356845252ac6b662d5c72c29903813eJake Slack//  are made available under the terms of the Eclipse Public License v1.0
703928aee4356845252ac6b662d5c72c29903813eJake Slack//  and Apache License v2.0 which accompanies this distribution.
803928aee4356845252ac6b662d5c72c29903813eJake Slack//
903928aee4356845252ac6b662d5c72c29903813eJake Slack//      The Eclipse Public License is available at
1003928aee4356845252ac6b662d5c72c29903813eJake Slack//      http://www.eclipse.org/legal/epl-v10.html
1103928aee4356845252ac6b662d5c72c29903813eJake Slack//
1203928aee4356845252ac6b662d5c72c29903813eJake Slack//      The Apache License v2.0 is available at
1303928aee4356845252ac6b662d5c72c29903813eJake Slack//      http://www.opensource.org/licenses/apache2.0.php
1403928aee4356845252ac6b662d5c72c29903813eJake Slack//
1503928aee4356845252ac6b662d5c72c29903813eJake Slack//  You may elect to redistribute this code under either of these licenses.
1603928aee4356845252ac6b662d5c72c29903813eJake Slack//  ========================================================================
1703928aee4356845252ac6b662d5c72c29903813eJake Slack//
1803928aee4356845252ac6b662d5c72c29903813eJake Slack
1903928aee4356845252ac6b662d5c72c29903813eJake Slackpackage org.eclipse.jetty.xml;
2003928aee4356845252ac6b662d5c72c29903813eJake Slack
2103928aee4356845252ac6b662d5c72c29903813eJake Slackimport java.io.IOException;
2203928aee4356845252ac6b662d5c72c29903813eJake Slackimport java.io.InputStream;
2303928aee4356845252ac6b662d5c72c29903813eJake Slackimport java.io.StringReader;
2403928aee4356845252ac6b662d5c72c29903813eJake Slackimport java.lang.reflect.Array;
2503928aee4356845252ac6b662d5c72c29903813eJake Slackimport java.lang.reflect.Constructor;
2603928aee4356845252ac6b662d5c72c29903813eJake Slackimport java.lang.reflect.Field;
2703928aee4356845252ac6b662d5c72c29903813eJake Slackimport java.lang.reflect.InvocationTargetException;
2803928aee4356845252ac6b662d5c72c29903813eJake Slackimport java.lang.reflect.Method;
2903928aee4356845252ac6b662d5c72c29903813eJake Slackimport java.lang.reflect.Modifier;
3003928aee4356845252ac6b662d5c72c29903813eJake Slackimport java.net.InetAddress;
3103928aee4356845252ac6b662d5c72c29903813eJake Slackimport java.net.MalformedURLException;
3203928aee4356845252ac6b662d5c72c29903813eJake Slackimport java.net.URL;
3303928aee4356845252ac6b662d5c72c29903813eJake Slackimport java.net.UnknownHostException;
3403928aee4356845252ac6b662d5c72c29903813eJake Slackimport java.security.AccessController;
3503928aee4356845252ac6b662d5c72c29903813eJake Slackimport java.security.PrivilegedAction;
3603928aee4356845252ac6b662d5c72c29903813eJake Slackimport java.util.ArrayList;
3703928aee4356845252ac6b662d5c72c29903813eJake Slackimport java.util.Collection;
3803928aee4356845252ac6b662d5c72c29903813eJake Slackimport java.util.Enumeration;
3903928aee4356845252ac6b662d5c72c29903813eJake Slackimport java.util.HashMap;
4003928aee4356845252ac6b662d5c72c29903813eJake Slackimport java.util.HashSet;
4103928aee4356845252ac6b662d5c72c29903813eJake Slackimport java.util.List;
4203928aee4356845252ac6b662d5c72c29903813eJake Slackimport java.util.Locale;
4303928aee4356845252ac6b662d5c72c29903813eJake Slackimport java.util.Map;
4403928aee4356845252ac6b662d5c72c29903813eJake Slackimport java.util.Properties;
4503928aee4356845252ac6b662d5c72c29903813eJake Slackimport java.util.Queue;
4603928aee4356845252ac6b662d5c72c29903813eJake Slackimport java.util.Set;
4703928aee4356845252ac6b662d5c72c29903813eJake Slackimport java.util.concurrent.atomic.AtomicReference;
4803928aee4356845252ac6b662d5c72c29903813eJake Slack
4903928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.eclipse.jetty.util.ArrayQueue;
5003928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.eclipse.jetty.util.LazyList;
5103928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.eclipse.jetty.util.Loader;
5203928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.eclipse.jetty.util.TypeUtil;
5303928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.eclipse.jetty.util.component.LifeCycle;
5403928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.eclipse.jetty.util.log.Log;
5503928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.eclipse.jetty.util.log.Logger;
5603928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.eclipse.jetty.util.resource.Resource;
5703928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.eclipse.jetty.xml.XmlParser.Node;
5803928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.xml.sax.InputSource;
5903928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.xml.sax.SAXException;
6003928aee4356845252ac6b662d5c72c29903813eJake Slack
6103928aee4356845252ac6b662d5c72c29903813eJake Slack/* ------------------------------------------------------------ */
6203928aee4356845252ac6b662d5c72c29903813eJake Slack/**
6303928aee4356845252ac6b662d5c72c29903813eJake Slack * Configure Objects from XML. 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
6403928aee4356845252ac6b662d5c72c29903813eJake Slack * methods on the object.
6503928aee4356845252ac6b662d5c72c29903813eJake Slack *
6603928aee4356845252ac6b662d5c72c29903813eJake Slack * <p>
6703928aee4356845252ac6b662d5c72c29903813eJake Slack * The actual XML file format may be changed (eg to spring XML) by implementing the {@link ConfigurationProcessorFactory} interfaces to be found by the
6803928aee4356845252ac6b662d5c72c29903813eJake Slack * <code>ServiceLoader</code> by using the DTD and first tag element in the file. Note that DTD will be null if validation is off.
6903928aee4356845252ac6b662d5c72c29903813eJake Slack *
7003928aee4356845252ac6b662d5c72c29903813eJake Slack */
7103928aee4356845252ac6b662d5c72c29903813eJake Slackpublic class XmlConfiguration
7203928aee4356845252ac6b662d5c72c29903813eJake Slack{
7303928aee4356845252ac6b662d5c72c29903813eJake Slack    private static final Logger LOG = Log.getLogger(XmlConfiguration.class);
7403928aee4356845252ac6b662d5c72c29903813eJake Slack
7503928aee4356845252ac6b662d5c72c29903813eJake Slack    private static final Class<?>[] __primitives =
7603928aee4356845252ac6b662d5c72c29903813eJake Slack    { Boolean.TYPE, Character.TYPE, Byte.TYPE, Short.TYPE, Integer.TYPE, Long.TYPE, Float.TYPE, Double.TYPE, Void.TYPE };
7703928aee4356845252ac6b662d5c72c29903813eJake Slack
7803928aee4356845252ac6b662d5c72c29903813eJake Slack    private static final Class<?>[] __primitiveHolders =
7903928aee4356845252ac6b662d5c72c29903813eJake Slack    { Boolean.class, Character.class, Byte.class, Short.class, Integer.class, Long.class, Float.class, Double.class, Void.class };
8003928aee4356845252ac6b662d5c72c29903813eJake Slack
8103928aee4356845252ac6b662d5c72c29903813eJake Slack    private static final Class<?>[] __supportedCollections =
8203928aee4356845252ac6b662d5c72c29903813eJake Slack    { ArrayList.class,ArrayQueue.class,HashSet.class,Queue.class,List.class,Set.class,Collection.class,};
8303928aee4356845252ac6b662d5c72c29903813eJake Slack
8403928aee4356845252ac6b662d5c72c29903813eJake Slack    private static final Iterable<?> __factoryLoader;
8503928aee4356845252ac6b662d5c72c29903813eJake Slack
8603928aee4356845252ac6b662d5c72c29903813eJake Slack    private static final XmlParser __parser = initParser();
8703928aee4356845252ac6b662d5c72c29903813eJake Slack
8803928aee4356845252ac6b662d5c72c29903813eJake Slack    static
8903928aee4356845252ac6b662d5c72c29903813eJake Slack    {
9003928aee4356845252ac6b662d5c72c29903813eJake Slack        Iterable<?> loader=null;
9103928aee4356845252ac6b662d5c72c29903813eJake Slack        try
9203928aee4356845252ac6b662d5c72c29903813eJake Slack        {
9303928aee4356845252ac6b662d5c72c29903813eJake Slack            // Use reflection to look up 1.6 service loader
9403928aee4356845252ac6b662d5c72c29903813eJake Slack            // loader=ServiceLoader.load(ConfigurationProcessorFactory.class);
9503928aee4356845252ac6b662d5c72c29903813eJake Slack            Class<?> slc = ClassLoader.getSystemClassLoader().loadClass("java.util.ServiceLoader");
9603928aee4356845252ac6b662d5c72c29903813eJake Slack            Method load = slc.getMethod("load",Class.class);
9703928aee4356845252ac6b662d5c72c29903813eJake Slack            loader=(Iterable<?>)load.invoke(null,ConfigurationProcessorFactory.class);
9803928aee4356845252ac6b662d5c72c29903813eJake Slack        }
9903928aee4356845252ac6b662d5c72c29903813eJake Slack        catch(Exception e)
10003928aee4356845252ac6b662d5c72c29903813eJake Slack        {
10103928aee4356845252ac6b662d5c72c29903813eJake Slack            LOG.ignore(e);
10203928aee4356845252ac6b662d5c72c29903813eJake Slack        }
10303928aee4356845252ac6b662d5c72c29903813eJake Slack        finally
10403928aee4356845252ac6b662d5c72c29903813eJake Slack        {
10503928aee4356845252ac6b662d5c72c29903813eJake Slack            __factoryLoader=loader;
10603928aee4356845252ac6b662d5c72c29903813eJake Slack        }
10703928aee4356845252ac6b662d5c72c29903813eJake Slack    }
10803928aee4356845252ac6b662d5c72c29903813eJake Slack
10903928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
11003928aee4356845252ac6b662d5c72c29903813eJake Slack    private URL _url;
11103928aee4356845252ac6b662d5c72c29903813eJake Slack    private String _dtd;
11203928aee4356845252ac6b662d5c72c29903813eJake Slack    private ConfigurationProcessor _processor;
11303928aee4356845252ac6b662d5c72c29903813eJake Slack    private final Map<String, Object> _idMap = new HashMap<String, Object>();
11403928aee4356845252ac6b662d5c72c29903813eJake Slack    private final Map<String, String> _propertyMap = new HashMap<String, String>();
11503928aee4356845252ac6b662d5c72c29903813eJake Slack
11603928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
11703928aee4356845252ac6b662d5c72c29903813eJake Slack    private synchronized static XmlParser initParser()
11803928aee4356845252ac6b662d5c72c29903813eJake Slack    {
11903928aee4356845252ac6b662d5c72c29903813eJake Slack        XmlParser parser = new XmlParser();
12003928aee4356845252ac6b662d5c72c29903813eJake Slack        URL config60 = Loader.getResource(XmlConfiguration.class,"org/eclipse/jetty/xml/configure_6_0.dtd",true);
12103928aee4356845252ac6b662d5c72c29903813eJake Slack        URL config76 = Loader.getResource(XmlConfiguration.class,"org/eclipse/jetty/xml/configure_7_6.dtd",true);
12203928aee4356845252ac6b662d5c72c29903813eJake Slack        parser.redirectEntity("configure.dtd",config76);
12303928aee4356845252ac6b662d5c72c29903813eJake Slack        parser.redirectEntity("configure_1_0.dtd",config60);
12403928aee4356845252ac6b662d5c72c29903813eJake Slack        parser.redirectEntity("configure_1_1.dtd",config60);
12503928aee4356845252ac6b662d5c72c29903813eJake Slack        parser.redirectEntity("configure_1_2.dtd",config60);
12603928aee4356845252ac6b662d5c72c29903813eJake Slack        parser.redirectEntity("configure_1_3.dtd",config60);
12703928aee4356845252ac6b662d5c72c29903813eJake Slack        parser.redirectEntity("configure_6_0.dtd",config60);
12803928aee4356845252ac6b662d5c72c29903813eJake Slack        parser.redirectEntity("configure_7_6.dtd",config76);
12903928aee4356845252ac6b662d5c72c29903813eJake Slack
13003928aee4356845252ac6b662d5c72c29903813eJake Slack        parser.redirectEntity("http://jetty.mortbay.org/configure.dtd",config76);
13103928aee4356845252ac6b662d5c72c29903813eJake Slack        parser.redirectEntity("http://jetty.eclipse.org/configure.dtd",config76);
13203928aee4356845252ac6b662d5c72c29903813eJake Slack        parser.redirectEntity("http://www.eclipse.org/jetty/configure.dtd",config76);
13303928aee4356845252ac6b662d5c72c29903813eJake Slack
13403928aee4356845252ac6b662d5c72c29903813eJake Slack        parser.redirectEntity("-//Mort Bay Consulting//DTD Configure//EN",config76);
13503928aee4356845252ac6b662d5c72c29903813eJake Slack        parser.redirectEntity("-//Jetty//Configure//EN",config76);
13603928aee4356845252ac6b662d5c72c29903813eJake Slack
13703928aee4356845252ac6b662d5c72c29903813eJake Slack        return parser;
13803928aee4356845252ac6b662d5c72c29903813eJake Slack    }
13903928aee4356845252ac6b662d5c72c29903813eJake Slack
14003928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
14103928aee4356845252ac6b662d5c72c29903813eJake Slack    /**
14203928aee4356845252ac6b662d5c72c29903813eJake Slack     * Reads and parses the XML configuration file.
14303928aee4356845252ac6b662d5c72c29903813eJake Slack     *
14403928aee4356845252ac6b662d5c72c29903813eJake Slack     * @param configuration the URL of the XML configuration
14503928aee4356845252ac6b662d5c72c29903813eJake Slack     * @throws IOException if the configuration could not be read
14603928aee4356845252ac6b662d5c72c29903813eJake Slack     * @throws SAXException if the configuration could not be parsed
14703928aee4356845252ac6b662d5c72c29903813eJake Slack     */
14803928aee4356845252ac6b662d5c72c29903813eJake Slack    public XmlConfiguration(URL configuration) throws SAXException, IOException
14903928aee4356845252ac6b662d5c72c29903813eJake Slack    {
15003928aee4356845252ac6b662d5c72c29903813eJake Slack        synchronized (__parser)
15103928aee4356845252ac6b662d5c72c29903813eJake Slack        {
15203928aee4356845252ac6b662d5c72c29903813eJake Slack            _url=configuration;
15303928aee4356845252ac6b662d5c72c29903813eJake Slack            setConfig(__parser.parse(configuration.toString()));
15403928aee4356845252ac6b662d5c72c29903813eJake Slack            _dtd=__parser.getDTD();
15503928aee4356845252ac6b662d5c72c29903813eJake Slack        }
15603928aee4356845252ac6b662d5c72c29903813eJake Slack    }
15703928aee4356845252ac6b662d5c72c29903813eJake Slack
15803928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
15903928aee4356845252ac6b662d5c72c29903813eJake Slack    /**
16003928aee4356845252ac6b662d5c72c29903813eJake Slack     * Reads and parses the XML configuration string.
16103928aee4356845252ac6b662d5c72c29903813eJake Slack     *
16203928aee4356845252ac6b662d5c72c29903813eJake Slack     * @param configuration String of XML configuration commands excluding the normal XML preamble.
16303928aee4356845252ac6b662d5c72c29903813eJake Slack     * The String should start with a "&lt;Configure ....&gt;" element.
16403928aee4356845252ac6b662d5c72c29903813eJake Slack     * @throws IOException if the configuration could not be read
16503928aee4356845252ac6b662d5c72c29903813eJake Slack     * @throws SAXException if the configuration could not be parsed
16603928aee4356845252ac6b662d5c72c29903813eJake Slack     */
16703928aee4356845252ac6b662d5c72c29903813eJake Slack    public XmlConfiguration(String configuration) throws SAXException, IOException
16803928aee4356845252ac6b662d5c72c29903813eJake Slack    {
16903928aee4356845252ac6b662d5c72c29903813eJake Slack        configuration = "<?xml version=\"1.0\"  encoding=\"ISO-8859-1\"?>\n<!DOCTYPE Configure PUBLIC \"-//Mort Bay Consulting//DTD Configure 1.2//EN\" \"http://jetty.eclipse.org/configure_1_2.dtd\">"
17003928aee4356845252ac6b662d5c72c29903813eJake Slack                + configuration;
17103928aee4356845252ac6b662d5c72c29903813eJake Slack        InputSource source = new InputSource(new StringReader(configuration));
17203928aee4356845252ac6b662d5c72c29903813eJake Slack        synchronized (__parser)
17303928aee4356845252ac6b662d5c72c29903813eJake Slack        {
17403928aee4356845252ac6b662d5c72c29903813eJake Slack            setConfig( __parser.parse(source));
17503928aee4356845252ac6b662d5c72c29903813eJake Slack            _dtd=__parser.getDTD();
17603928aee4356845252ac6b662d5c72c29903813eJake Slack        }
17703928aee4356845252ac6b662d5c72c29903813eJake Slack    }
17803928aee4356845252ac6b662d5c72c29903813eJake Slack
17903928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
18003928aee4356845252ac6b662d5c72c29903813eJake Slack    /**
18103928aee4356845252ac6b662d5c72c29903813eJake Slack     * Reads and parses the XML configuration stream.
18203928aee4356845252ac6b662d5c72c29903813eJake Slack     *
18303928aee4356845252ac6b662d5c72c29903813eJake Slack     * @param configuration An input stream containing a complete configuration file
18403928aee4356845252ac6b662d5c72c29903813eJake Slack     * @throws IOException if the configuration could not be read
18503928aee4356845252ac6b662d5c72c29903813eJake Slack     * @throws SAXException if the configuration could not be parsed
18603928aee4356845252ac6b662d5c72c29903813eJake Slack     */
18703928aee4356845252ac6b662d5c72c29903813eJake Slack    public XmlConfiguration(InputStream configuration) throws SAXException, IOException
18803928aee4356845252ac6b662d5c72c29903813eJake Slack    {
18903928aee4356845252ac6b662d5c72c29903813eJake Slack        InputSource source = new InputSource(configuration);
19003928aee4356845252ac6b662d5c72c29903813eJake Slack        synchronized (__parser)
19103928aee4356845252ac6b662d5c72c29903813eJake Slack        {
19203928aee4356845252ac6b662d5c72c29903813eJake Slack            setConfig(__parser.parse(source));
19303928aee4356845252ac6b662d5c72c29903813eJake Slack            _dtd=__parser.getDTD();
19403928aee4356845252ac6b662d5c72c29903813eJake Slack        }
19503928aee4356845252ac6b662d5c72c29903813eJake Slack    }
19603928aee4356845252ac6b662d5c72c29903813eJake Slack
19703928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
19803928aee4356845252ac6b662d5c72c29903813eJake Slack    private void setConfig(XmlParser.Node config)
19903928aee4356845252ac6b662d5c72c29903813eJake Slack    {
20003928aee4356845252ac6b662d5c72c29903813eJake Slack        if ("Configure".equals(config.getTag()))
20103928aee4356845252ac6b662d5c72c29903813eJake Slack        {
20203928aee4356845252ac6b662d5c72c29903813eJake Slack            _processor=new JettyXmlConfiguration();
20303928aee4356845252ac6b662d5c72c29903813eJake Slack        }
20403928aee4356845252ac6b662d5c72c29903813eJake Slack        else if (__factoryLoader!=null)
20503928aee4356845252ac6b662d5c72c29903813eJake Slack        {
20603928aee4356845252ac6b662d5c72c29903813eJake Slack            for ( Object factory : __factoryLoader)
20703928aee4356845252ac6b662d5c72c29903813eJake Slack            {
20803928aee4356845252ac6b662d5c72c29903813eJake Slack                // use reflection to get 1.6 methods
20903928aee4356845252ac6b662d5c72c29903813eJake Slack                Method gcp;
21003928aee4356845252ac6b662d5c72c29903813eJake Slack                try
21103928aee4356845252ac6b662d5c72c29903813eJake Slack                {
21203928aee4356845252ac6b662d5c72c29903813eJake Slack                    gcp = factory.getClass().getMethod("getConfigurationProcessor",String.class,String.class);
21303928aee4356845252ac6b662d5c72c29903813eJake Slack                    _processor = (ConfigurationProcessor) gcp.invoke(factory,_dtd,config.getTag());
21403928aee4356845252ac6b662d5c72c29903813eJake Slack                }
21503928aee4356845252ac6b662d5c72c29903813eJake Slack                catch (Exception e)
21603928aee4356845252ac6b662d5c72c29903813eJake Slack                {
21703928aee4356845252ac6b662d5c72c29903813eJake Slack                    LOG.warn(e);
21803928aee4356845252ac6b662d5c72c29903813eJake Slack                }
21903928aee4356845252ac6b662d5c72c29903813eJake Slack                if (_processor!=null)
22003928aee4356845252ac6b662d5c72c29903813eJake Slack                    break;
22103928aee4356845252ac6b662d5c72c29903813eJake Slack            }
22203928aee4356845252ac6b662d5c72c29903813eJake Slack
22303928aee4356845252ac6b662d5c72c29903813eJake Slack            if (_processor==null)
22403928aee4356845252ac6b662d5c72c29903813eJake Slack                throw new IllegalStateException("Unknown configuration type: "+config.getTag()+" in "+this);
22503928aee4356845252ac6b662d5c72c29903813eJake Slack        }
22603928aee4356845252ac6b662d5c72c29903813eJake Slack        else
22703928aee4356845252ac6b662d5c72c29903813eJake Slack        {
22803928aee4356845252ac6b662d5c72c29903813eJake Slack            throw new IllegalArgumentException("Unknown XML tag:"+config.getTag());
22903928aee4356845252ac6b662d5c72c29903813eJake Slack        }
23003928aee4356845252ac6b662d5c72c29903813eJake Slack        _processor.init(_url,config,this);
23103928aee4356845252ac6b662d5c72c29903813eJake Slack    }
23203928aee4356845252ac6b662d5c72c29903813eJake Slack
23303928aee4356845252ac6b662d5c72c29903813eJake Slack
23403928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
23503928aee4356845252ac6b662d5c72c29903813eJake Slack    public Map<String, Object> getIdMap()
23603928aee4356845252ac6b662d5c72c29903813eJake Slack    {
23703928aee4356845252ac6b662d5c72c29903813eJake Slack        return _idMap;
23803928aee4356845252ac6b662d5c72c29903813eJake Slack    }
23903928aee4356845252ac6b662d5c72c29903813eJake Slack
24003928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
24103928aee4356845252ac6b662d5c72c29903813eJake Slack    /**
24203928aee4356845252ac6b662d5c72c29903813eJake Slack     * @param map the ID map
24303928aee4356845252ac6b662d5c72c29903813eJake Slack     * @deprecated use {@link #getIdMap()}.put(...)
24403928aee4356845252ac6b662d5c72c29903813eJake Slack     */
24503928aee4356845252ac6b662d5c72c29903813eJake Slack    @Deprecated
24603928aee4356845252ac6b662d5c72c29903813eJake Slack    public void setIdMap(Map<String, Object> map)
24703928aee4356845252ac6b662d5c72c29903813eJake Slack    {
24803928aee4356845252ac6b662d5c72c29903813eJake Slack        _idMap.clear();
24903928aee4356845252ac6b662d5c72c29903813eJake Slack        _idMap.putAll(map);
25003928aee4356845252ac6b662d5c72c29903813eJake Slack    }
25103928aee4356845252ac6b662d5c72c29903813eJake Slack
25203928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
25303928aee4356845252ac6b662d5c72c29903813eJake Slack    /**
25403928aee4356845252ac6b662d5c72c29903813eJake Slack     * @param map the properties map
25503928aee4356845252ac6b662d5c72c29903813eJake Slack     * @deprecated use {@link #getProperties()}.putAll(...)
25603928aee4356845252ac6b662d5c72c29903813eJake Slack     */
25703928aee4356845252ac6b662d5c72c29903813eJake Slack    @Deprecated
25803928aee4356845252ac6b662d5c72c29903813eJake Slack    public void setProperties(Map<String, String> map)
25903928aee4356845252ac6b662d5c72c29903813eJake Slack    {
26003928aee4356845252ac6b662d5c72c29903813eJake Slack        _propertyMap.clear();
26103928aee4356845252ac6b662d5c72c29903813eJake Slack        _propertyMap.putAll(map);
26203928aee4356845252ac6b662d5c72c29903813eJake Slack    }
26303928aee4356845252ac6b662d5c72c29903813eJake Slack
26403928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
26503928aee4356845252ac6b662d5c72c29903813eJake Slack    public Map<String, String> getProperties()
26603928aee4356845252ac6b662d5c72c29903813eJake Slack    {
26703928aee4356845252ac6b662d5c72c29903813eJake Slack        return _propertyMap;
26803928aee4356845252ac6b662d5c72c29903813eJake Slack    }
26903928aee4356845252ac6b662d5c72c29903813eJake Slack
27003928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
27103928aee4356845252ac6b662d5c72c29903813eJake Slack    /**
27203928aee4356845252ac6b662d5c72c29903813eJake Slack     * Applies the XML configuration script to the given object.
27303928aee4356845252ac6b662d5c72c29903813eJake Slack     *
27403928aee4356845252ac6b662d5c72c29903813eJake Slack     * @param obj The object to be configured, which must be of a type or super type
27503928aee4356845252ac6b662d5c72c29903813eJake Slack     * of the class attribute of the &lt;Configure&gt; element.
27603928aee4356845252ac6b662d5c72c29903813eJake Slack     * @throws Exception if the configuration fails
27703928aee4356845252ac6b662d5c72c29903813eJake Slack     * @return the configured object
27803928aee4356845252ac6b662d5c72c29903813eJake Slack     */
27903928aee4356845252ac6b662d5c72c29903813eJake Slack    public Object configure(Object obj) throws Exception
28003928aee4356845252ac6b662d5c72c29903813eJake Slack    {
28103928aee4356845252ac6b662d5c72c29903813eJake Slack        return _processor.configure(obj);
28203928aee4356845252ac6b662d5c72c29903813eJake Slack    }
28303928aee4356845252ac6b662d5c72c29903813eJake Slack
28403928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
28503928aee4356845252ac6b662d5c72c29903813eJake Slack    /**
28603928aee4356845252ac6b662d5c72c29903813eJake Slack     * Applies the XML configuration script.
28703928aee4356845252ac6b662d5c72c29903813eJake Slack     * If the root element of the configuration has an ID, an object is looked up by ID and its type checked
28803928aee4356845252ac6b662d5c72c29903813eJake Slack     * against the root element's type.
28903928aee4356845252ac6b662d5c72c29903813eJake Slack     * Otherwise a new object of the type specified by the root element is created.
29003928aee4356845252ac6b662d5c72c29903813eJake Slack     *
29103928aee4356845252ac6b662d5c72c29903813eJake Slack     * @return The newly created configured object.
29203928aee4356845252ac6b662d5c72c29903813eJake Slack     * @throws Exception if the configuration fails
29303928aee4356845252ac6b662d5c72c29903813eJake Slack     */
29403928aee4356845252ac6b662d5c72c29903813eJake Slack    public Object configure() throws Exception
29503928aee4356845252ac6b662d5c72c29903813eJake Slack    {
29603928aee4356845252ac6b662d5c72c29903813eJake Slack        return _processor.configure();
29703928aee4356845252ac6b662d5c72c29903813eJake Slack    }
29803928aee4356845252ac6b662d5c72c29903813eJake Slack
29903928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
30003928aee4356845252ac6b662d5c72c29903813eJake Slack    /** Initialize a new Object defaults.
30103928aee4356845252ac6b662d5c72c29903813eJake Slack     * <p>This method must be called by any {@link ConfigurationProcessor} when it
30203928aee4356845252ac6b662d5c72c29903813eJake Slack     * creates a new instance of an object before configuring it, so that a derived
30303928aee4356845252ac6b662d5c72c29903813eJake Slack     * XmlConfiguration class may inject default values.
30403928aee4356845252ac6b662d5c72c29903813eJake Slack     * @param object
30503928aee4356845252ac6b662d5c72c29903813eJake Slack     */
30603928aee4356845252ac6b662d5c72c29903813eJake Slack    public void initializeDefaults(Object object)
30703928aee4356845252ac6b662d5c72c29903813eJake Slack    {
30803928aee4356845252ac6b662d5c72c29903813eJake Slack    }
30903928aee4356845252ac6b662d5c72c29903813eJake Slack
31003928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
31103928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
31203928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
31303928aee4356845252ac6b662d5c72c29903813eJake Slack    private static class JettyXmlConfiguration implements ConfigurationProcessor
31403928aee4356845252ac6b662d5c72c29903813eJake Slack    {
31503928aee4356845252ac6b662d5c72c29903813eJake Slack        XmlParser.Node _root;
31603928aee4356845252ac6b662d5c72c29903813eJake Slack        XmlConfiguration _configuration;
31703928aee4356845252ac6b662d5c72c29903813eJake Slack
31803928aee4356845252ac6b662d5c72c29903813eJake Slack        public void init(URL url, XmlParser.Node root, XmlConfiguration configuration)
31903928aee4356845252ac6b662d5c72c29903813eJake Slack        {
32003928aee4356845252ac6b662d5c72c29903813eJake Slack            _root=root;
32103928aee4356845252ac6b662d5c72c29903813eJake Slack            _configuration=configuration;
32203928aee4356845252ac6b662d5c72c29903813eJake Slack        }
32303928aee4356845252ac6b662d5c72c29903813eJake Slack
32403928aee4356845252ac6b662d5c72c29903813eJake Slack        /* ------------------------------------------------------------ */
32503928aee4356845252ac6b662d5c72c29903813eJake Slack        public Object configure(Object obj) throws Exception
32603928aee4356845252ac6b662d5c72c29903813eJake Slack        {
32703928aee4356845252ac6b662d5c72c29903813eJake Slack            // Check the class of the object
32803928aee4356845252ac6b662d5c72c29903813eJake Slack            Class<?> oClass = nodeClass(_root);
32903928aee4356845252ac6b662d5c72c29903813eJake Slack            if (oClass != null && !oClass.isInstance(obj))
33003928aee4356845252ac6b662d5c72c29903813eJake Slack            {
33103928aee4356845252ac6b662d5c72c29903813eJake Slack                String loaders = (oClass.getClassLoader()==obj.getClass().getClassLoader())?"":"Object Class and type Class are from different loaders.";
33203928aee4356845252ac6b662d5c72c29903813eJake Slack                throw new IllegalArgumentException("Object of class '"+obj.getClass().getCanonicalName()+"' is not of type '" + oClass.getCanonicalName()+"'. "+loaders);
33303928aee4356845252ac6b662d5c72c29903813eJake Slack            }
33403928aee4356845252ac6b662d5c72c29903813eJake Slack            configure(obj,_root,0);
33503928aee4356845252ac6b662d5c72c29903813eJake Slack            return obj;
33603928aee4356845252ac6b662d5c72c29903813eJake Slack        }
33703928aee4356845252ac6b662d5c72c29903813eJake Slack
33803928aee4356845252ac6b662d5c72c29903813eJake Slack        /* ------------------------------------------------------------ */
33903928aee4356845252ac6b662d5c72c29903813eJake Slack        public Object configure() throws Exception
34003928aee4356845252ac6b662d5c72c29903813eJake Slack        {
34103928aee4356845252ac6b662d5c72c29903813eJake Slack            Class<?> oClass = nodeClass(_root);
34203928aee4356845252ac6b662d5c72c29903813eJake Slack
34303928aee4356845252ac6b662d5c72c29903813eJake Slack            String id = _root.getAttribute("id");
34403928aee4356845252ac6b662d5c72c29903813eJake Slack            Object obj = id == null?null:_configuration.getIdMap().get(id);
34503928aee4356845252ac6b662d5c72c29903813eJake Slack
34603928aee4356845252ac6b662d5c72c29903813eJake Slack            if (obj == null && oClass != null)
34703928aee4356845252ac6b662d5c72c29903813eJake Slack            {
34803928aee4356845252ac6b662d5c72c29903813eJake Slack                obj = oClass.newInstance();
34903928aee4356845252ac6b662d5c72c29903813eJake Slack                _configuration.initializeDefaults(obj);
35003928aee4356845252ac6b662d5c72c29903813eJake Slack            }
35103928aee4356845252ac6b662d5c72c29903813eJake Slack
35203928aee4356845252ac6b662d5c72c29903813eJake Slack            if (oClass != null && !oClass.isInstance(obj))
35303928aee4356845252ac6b662d5c72c29903813eJake Slack                throw new ClassCastException(oClass.toString());
35403928aee4356845252ac6b662d5c72c29903813eJake Slack
35503928aee4356845252ac6b662d5c72c29903813eJake Slack            configure(obj,_root,0);
35603928aee4356845252ac6b662d5c72c29903813eJake Slack            return obj;
35703928aee4356845252ac6b662d5c72c29903813eJake Slack        }
35803928aee4356845252ac6b662d5c72c29903813eJake Slack
35903928aee4356845252ac6b662d5c72c29903813eJake Slack        /* ------------------------------------------------------------ */
36003928aee4356845252ac6b662d5c72c29903813eJake Slack        private static Class<?> nodeClass(XmlParser.Node node) throws ClassNotFoundException
36103928aee4356845252ac6b662d5c72c29903813eJake Slack        {
36203928aee4356845252ac6b662d5c72c29903813eJake Slack            String className = node.getAttribute("class");
36303928aee4356845252ac6b662d5c72c29903813eJake Slack            if (className == null)
36403928aee4356845252ac6b662d5c72c29903813eJake Slack                return null;
36503928aee4356845252ac6b662d5c72c29903813eJake Slack
36603928aee4356845252ac6b662d5c72c29903813eJake Slack            return Loader.loadClass(XmlConfiguration.class,className,true);
36703928aee4356845252ac6b662d5c72c29903813eJake Slack        }
36803928aee4356845252ac6b662d5c72c29903813eJake Slack
36903928aee4356845252ac6b662d5c72c29903813eJake Slack        /* ------------------------------------------------------------ */
37003928aee4356845252ac6b662d5c72c29903813eJake Slack        /**
37103928aee4356845252ac6b662d5c72c29903813eJake Slack         * Recursive configuration routine.
37203928aee4356845252ac6b662d5c72c29903813eJake Slack         * This method applies the nested Set, Put, Call, etc. elements to the given object.
37303928aee4356845252ac6b662d5c72c29903813eJake Slack         *
37403928aee4356845252ac6b662d5c72c29903813eJake Slack         * @param obj the object to configure
37503928aee4356845252ac6b662d5c72c29903813eJake Slack         * @param cfg the XML nodes of the configuration
37603928aee4356845252ac6b662d5c72c29903813eJake Slack         * @param i the index of the XML nodes
37703928aee4356845252ac6b662d5c72c29903813eJake Slack         * @throws Exception if the configuration fails
37803928aee4356845252ac6b662d5c72c29903813eJake Slack         */
37903928aee4356845252ac6b662d5c72c29903813eJake Slack        public void configure(Object obj, XmlParser.Node cfg, int i) throws Exception
38003928aee4356845252ac6b662d5c72c29903813eJake Slack        {
38103928aee4356845252ac6b662d5c72c29903813eJake Slack            String id = cfg.getAttribute("id");
38203928aee4356845252ac6b662d5c72c29903813eJake Slack            if (id != null)
38303928aee4356845252ac6b662d5c72c29903813eJake Slack                _configuration.getIdMap().put(id,obj);
38403928aee4356845252ac6b662d5c72c29903813eJake Slack
38503928aee4356845252ac6b662d5c72c29903813eJake Slack            for (; i < cfg.size(); i++)
38603928aee4356845252ac6b662d5c72c29903813eJake Slack            {
38703928aee4356845252ac6b662d5c72c29903813eJake Slack                Object o = cfg.get(i);
38803928aee4356845252ac6b662d5c72c29903813eJake Slack                if (o instanceof String)
38903928aee4356845252ac6b662d5c72c29903813eJake Slack                    continue;
39003928aee4356845252ac6b662d5c72c29903813eJake Slack                XmlParser.Node node = (XmlParser.Node)o;
39103928aee4356845252ac6b662d5c72c29903813eJake Slack
39203928aee4356845252ac6b662d5c72c29903813eJake Slack                try
39303928aee4356845252ac6b662d5c72c29903813eJake Slack                {
39403928aee4356845252ac6b662d5c72c29903813eJake Slack                    String tag = node.getTag();
39503928aee4356845252ac6b662d5c72c29903813eJake Slack                    if ("Set".equals(tag))
39603928aee4356845252ac6b662d5c72c29903813eJake Slack                        set(obj,node);
39703928aee4356845252ac6b662d5c72c29903813eJake Slack                    else if ("Put".equals(tag))
39803928aee4356845252ac6b662d5c72c29903813eJake Slack                        put(obj,node);
39903928aee4356845252ac6b662d5c72c29903813eJake Slack                    else if ("Call".equals(tag))
40003928aee4356845252ac6b662d5c72c29903813eJake Slack                        call(obj,node);
40103928aee4356845252ac6b662d5c72c29903813eJake Slack                    else if ("Get".equals(tag))
40203928aee4356845252ac6b662d5c72c29903813eJake Slack                        get(obj,node);
40303928aee4356845252ac6b662d5c72c29903813eJake Slack                    else if ("New".equals(tag))
40403928aee4356845252ac6b662d5c72c29903813eJake Slack                        newObj(obj,node);
40503928aee4356845252ac6b662d5c72c29903813eJake Slack                    else if ("Array".equals(tag))
40603928aee4356845252ac6b662d5c72c29903813eJake Slack                        newArray(obj,node);
40703928aee4356845252ac6b662d5c72c29903813eJake Slack                    else if ("Ref".equals(tag))
40803928aee4356845252ac6b662d5c72c29903813eJake Slack                        refObj(obj,node);
40903928aee4356845252ac6b662d5c72c29903813eJake Slack                    else if ("Property".equals(tag))
41003928aee4356845252ac6b662d5c72c29903813eJake Slack                        propertyObj(node);
41103928aee4356845252ac6b662d5c72c29903813eJake Slack                    else
41203928aee4356845252ac6b662d5c72c29903813eJake Slack                        throw new IllegalStateException("Unknown tag: " + tag);
41303928aee4356845252ac6b662d5c72c29903813eJake Slack                }
41403928aee4356845252ac6b662d5c72c29903813eJake Slack                catch (Exception e)
41503928aee4356845252ac6b662d5c72c29903813eJake Slack                {
41603928aee4356845252ac6b662d5c72c29903813eJake Slack                    LOG.warn("Config error at " + node,e.toString());
41703928aee4356845252ac6b662d5c72c29903813eJake Slack                    throw e;
41803928aee4356845252ac6b662d5c72c29903813eJake Slack                }
41903928aee4356845252ac6b662d5c72c29903813eJake Slack            }
42003928aee4356845252ac6b662d5c72c29903813eJake Slack        }
42103928aee4356845252ac6b662d5c72c29903813eJake Slack
42203928aee4356845252ac6b662d5c72c29903813eJake Slack        /* ------------------------------------------------------------ */
42303928aee4356845252ac6b662d5c72c29903813eJake Slack        /*
42403928aee4356845252ac6b662d5c72c29903813eJake Slack         * 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.
42503928aee4356845252ac6b662d5c72c29903813eJake Slack         * 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
42603928aee4356845252ac6b662d5c72c29903813eJake Slack         * construct a suitable value from original value. @param obj
42703928aee4356845252ac6b662d5c72c29903813eJake Slack         *
42803928aee4356845252ac6b662d5c72c29903813eJake Slack         * @param node
42903928aee4356845252ac6b662d5c72c29903813eJake Slack         */
43003928aee4356845252ac6b662d5c72c29903813eJake Slack        private void set(Object obj, XmlParser.Node node) throws Exception
43103928aee4356845252ac6b662d5c72c29903813eJake Slack        {
43203928aee4356845252ac6b662d5c72c29903813eJake Slack            String attr = node.getAttribute("name");
43303928aee4356845252ac6b662d5c72c29903813eJake Slack            String name = "set" + attr.substring(0,1).toUpperCase(Locale.ENGLISH) + attr.substring(1);
43403928aee4356845252ac6b662d5c72c29903813eJake Slack            Object value = value(obj,node);
43503928aee4356845252ac6b662d5c72c29903813eJake Slack            Object[] arg =
43603928aee4356845252ac6b662d5c72c29903813eJake Slack            { value };
43703928aee4356845252ac6b662d5c72c29903813eJake Slack
43803928aee4356845252ac6b662d5c72c29903813eJake Slack            Class<?> oClass = nodeClass(node);
43903928aee4356845252ac6b662d5c72c29903813eJake Slack            if (oClass != null)
44003928aee4356845252ac6b662d5c72c29903813eJake Slack                obj = null;
44103928aee4356845252ac6b662d5c72c29903813eJake Slack            else
44203928aee4356845252ac6b662d5c72c29903813eJake Slack                oClass = obj.getClass();
44303928aee4356845252ac6b662d5c72c29903813eJake Slack
44403928aee4356845252ac6b662d5c72c29903813eJake Slack            Class<?>[] vClass =
44503928aee4356845252ac6b662d5c72c29903813eJake Slack            { Object.class };
44603928aee4356845252ac6b662d5c72c29903813eJake Slack            if (value != null)
44703928aee4356845252ac6b662d5c72c29903813eJake Slack                vClass[0] = value.getClass();
44803928aee4356845252ac6b662d5c72c29903813eJake Slack
44903928aee4356845252ac6b662d5c72c29903813eJake Slack            if (LOG.isDebugEnabled())
45003928aee4356845252ac6b662d5c72c29903813eJake Slack                LOG.debug("XML " + (obj != null?obj.toString():oClass.getName()) + "." + name + "(" + value + ")");
45103928aee4356845252ac6b662d5c72c29903813eJake Slack
45203928aee4356845252ac6b662d5c72c29903813eJake Slack            // Try for trivial match
45303928aee4356845252ac6b662d5c72c29903813eJake Slack            try
45403928aee4356845252ac6b662d5c72c29903813eJake Slack            {
45503928aee4356845252ac6b662d5c72c29903813eJake Slack                Method set = oClass.getMethod(name,vClass);
45603928aee4356845252ac6b662d5c72c29903813eJake Slack                set.invoke(obj,arg);
45703928aee4356845252ac6b662d5c72c29903813eJake Slack                return;
45803928aee4356845252ac6b662d5c72c29903813eJake Slack            }
45903928aee4356845252ac6b662d5c72c29903813eJake Slack            catch (IllegalArgumentException e)
46003928aee4356845252ac6b662d5c72c29903813eJake Slack            {
46103928aee4356845252ac6b662d5c72c29903813eJake Slack                LOG.ignore(e);
46203928aee4356845252ac6b662d5c72c29903813eJake Slack            }
46303928aee4356845252ac6b662d5c72c29903813eJake Slack            catch (IllegalAccessException e)
46403928aee4356845252ac6b662d5c72c29903813eJake Slack            {
46503928aee4356845252ac6b662d5c72c29903813eJake Slack                LOG.ignore(e);
46603928aee4356845252ac6b662d5c72c29903813eJake Slack            }
46703928aee4356845252ac6b662d5c72c29903813eJake Slack            catch (NoSuchMethodException e)
46803928aee4356845252ac6b662d5c72c29903813eJake Slack            {
46903928aee4356845252ac6b662d5c72c29903813eJake Slack                LOG.ignore(e);
47003928aee4356845252ac6b662d5c72c29903813eJake Slack            }
47103928aee4356845252ac6b662d5c72c29903813eJake Slack
47203928aee4356845252ac6b662d5c72c29903813eJake Slack            // Try for native match
47303928aee4356845252ac6b662d5c72c29903813eJake Slack            try
47403928aee4356845252ac6b662d5c72c29903813eJake Slack            {
47503928aee4356845252ac6b662d5c72c29903813eJake Slack                Field type = vClass[0].getField("TYPE");
47603928aee4356845252ac6b662d5c72c29903813eJake Slack                vClass[0] = (Class<?>)type.get(null);
47703928aee4356845252ac6b662d5c72c29903813eJake Slack                Method set = oClass.getMethod(name,vClass);
47803928aee4356845252ac6b662d5c72c29903813eJake Slack                set.invoke(obj,arg);
47903928aee4356845252ac6b662d5c72c29903813eJake Slack                return;
48003928aee4356845252ac6b662d5c72c29903813eJake Slack            }
48103928aee4356845252ac6b662d5c72c29903813eJake Slack            catch (NoSuchFieldException e)
48203928aee4356845252ac6b662d5c72c29903813eJake Slack            {
48303928aee4356845252ac6b662d5c72c29903813eJake Slack                LOG.ignore(e);
48403928aee4356845252ac6b662d5c72c29903813eJake Slack            }
48503928aee4356845252ac6b662d5c72c29903813eJake Slack            catch (IllegalArgumentException e)
48603928aee4356845252ac6b662d5c72c29903813eJake Slack            {
48703928aee4356845252ac6b662d5c72c29903813eJake Slack                LOG.ignore(e);
48803928aee4356845252ac6b662d5c72c29903813eJake Slack            }
48903928aee4356845252ac6b662d5c72c29903813eJake Slack            catch (IllegalAccessException e)
49003928aee4356845252ac6b662d5c72c29903813eJake Slack            {
49103928aee4356845252ac6b662d5c72c29903813eJake Slack                LOG.ignore(e);
49203928aee4356845252ac6b662d5c72c29903813eJake Slack            }
49303928aee4356845252ac6b662d5c72c29903813eJake Slack            catch (NoSuchMethodException e)
49403928aee4356845252ac6b662d5c72c29903813eJake Slack            {
49503928aee4356845252ac6b662d5c72c29903813eJake Slack                LOG.ignore(e);
49603928aee4356845252ac6b662d5c72c29903813eJake Slack            }
49703928aee4356845252ac6b662d5c72c29903813eJake Slack
49803928aee4356845252ac6b662d5c72c29903813eJake Slack            // Try a field
49903928aee4356845252ac6b662d5c72c29903813eJake Slack            try
50003928aee4356845252ac6b662d5c72c29903813eJake Slack            {
50103928aee4356845252ac6b662d5c72c29903813eJake Slack                Field field = oClass.getField(attr);
50203928aee4356845252ac6b662d5c72c29903813eJake Slack                if (Modifier.isPublic(field.getModifiers()))
50303928aee4356845252ac6b662d5c72c29903813eJake Slack                {
50403928aee4356845252ac6b662d5c72c29903813eJake Slack                    field.set(obj,value);
50503928aee4356845252ac6b662d5c72c29903813eJake Slack                    return;
50603928aee4356845252ac6b662d5c72c29903813eJake Slack                }
50703928aee4356845252ac6b662d5c72c29903813eJake Slack            }
50803928aee4356845252ac6b662d5c72c29903813eJake Slack            catch (NoSuchFieldException e)
50903928aee4356845252ac6b662d5c72c29903813eJake Slack            {
51003928aee4356845252ac6b662d5c72c29903813eJake Slack                LOG.ignore(e);
51103928aee4356845252ac6b662d5c72c29903813eJake Slack            }
51203928aee4356845252ac6b662d5c72c29903813eJake Slack
51303928aee4356845252ac6b662d5c72c29903813eJake Slack            // Search for a match by trying all the set methods
51403928aee4356845252ac6b662d5c72c29903813eJake Slack            Method[] sets = oClass.getMethods();
51503928aee4356845252ac6b662d5c72c29903813eJake Slack            Method set = null;
51603928aee4356845252ac6b662d5c72c29903813eJake Slack            for (int s = 0; sets != null && s < sets.length; s++)
51703928aee4356845252ac6b662d5c72c29903813eJake Slack            {
51803928aee4356845252ac6b662d5c72c29903813eJake Slack                Class<?>[] paramTypes = sets[s].getParameterTypes();
51903928aee4356845252ac6b662d5c72c29903813eJake Slack                if (name.equals(sets[s].getName()) && paramTypes.length == 1)
52003928aee4356845252ac6b662d5c72c29903813eJake Slack                {
52103928aee4356845252ac6b662d5c72c29903813eJake Slack
52203928aee4356845252ac6b662d5c72c29903813eJake Slack                    // lets try it
52303928aee4356845252ac6b662d5c72c29903813eJake Slack                    try
52403928aee4356845252ac6b662d5c72c29903813eJake Slack                    {
52503928aee4356845252ac6b662d5c72c29903813eJake Slack                        set = sets[s];
52603928aee4356845252ac6b662d5c72c29903813eJake Slack                        sets[s].invoke(obj,arg);
52703928aee4356845252ac6b662d5c72c29903813eJake Slack                        return;
52803928aee4356845252ac6b662d5c72c29903813eJake Slack                    }
52903928aee4356845252ac6b662d5c72c29903813eJake Slack                    catch (IllegalArgumentException e)
53003928aee4356845252ac6b662d5c72c29903813eJake Slack                    {
53103928aee4356845252ac6b662d5c72c29903813eJake Slack                        LOG.ignore(e);
53203928aee4356845252ac6b662d5c72c29903813eJake Slack                    }
53303928aee4356845252ac6b662d5c72c29903813eJake Slack                    catch (IllegalAccessException e)
53403928aee4356845252ac6b662d5c72c29903813eJake Slack                    {
53503928aee4356845252ac6b662d5c72c29903813eJake Slack                        LOG.ignore(e);
53603928aee4356845252ac6b662d5c72c29903813eJake Slack                    }
53703928aee4356845252ac6b662d5c72c29903813eJake Slack
53803928aee4356845252ac6b662d5c72c29903813eJake Slack                    try
53903928aee4356845252ac6b662d5c72c29903813eJake Slack                    {
54003928aee4356845252ac6b662d5c72c29903813eJake Slack                        for (Class<?> c : __supportedCollections)
54103928aee4356845252ac6b662d5c72c29903813eJake Slack                            if (paramTypes[0].isAssignableFrom(c))
54203928aee4356845252ac6b662d5c72c29903813eJake Slack                            {
54303928aee4356845252ac6b662d5c72c29903813eJake Slack                                sets[s].invoke(obj,convertArrayToCollection(value,c));
54403928aee4356845252ac6b662d5c72c29903813eJake Slack                                return;
54503928aee4356845252ac6b662d5c72c29903813eJake Slack                            }
54603928aee4356845252ac6b662d5c72c29903813eJake Slack                    }
54703928aee4356845252ac6b662d5c72c29903813eJake Slack                    catch (IllegalAccessException e)
54803928aee4356845252ac6b662d5c72c29903813eJake Slack                    {
54903928aee4356845252ac6b662d5c72c29903813eJake Slack                        LOG.ignore(e);
55003928aee4356845252ac6b662d5c72c29903813eJake Slack                    }
55103928aee4356845252ac6b662d5c72c29903813eJake Slack                }
55203928aee4356845252ac6b662d5c72c29903813eJake Slack            }
55303928aee4356845252ac6b662d5c72c29903813eJake Slack
55403928aee4356845252ac6b662d5c72c29903813eJake Slack            // Try converting the arg to the last set found.
55503928aee4356845252ac6b662d5c72c29903813eJake Slack            if (set != null)
55603928aee4356845252ac6b662d5c72c29903813eJake Slack            {
55703928aee4356845252ac6b662d5c72c29903813eJake Slack                try
55803928aee4356845252ac6b662d5c72c29903813eJake Slack                {
55903928aee4356845252ac6b662d5c72c29903813eJake Slack                    Class<?> sClass = set.getParameterTypes()[0];
56003928aee4356845252ac6b662d5c72c29903813eJake Slack                    if (sClass.isPrimitive())
56103928aee4356845252ac6b662d5c72c29903813eJake Slack                    {
56203928aee4356845252ac6b662d5c72c29903813eJake Slack                        for (int t = 0; t < __primitives.length; t++)
56303928aee4356845252ac6b662d5c72c29903813eJake Slack                        {
56403928aee4356845252ac6b662d5c72c29903813eJake Slack                            if (sClass.equals(__primitives[t]))
56503928aee4356845252ac6b662d5c72c29903813eJake Slack                            {
56603928aee4356845252ac6b662d5c72c29903813eJake Slack                                sClass = __primitiveHolders[t];
56703928aee4356845252ac6b662d5c72c29903813eJake Slack                                break;
56803928aee4356845252ac6b662d5c72c29903813eJake Slack                            }
56903928aee4356845252ac6b662d5c72c29903813eJake Slack                        }
57003928aee4356845252ac6b662d5c72c29903813eJake Slack                    }
57103928aee4356845252ac6b662d5c72c29903813eJake Slack                    Constructor<?> cons = sClass.getConstructor(vClass);
57203928aee4356845252ac6b662d5c72c29903813eJake Slack                    arg[0] = cons.newInstance(arg);
57303928aee4356845252ac6b662d5c72c29903813eJake Slack                    _configuration.initializeDefaults(arg[0]);
57403928aee4356845252ac6b662d5c72c29903813eJake Slack                    set.invoke(obj,arg);
57503928aee4356845252ac6b662d5c72c29903813eJake Slack                    return;
57603928aee4356845252ac6b662d5c72c29903813eJake Slack                }
57703928aee4356845252ac6b662d5c72c29903813eJake Slack                catch (NoSuchMethodException e)
57803928aee4356845252ac6b662d5c72c29903813eJake Slack                {
57903928aee4356845252ac6b662d5c72c29903813eJake Slack                    LOG.ignore(e);
58003928aee4356845252ac6b662d5c72c29903813eJake Slack                }
58103928aee4356845252ac6b662d5c72c29903813eJake Slack                catch (IllegalAccessException e)
58203928aee4356845252ac6b662d5c72c29903813eJake Slack                {
58303928aee4356845252ac6b662d5c72c29903813eJake Slack                    LOG.ignore(e);
58403928aee4356845252ac6b662d5c72c29903813eJake Slack                }
58503928aee4356845252ac6b662d5c72c29903813eJake Slack                catch (InstantiationException e)
58603928aee4356845252ac6b662d5c72c29903813eJake Slack                {
58703928aee4356845252ac6b662d5c72c29903813eJake Slack                    LOG.ignore(e);
58803928aee4356845252ac6b662d5c72c29903813eJake Slack                }
58903928aee4356845252ac6b662d5c72c29903813eJake Slack            }
59003928aee4356845252ac6b662d5c72c29903813eJake Slack
59103928aee4356845252ac6b662d5c72c29903813eJake Slack            // No Joy
59203928aee4356845252ac6b662d5c72c29903813eJake Slack            throw new NoSuchMethodException(oClass + "." + name + "(" + vClass[0] + ")");
59303928aee4356845252ac6b662d5c72c29903813eJake Slack        }
59403928aee4356845252ac6b662d5c72c29903813eJake Slack
59503928aee4356845252ac6b662d5c72c29903813eJake Slack        /**
59603928aee4356845252ac6b662d5c72c29903813eJake Slack         * @param array the array to convert
59703928aee4356845252ac6b662d5c72c29903813eJake Slack         * @param collectionType the desired collection type
59803928aee4356845252ac6b662d5c72c29903813eJake Slack         * @return a collection of the desired type if the array can be converted
59903928aee4356845252ac6b662d5c72c29903813eJake Slack         */
60003928aee4356845252ac6b662d5c72c29903813eJake Slack        private static Collection<?> convertArrayToCollection(Object array, Class<?> collectionType)
60103928aee4356845252ac6b662d5c72c29903813eJake Slack        {
60203928aee4356845252ac6b662d5c72c29903813eJake Slack            Collection<?> collection = null;
60303928aee4356845252ac6b662d5c72c29903813eJake Slack            if (array.getClass().isArray())
60403928aee4356845252ac6b662d5c72c29903813eJake Slack            {
60503928aee4356845252ac6b662d5c72c29903813eJake Slack                if (collectionType.isAssignableFrom(ArrayList.class))
60603928aee4356845252ac6b662d5c72c29903813eJake Slack                    collection = convertArrayToArrayList(array);
60703928aee4356845252ac6b662d5c72c29903813eJake Slack                else if (collectionType.isAssignableFrom(HashSet.class))
60803928aee4356845252ac6b662d5c72c29903813eJake Slack                    collection = new HashSet<Object>(convertArrayToArrayList(array));
60903928aee4356845252ac6b662d5c72c29903813eJake Slack                else if (collectionType.isAssignableFrom(ArrayQueue.class))
61003928aee4356845252ac6b662d5c72c29903813eJake Slack                {
61103928aee4356845252ac6b662d5c72c29903813eJake Slack                    ArrayQueue<Object> q= new ArrayQueue<Object>();
61203928aee4356845252ac6b662d5c72c29903813eJake Slack                    q.addAll(convertArrayToArrayList(array));
61303928aee4356845252ac6b662d5c72c29903813eJake Slack                    collection=q;
61403928aee4356845252ac6b662d5c72c29903813eJake Slack                }
61503928aee4356845252ac6b662d5c72c29903813eJake Slack            }
61603928aee4356845252ac6b662d5c72c29903813eJake Slack            if (collection==null)
61703928aee4356845252ac6b662d5c72c29903813eJake Slack                throw new IllegalArgumentException("Can't convert \"" + array.getClass() + "\" to " + collectionType);
61803928aee4356845252ac6b662d5c72c29903813eJake Slack            return collection;
61903928aee4356845252ac6b662d5c72c29903813eJake Slack        }
62003928aee4356845252ac6b662d5c72c29903813eJake Slack
62103928aee4356845252ac6b662d5c72c29903813eJake Slack        /* ------------------------------------------------------------ */
62203928aee4356845252ac6b662d5c72c29903813eJake Slack        private static ArrayList<Object> convertArrayToArrayList(Object array)
62303928aee4356845252ac6b662d5c72c29903813eJake Slack        {
62403928aee4356845252ac6b662d5c72c29903813eJake Slack            int length = Array.getLength(array);
62503928aee4356845252ac6b662d5c72c29903813eJake Slack            ArrayList<Object> list = new ArrayList<Object>(length);
62603928aee4356845252ac6b662d5c72c29903813eJake Slack            for (int i = 0; i < length; i++)
62703928aee4356845252ac6b662d5c72c29903813eJake Slack                list.add(Array.get(array,i));
62803928aee4356845252ac6b662d5c72c29903813eJake Slack            return list;
62903928aee4356845252ac6b662d5c72c29903813eJake Slack        }
63003928aee4356845252ac6b662d5c72c29903813eJake Slack
63103928aee4356845252ac6b662d5c72c29903813eJake Slack        /* ------------------------------------------------------------ */
63203928aee4356845252ac6b662d5c72c29903813eJake Slack        /*
63303928aee4356845252ac6b662d5c72c29903813eJake Slack         * Call a put method.
63403928aee4356845252ac6b662d5c72c29903813eJake Slack         *
63503928aee4356845252ac6b662d5c72c29903813eJake Slack         * @param obj @param node
63603928aee4356845252ac6b662d5c72c29903813eJake Slack         */
63703928aee4356845252ac6b662d5c72c29903813eJake Slack        private void put(Object obj, XmlParser.Node node) throws Exception
63803928aee4356845252ac6b662d5c72c29903813eJake Slack        {
63903928aee4356845252ac6b662d5c72c29903813eJake Slack            if (!(obj instanceof Map))
64003928aee4356845252ac6b662d5c72c29903813eJake Slack                throw new IllegalArgumentException("Object for put is not a Map: " + obj);
64103928aee4356845252ac6b662d5c72c29903813eJake Slack            @SuppressWarnings("unchecked")
64203928aee4356845252ac6b662d5c72c29903813eJake Slack            Map<Object, Object> map = (Map<Object, Object>)obj;
64303928aee4356845252ac6b662d5c72c29903813eJake Slack
64403928aee4356845252ac6b662d5c72c29903813eJake Slack            String name = node.getAttribute("name");
64503928aee4356845252ac6b662d5c72c29903813eJake Slack            Object value = value(obj,node);
64603928aee4356845252ac6b662d5c72c29903813eJake Slack            map.put(name,value);
64703928aee4356845252ac6b662d5c72c29903813eJake Slack            if (LOG.isDebugEnabled())
64803928aee4356845252ac6b662d5c72c29903813eJake Slack                LOG.debug("XML " + obj + ".put(" + name + "," + value + ")");
64903928aee4356845252ac6b662d5c72c29903813eJake Slack        }
65003928aee4356845252ac6b662d5c72c29903813eJake Slack
65103928aee4356845252ac6b662d5c72c29903813eJake Slack        /* ------------------------------------------------------------ */
65203928aee4356845252ac6b662d5c72c29903813eJake Slack        /*
65303928aee4356845252ac6b662d5c72c29903813eJake Slack         * 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
65403928aee4356845252ac6b662d5c72c29903813eJake Slack         *
65503928aee4356845252ac6b662d5c72c29903813eJake Slack         * @return @exception Exception
65603928aee4356845252ac6b662d5c72c29903813eJake Slack         */
65703928aee4356845252ac6b662d5c72c29903813eJake Slack        private Object get(Object obj, XmlParser.Node node) throws Exception
65803928aee4356845252ac6b662d5c72c29903813eJake Slack        {
65903928aee4356845252ac6b662d5c72c29903813eJake Slack            Class<?> oClass = nodeClass(node);
66003928aee4356845252ac6b662d5c72c29903813eJake Slack            if (oClass != null)
66103928aee4356845252ac6b662d5c72c29903813eJake Slack                obj = null;
66203928aee4356845252ac6b662d5c72c29903813eJake Slack            else
66303928aee4356845252ac6b662d5c72c29903813eJake Slack                oClass = obj.getClass();
66403928aee4356845252ac6b662d5c72c29903813eJake Slack
66503928aee4356845252ac6b662d5c72c29903813eJake Slack            String name = node.getAttribute("name");
66603928aee4356845252ac6b662d5c72c29903813eJake Slack            String id = node.getAttribute("id");
66703928aee4356845252ac6b662d5c72c29903813eJake Slack            if (LOG.isDebugEnabled())
66803928aee4356845252ac6b662d5c72c29903813eJake Slack                LOG.debug("XML get " + name);
66903928aee4356845252ac6b662d5c72c29903813eJake Slack
67003928aee4356845252ac6b662d5c72c29903813eJake Slack            try
67103928aee4356845252ac6b662d5c72c29903813eJake Slack            {
67203928aee4356845252ac6b662d5c72c29903813eJake Slack                // try calling a getXxx method.
67303928aee4356845252ac6b662d5c72c29903813eJake Slack                Method method = oClass.getMethod("get" + name.substring(0,1).toUpperCase(Locale.ENGLISH) + name.substring(1),(java.lang.Class[])null);
67403928aee4356845252ac6b662d5c72c29903813eJake Slack                obj = method.invoke(obj,(java.lang.Object[])null);
67503928aee4356845252ac6b662d5c72c29903813eJake Slack                configure(obj,node,0);
67603928aee4356845252ac6b662d5c72c29903813eJake Slack            }
67703928aee4356845252ac6b662d5c72c29903813eJake Slack            catch (NoSuchMethodException nsme)
67803928aee4356845252ac6b662d5c72c29903813eJake Slack            {
67903928aee4356845252ac6b662d5c72c29903813eJake Slack                try
68003928aee4356845252ac6b662d5c72c29903813eJake Slack                {
68103928aee4356845252ac6b662d5c72c29903813eJake Slack                    Field field = oClass.getField(name);
68203928aee4356845252ac6b662d5c72c29903813eJake Slack                    obj = field.get(obj);
68303928aee4356845252ac6b662d5c72c29903813eJake Slack                    configure(obj,node,0);
68403928aee4356845252ac6b662d5c72c29903813eJake Slack                }
68503928aee4356845252ac6b662d5c72c29903813eJake Slack                catch (NoSuchFieldException nsfe)
68603928aee4356845252ac6b662d5c72c29903813eJake Slack                {
68703928aee4356845252ac6b662d5c72c29903813eJake Slack                    throw nsme;
68803928aee4356845252ac6b662d5c72c29903813eJake Slack                }
68903928aee4356845252ac6b662d5c72c29903813eJake Slack            }
69003928aee4356845252ac6b662d5c72c29903813eJake Slack            if (id != null)
69103928aee4356845252ac6b662d5c72c29903813eJake Slack                _configuration.getIdMap().put(id,obj);
69203928aee4356845252ac6b662d5c72c29903813eJake Slack            return obj;
69303928aee4356845252ac6b662d5c72c29903813eJake Slack        }
69403928aee4356845252ac6b662d5c72c29903813eJake Slack
69503928aee4356845252ac6b662d5c72c29903813eJake Slack        /* ------------------------------------------------------------ */
69603928aee4356845252ac6b662d5c72c29903813eJake Slack        /*
69703928aee4356845252ac6b662d5c72c29903813eJake Slack         * 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
69803928aee4356845252ac6b662d5c72c29903813eJake Slack         * 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
69903928aee4356845252ac6b662d5c72c29903813eJake Slack         * class. i.e. we ignore any static methods in superclasses. @param obj
70003928aee4356845252ac6b662d5c72c29903813eJake Slack         *
70103928aee4356845252ac6b662d5c72c29903813eJake Slack         * @param node @return @exception Exception
70203928aee4356845252ac6b662d5c72c29903813eJake Slack         */
70303928aee4356845252ac6b662d5c72c29903813eJake Slack        private Object call(Object obj, XmlParser.Node node) throws Exception
70403928aee4356845252ac6b662d5c72c29903813eJake Slack        {
70503928aee4356845252ac6b662d5c72c29903813eJake Slack            String id = node.getAttribute("id");
70603928aee4356845252ac6b662d5c72c29903813eJake Slack            Class<?> oClass = nodeClass(node);
70703928aee4356845252ac6b662d5c72c29903813eJake Slack            if (oClass != null)
70803928aee4356845252ac6b662d5c72c29903813eJake Slack                obj = null;
70903928aee4356845252ac6b662d5c72c29903813eJake Slack            else if (obj != null)
71003928aee4356845252ac6b662d5c72c29903813eJake Slack                oClass = obj.getClass();
71103928aee4356845252ac6b662d5c72c29903813eJake Slack            if (oClass == null)
71203928aee4356845252ac6b662d5c72c29903813eJake Slack                throw new IllegalArgumentException(node.toString());
71303928aee4356845252ac6b662d5c72c29903813eJake Slack
71403928aee4356845252ac6b662d5c72c29903813eJake Slack            int size = 0;
71503928aee4356845252ac6b662d5c72c29903813eJake Slack            int argi = node.size();
71603928aee4356845252ac6b662d5c72c29903813eJake Slack            for (int i = 0; i < node.size(); i++)
71703928aee4356845252ac6b662d5c72c29903813eJake Slack            {
71803928aee4356845252ac6b662d5c72c29903813eJake Slack                Object o = node.get(i);
71903928aee4356845252ac6b662d5c72c29903813eJake Slack                if (o instanceof String)
72003928aee4356845252ac6b662d5c72c29903813eJake Slack                    continue;
72103928aee4356845252ac6b662d5c72c29903813eJake Slack                if (!((XmlParser.Node)o).getTag().equals("Arg"))
72203928aee4356845252ac6b662d5c72c29903813eJake Slack                {
72303928aee4356845252ac6b662d5c72c29903813eJake Slack                    argi = i;
72403928aee4356845252ac6b662d5c72c29903813eJake Slack                    break;
72503928aee4356845252ac6b662d5c72c29903813eJake Slack                }
72603928aee4356845252ac6b662d5c72c29903813eJake Slack                size++;
72703928aee4356845252ac6b662d5c72c29903813eJake Slack            }
72803928aee4356845252ac6b662d5c72c29903813eJake Slack
72903928aee4356845252ac6b662d5c72c29903813eJake Slack            Object[] arg = new Object[size];
73003928aee4356845252ac6b662d5c72c29903813eJake Slack            for (int i = 0, j = 0; j < size; i++)
73103928aee4356845252ac6b662d5c72c29903813eJake Slack            {
73203928aee4356845252ac6b662d5c72c29903813eJake Slack                Object o = node.get(i);
73303928aee4356845252ac6b662d5c72c29903813eJake Slack                if (o instanceof String)
73403928aee4356845252ac6b662d5c72c29903813eJake Slack                    continue;
73503928aee4356845252ac6b662d5c72c29903813eJake Slack                arg[j++] = value(obj,(XmlParser.Node)o);
73603928aee4356845252ac6b662d5c72c29903813eJake Slack            }
73703928aee4356845252ac6b662d5c72c29903813eJake Slack
73803928aee4356845252ac6b662d5c72c29903813eJake Slack            String method = node.getAttribute("name");
73903928aee4356845252ac6b662d5c72c29903813eJake Slack            if (LOG.isDebugEnabled())
74003928aee4356845252ac6b662d5c72c29903813eJake Slack                LOG.debug("XML call " + method);
74103928aee4356845252ac6b662d5c72c29903813eJake Slack
74203928aee4356845252ac6b662d5c72c29903813eJake Slack            try
74303928aee4356845252ac6b662d5c72c29903813eJake Slack            {
74403928aee4356845252ac6b662d5c72c29903813eJake Slack                Object n= TypeUtil.call(oClass,method,obj,arg);
74503928aee4356845252ac6b662d5c72c29903813eJake Slack                if (id != null)
74603928aee4356845252ac6b662d5c72c29903813eJake Slack                    _configuration.getIdMap().put(id,n);
74703928aee4356845252ac6b662d5c72c29903813eJake Slack                configure(n,node,argi);
74803928aee4356845252ac6b662d5c72c29903813eJake Slack                return n;
74903928aee4356845252ac6b662d5c72c29903813eJake Slack            }
75003928aee4356845252ac6b662d5c72c29903813eJake Slack            catch (NoSuchMethodException e)
75103928aee4356845252ac6b662d5c72c29903813eJake Slack            {
75203928aee4356845252ac6b662d5c72c29903813eJake Slack                IllegalStateException ise = new IllegalStateException("No Method: " + node + " on " + oClass);
75303928aee4356845252ac6b662d5c72c29903813eJake Slack                ise.initCause(e);
75403928aee4356845252ac6b662d5c72c29903813eJake Slack                throw ise;
75503928aee4356845252ac6b662d5c72c29903813eJake Slack            }
75603928aee4356845252ac6b662d5c72c29903813eJake Slack
75703928aee4356845252ac6b662d5c72c29903813eJake Slack        }
75803928aee4356845252ac6b662d5c72c29903813eJake Slack
75903928aee4356845252ac6b662d5c72c29903813eJake Slack        /* ------------------------------------------------------------ */
76003928aee4356845252ac6b662d5c72c29903813eJake Slack        /*
76103928aee4356845252ac6b662d5c72c29903813eJake Slack         * Create a new value object.
76203928aee4356845252ac6b662d5c72c29903813eJake Slack         *
76303928aee4356845252ac6b662d5c72c29903813eJake Slack         * @param obj @param node @return @exception Exception
76403928aee4356845252ac6b662d5c72c29903813eJake Slack         */
76503928aee4356845252ac6b662d5c72c29903813eJake Slack        private Object newObj(Object obj, XmlParser.Node node) throws Exception
76603928aee4356845252ac6b662d5c72c29903813eJake Slack        {
76703928aee4356845252ac6b662d5c72c29903813eJake Slack            Class<?> oClass = nodeClass(node);
76803928aee4356845252ac6b662d5c72c29903813eJake Slack            String id = node.getAttribute("id");
76903928aee4356845252ac6b662d5c72c29903813eJake Slack            int size = 0;
77003928aee4356845252ac6b662d5c72c29903813eJake Slack            int argi = node.size();
77103928aee4356845252ac6b662d5c72c29903813eJake Slack            for (int i = 0; i < node.size(); i++)
77203928aee4356845252ac6b662d5c72c29903813eJake Slack            {
77303928aee4356845252ac6b662d5c72c29903813eJake Slack                Object o = node.get(i);
77403928aee4356845252ac6b662d5c72c29903813eJake Slack                if (o instanceof String)
77503928aee4356845252ac6b662d5c72c29903813eJake Slack                    continue;
77603928aee4356845252ac6b662d5c72c29903813eJake Slack                if (!((XmlParser.Node)o).getTag().equals("Arg"))
77703928aee4356845252ac6b662d5c72c29903813eJake Slack                {
77803928aee4356845252ac6b662d5c72c29903813eJake Slack                    argi = i;
77903928aee4356845252ac6b662d5c72c29903813eJake Slack                    break;
78003928aee4356845252ac6b662d5c72c29903813eJake Slack                }
78103928aee4356845252ac6b662d5c72c29903813eJake Slack                size++;
78203928aee4356845252ac6b662d5c72c29903813eJake Slack            }
78303928aee4356845252ac6b662d5c72c29903813eJake Slack
78403928aee4356845252ac6b662d5c72c29903813eJake Slack            Object[] arg = new Object[size];
78503928aee4356845252ac6b662d5c72c29903813eJake Slack            for (int i = 0, j = 0; j < size; i++)
78603928aee4356845252ac6b662d5c72c29903813eJake Slack            {
78703928aee4356845252ac6b662d5c72c29903813eJake Slack                Object o = node.get(i);
78803928aee4356845252ac6b662d5c72c29903813eJake Slack                if (o instanceof String)
78903928aee4356845252ac6b662d5c72c29903813eJake Slack                    continue;
79003928aee4356845252ac6b662d5c72c29903813eJake Slack                arg[j++] = value(obj,(XmlParser.Node)o);
79103928aee4356845252ac6b662d5c72c29903813eJake Slack            }
79203928aee4356845252ac6b662d5c72c29903813eJake Slack
79303928aee4356845252ac6b662d5c72c29903813eJake Slack            if (LOG.isDebugEnabled())
79403928aee4356845252ac6b662d5c72c29903813eJake Slack                LOG.debug("XML new " + oClass);
79503928aee4356845252ac6b662d5c72c29903813eJake Slack
79603928aee4356845252ac6b662d5c72c29903813eJake Slack            // Lets just try all constructors for now
79703928aee4356845252ac6b662d5c72c29903813eJake Slack            Constructor<?>[] constructors = oClass.getConstructors();
79803928aee4356845252ac6b662d5c72c29903813eJake Slack            for (int c = 0; constructors != null && c < constructors.length; c++)
79903928aee4356845252ac6b662d5c72c29903813eJake Slack            {
80003928aee4356845252ac6b662d5c72c29903813eJake Slack                if (constructors[c].getParameterTypes().length != size)
80103928aee4356845252ac6b662d5c72c29903813eJake Slack                    continue;
80203928aee4356845252ac6b662d5c72c29903813eJake Slack
80303928aee4356845252ac6b662d5c72c29903813eJake Slack                Object n = null;
80403928aee4356845252ac6b662d5c72c29903813eJake Slack                boolean called = false;
80503928aee4356845252ac6b662d5c72c29903813eJake Slack                try
80603928aee4356845252ac6b662d5c72c29903813eJake Slack                {
80703928aee4356845252ac6b662d5c72c29903813eJake Slack                    n = constructors[c].newInstance(arg);
80803928aee4356845252ac6b662d5c72c29903813eJake Slack                    _configuration.initializeDefaults(n);
80903928aee4356845252ac6b662d5c72c29903813eJake Slack                    called = true;
81003928aee4356845252ac6b662d5c72c29903813eJake Slack                }
81103928aee4356845252ac6b662d5c72c29903813eJake Slack                catch (IllegalAccessException e)
81203928aee4356845252ac6b662d5c72c29903813eJake Slack                {
81303928aee4356845252ac6b662d5c72c29903813eJake Slack                    LOG.ignore(e);
81403928aee4356845252ac6b662d5c72c29903813eJake Slack                }
81503928aee4356845252ac6b662d5c72c29903813eJake Slack                catch (InstantiationException e)
81603928aee4356845252ac6b662d5c72c29903813eJake Slack                {
81703928aee4356845252ac6b662d5c72c29903813eJake Slack                    LOG.ignore(e);
81803928aee4356845252ac6b662d5c72c29903813eJake Slack                }
81903928aee4356845252ac6b662d5c72c29903813eJake Slack                catch (IllegalArgumentException e)
82003928aee4356845252ac6b662d5c72c29903813eJake Slack                {
82103928aee4356845252ac6b662d5c72c29903813eJake Slack                    LOG.ignore(e);
82203928aee4356845252ac6b662d5c72c29903813eJake Slack                }
82303928aee4356845252ac6b662d5c72c29903813eJake Slack                if (called)
82403928aee4356845252ac6b662d5c72c29903813eJake Slack                {
82503928aee4356845252ac6b662d5c72c29903813eJake Slack                    if (id != null)
82603928aee4356845252ac6b662d5c72c29903813eJake Slack                        _configuration.getIdMap().put(id,n);
82703928aee4356845252ac6b662d5c72c29903813eJake Slack                    configure(n,node,argi);
82803928aee4356845252ac6b662d5c72c29903813eJake Slack                    return n;
82903928aee4356845252ac6b662d5c72c29903813eJake Slack                }
83003928aee4356845252ac6b662d5c72c29903813eJake Slack            }
83103928aee4356845252ac6b662d5c72c29903813eJake Slack
83203928aee4356845252ac6b662d5c72c29903813eJake Slack            throw new IllegalStateException("No Constructor: " + node + " on " + obj);
83303928aee4356845252ac6b662d5c72c29903813eJake Slack        }
83403928aee4356845252ac6b662d5c72c29903813eJake Slack
83503928aee4356845252ac6b662d5c72c29903813eJake Slack        /* ------------------------------------------------------------ */
83603928aee4356845252ac6b662d5c72c29903813eJake Slack        /*
83703928aee4356845252ac6b662d5c72c29903813eJake Slack         * Reference an id value object.
83803928aee4356845252ac6b662d5c72c29903813eJake Slack         *
83903928aee4356845252ac6b662d5c72c29903813eJake Slack         * @param obj @param node @return @exception NoSuchMethodException @exception ClassNotFoundException @exception InvocationTargetException
84003928aee4356845252ac6b662d5c72c29903813eJake Slack         */
84103928aee4356845252ac6b662d5c72c29903813eJake Slack        private Object refObj(Object obj, XmlParser.Node node) throws Exception
84203928aee4356845252ac6b662d5c72c29903813eJake Slack        {
84303928aee4356845252ac6b662d5c72c29903813eJake Slack            String id = node.getAttribute("id");
84403928aee4356845252ac6b662d5c72c29903813eJake Slack            obj = _configuration.getIdMap().get(id);
84503928aee4356845252ac6b662d5c72c29903813eJake Slack            if (obj == null)
84603928aee4356845252ac6b662d5c72c29903813eJake Slack                throw new IllegalStateException("No object for id=" + id);
84703928aee4356845252ac6b662d5c72c29903813eJake Slack            configure(obj,node,0);
84803928aee4356845252ac6b662d5c72c29903813eJake Slack            return obj;
84903928aee4356845252ac6b662d5c72c29903813eJake Slack        }
85003928aee4356845252ac6b662d5c72c29903813eJake Slack
85103928aee4356845252ac6b662d5c72c29903813eJake Slack        /* ------------------------------------------------------------ */
85203928aee4356845252ac6b662d5c72c29903813eJake Slack        /*
85303928aee4356845252ac6b662d5c72c29903813eJake Slack         * Create a new array object.
85403928aee4356845252ac6b662d5c72c29903813eJake Slack         */
85503928aee4356845252ac6b662d5c72c29903813eJake Slack        private Object newArray(Object obj, XmlParser.Node node) throws Exception
85603928aee4356845252ac6b662d5c72c29903813eJake Slack        {
85703928aee4356845252ac6b662d5c72c29903813eJake Slack
85803928aee4356845252ac6b662d5c72c29903813eJake Slack            // Get the type
85903928aee4356845252ac6b662d5c72c29903813eJake Slack            Class<?> aClass = java.lang.Object.class;
86003928aee4356845252ac6b662d5c72c29903813eJake Slack            String type = node.getAttribute("type");
86103928aee4356845252ac6b662d5c72c29903813eJake Slack            final String id = node.getAttribute("id");
86203928aee4356845252ac6b662d5c72c29903813eJake Slack            if (type != null)
86303928aee4356845252ac6b662d5c72c29903813eJake Slack            {
86403928aee4356845252ac6b662d5c72c29903813eJake Slack                aClass = TypeUtil.fromName(type);
86503928aee4356845252ac6b662d5c72c29903813eJake Slack                if (aClass == null)
86603928aee4356845252ac6b662d5c72c29903813eJake Slack                {
86703928aee4356845252ac6b662d5c72c29903813eJake Slack                    if ("String".equals(type))
86803928aee4356845252ac6b662d5c72c29903813eJake Slack                        aClass = java.lang.String.class;
86903928aee4356845252ac6b662d5c72c29903813eJake Slack                    else if ("URL".equals(type))
87003928aee4356845252ac6b662d5c72c29903813eJake Slack                        aClass = java.net.URL.class;
87103928aee4356845252ac6b662d5c72c29903813eJake Slack                    else if ("InetAddress".equals(type))
87203928aee4356845252ac6b662d5c72c29903813eJake Slack                        aClass = java.net.InetAddress.class;
87303928aee4356845252ac6b662d5c72c29903813eJake Slack                    else
87403928aee4356845252ac6b662d5c72c29903813eJake Slack                        aClass = Loader.loadClass(XmlConfiguration.class,type,true);
87503928aee4356845252ac6b662d5c72c29903813eJake Slack                }
87603928aee4356845252ac6b662d5c72c29903813eJake Slack            }
87703928aee4356845252ac6b662d5c72c29903813eJake Slack
87803928aee4356845252ac6b662d5c72c29903813eJake Slack            Object al = null;
87903928aee4356845252ac6b662d5c72c29903813eJake Slack
88003928aee4356845252ac6b662d5c72c29903813eJake Slack            for (Object nodeObject : node)
88103928aee4356845252ac6b662d5c72c29903813eJake Slack            {
88203928aee4356845252ac6b662d5c72c29903813eJake Slack                XmlParser.Node item = (Node)nodeObject;
88303928aee4356845252ac6b662d5c72c29903813eJake Slack                String nid = item.getAttribute("id");
88403928aee4356845252ac6b662d5c72c29903813eJake Slack                Object v = value(obj,item);
88503928aee4356845252ac6b662d5c72c29903813eJake Slack                al = LazyList.add(al,(v == null && aClass.isPrimitive())?0:v);
88603928aee4356845252ac6b662d5c72c29903813eJake Slack                if (nid != null)
88703928aee4356845252ac6b662d5c72c29903813eJake Slack                    _configuration.getIdMap().put(nid,v);
88803928aee4356845252ac6b662d5c72c29903813eJake Slack            }
88903928aee4356845252ac6b662d5c72c29903813eJake Slack
89003928aee4356845252ac6b662d5c72c29903813eJake Slack            Object array = LazyList.toArray(al,aClass);
89103928aee4356845252ac6b662d5c72c29903813eJake Slack            if (id != null)
89203928aee4356845252ac6b662d5c72c29903813eJake Slack                _configuration.getIdMap().put(id,array);
89303928aee4356845252ac6b662d5c72c29903813eJake Slack            return array;
89403928aee4356845252ac6b662d5c72c29903813eJake Slack        }
89503928aee4356845252ac6b662d5c72c29903813eJake Slack
89603928aee4356845252ac6b662d5c72c29903813eJake Slack        /* ------------------------------------------------------------ */
89703928aee4356845252ac6b662d5c72c29903813eJake Slack        /*
89803928aee4356845252ac6b662d5c72c29903813eJake Slack         * Create a new map object.
89903928aee4356845252ac6b662d5c72c29903813eJake Slack         */
90003928aee4356845252ac6b662d5c72c29903813eJake Slack        private Object newMap(Object obj, XmlParser.Node node) throws Exception
90103928aee4356845252ac6b662d5c72c29903813eJake Slack        {
90203928aee4356845252ac6b662d5c72c29903813eJake Slack            String id = node.getAttribute("id");
90303928aee4356845252ac6b662d5c72c29903813eJake Slack
90403928aee4356845252ac6b662d5c72c29903813eJake Slack            Map<Object, Object> map = new HashMap<Object, Object>();
90503928aee4356845252ac6b662d5c72c29903813eJake Slack            if (id != null)
90603928aee4356845252ac6b662d5c72c29903813eJake Slack                _configuration.getIdMap().put(id,map);
90703928aee4356845252ac6b662d5c72c29903813eJake Slack
90803928aee4356845252ac6b662d5c72c29903813eJake Slack            for (Object o : node)
90903928aee4356845252ac6b662d5c72c29903813eJake Slack            {
91003928aee4356845252ac6b662d5c72c29903813eJake Slack                if (o instanceof String)
91103928aee4356845252ac6b662d5c72c29903813eJake Slack                    continue;
91203928aee4356845252ac6b662d5c72c29903813eJake Slack                XmlParser.Node entry = (XmlParser.Node)o;
91303928aee4356845252ac6b662d5c72c29903813eJake Slack                if (!entry.getTag().equals("Entry"))
91403928aee4356845252ac6b662d5c72c29903813eJake Slack                    throw new IllegalStateException("Not an Entry");
91503928aee4356845252ac6b662d5c72c29903813eJake Slack
91603928aee4356845252ac6b662d5c72c29903813eJake Slack                XmlParser.Node key = null;
91703928aee4356845252ac6b662d5c72c29903813eJake Slack                XmlParser.Node value = null;
91803928aee4356845252ac6b662d5c72c29903813eJake Slack
91903928aee4356845252ac6b662d5c72c29903813eJake Slack                for (Object object : entry)
92003928aee4356845252ac6b662d5c72c29903813eJake Slack                {
92103928aee4356845252ac6b662d5c72c29903813eJake Slack                    if (object instanceof String)
92203928aee4356845252ac6b662d5c72c29903813eJake Slack                        continue;
92303928aee4356845252ac6b662d5c72c29903813eJake Slack                    XmlParser.Node item = (XmlParser.Node)object;
92403928aee4356845252ac6b662d5c72c29903813eJake Slack                    if (!item.getTag().equals("Item"))
92503928aee4356845252ac6b662d5c72c29903813eJake Slack                        throw new IllegalStateException("Not an Item");
92603928aee4356845252ac6b662d5c72c29903813eJake Slack                    if (key == null)
92703928aee4356845252ac6b662d5c72c29903813eJake Slack                        key = item;
92803928aee4356845252ac6b662d5c72c29903813eJake Slack                    else
92903928aee4356845252ac6b662d5c72c29903813eJake Slack                        value = item;
93003928aee4356845252ac6b662d5c72c29903813eJake Slack                }
93103928aee4356845252ac6b662d5c72c29903813eJake Slack
93203928aee4356845252ac6b662d5c72c29903813eJake Slack                if (key == null || value == null)
93303928aee4356845252ac6b662d5c72c29903813eJake Slack                    throw new IllegalStateException("Missing Item in Entry");
93403928aee4356845252ac6b662d5c72c29903813eJake Slack                String kid = key.getAttribute("id");
93503928aee4356845252ac6b662d5c72c29903813eJake Slack                String vid = value.getAttribute("id");
93603928aee4356845252ac6b662d5c72c29903813eJake Slack
93703928aee4356845252ac6b662d5c72c29903813eJake Slack                Object k = value(obj,key);
93803928aee4356845252ac6b662d5c72c29903813eJake Slack                Object v = value(obj,value);
93903928aee4356845252ac6b662d5c72c29903813eJake Slack                map.put(k,v);
94003928aee4356845252ac6b662d5c72c29903813eJake Slack
94103928aee4356845252ac6b662d5c72c29903813eJake Slack                if (kid != null)
94203928aee4356845252ac6b662d5c72c29903813eJake Slack                    _configuration.getIdMap().put(kid,k);
94303928aee4356845252ac6b662d5c72c29903813eJake Slack                if (vid != null)
94403928aee4356845252ac6b662d5c72c29903813eJake Slack                    _configuration.getIdMap().put(vid,v);
94503928aee4356845252ac6b662d5c72c29903813eJake Slack            }
94603928aee4356845252ac6b662d5c72c29903813eJake Slack
94703928aee4356845252ac6b662d5c72c29903813eJake Slack            return map;
94803928aee4356845252ac6b662d5c72c29903813eJake Slack        }
94903928aee4356845252ac6b662d5c72c29903813eJake Slack
95003928aee4356845252ac6b662d5c72c29903813eJake Slack        /* ------------------------------------------------------------ */
95103928aee4356845252ac6b662d5c72c29903813eJake Slack        /*
95203928aee4356845252ac6b662d5c72c29903813eJake Slack         * Get a Property.
95303928aee4356845252ac6b662d5c72c29903813eJake Slack         *
95403928aee4356845252ac6b662d5c72c29903813eJake Slack         * @param node
95503928aee4356845252ac6b662d5c72c29903813eJake Slack         * @return
95603928aee4356845252ac6b662d5c72c29903813eJake Slack         * @exception Exception
95703928aee4356845252ac6b662d5c72c29903813eJake Slack         */
95803928aee4356845252ac6b662d5c72c29903813eJake Slack        private Object propertyObj(XmlParser.Node node) throws Exception
95903928aee4356845252ac6b662d5c72c29903813eJake Slack        {
96003928aee4356845252ac6b662d5c72c29903813eJake Slack            String id = node.getAttribute("id");
96103928aee4356845252ac6b662d5c72c29903813eJake Slack            String name = node.getAttribute("name");
96203928aee4356845252ac6b662d5c72c29903813eJake Slack            String defaultValue = node.getAttribute("default");
96303928aee4356845252ac6b662d5c72c29903813eJake Slack            Object prop;
96403928aee4356845252ac6b662d5c72c29903813eJake Slack            Map<String,String> property_map=_configuration.getProperties();
96503928aee4356845252ac6b662d5c72c29903813eJake Slack            if (property_map != null && property_map.containsKey(name))
96603928aee4356845252ac6b662d5c72c29903813eJake Slack                prop = property_map.get(name);
96703928aee4356845252ac6b662d5c72c29903813eJake Slack            else
96803928aee4356845252ac6b662d5c72c29903813eJake Slack                prop = defaultValue;
96903928aee4356845252ac6b662d5c72c29903813eJake Slack            if (id != null)
97003928aee4356845252ac6b662d5c72c29903813eJake Slack                _configuration.getIdMap().put(id,prop);
97103928aee4356845252ac6b662d5c72c29903813eJake Slack            if (prop != null)
97203928aee4356845252ac6b662d5c72c29903813eJake Slack                configure(prop,node,0);
97303928aee4356845252ac6b662d5c72c29903813eJake Slack            return prop;
97403928aee4356845252ac6b662d5c72c29903813eJake Slack        }
97503928aee4356845252ac6b662d5c72c29903813eJake Slack
97603928aee4356845252ac6b662d5c72c29903813eJake Slack
97703928aee4356845252ac6b662d5c72c29903813eJake Slack        /* ------------------------------------------------------------ */
97803928aee4356845252ac6b662d5c72c29903813eJake Slack        /*
97903928aee4356845252ac6b662d5c72c29903813eJake Slack         * 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
98003928aee4356845252ac6b662d5c72c29903813eJake Slack         * are added as strings before being converted to any specified type. @param node
98103928aee4356845252ac6b662d5c72c29903813eJake Slack         */
98203928aee4356845252ac6b662d5c72c29903813eJake Slack        private Object value(Object obj, XmlParser.Node node) throws Exception
98303928aee4356845252ac6b662d5c72c29903813eJake Slack        {
98403928aee4356845252ac6b662d5c72c29903813eJake Slack            Object value;
98503928aee4356845252ac6b662d5c72c29903813eJake Slack
98603928aee4356845252ac6b662d5c72c29903813eJake Slack            // Get the type
98703928aee4356845252ac6b662d5c72c29903813eJake Slack            String type = node.getAttribute("type");
98803928aee4356845252ac6b662d5c72c29903813eJake Slack
98903928aee4356845252ac6b662d5c72c29903813eJake Slack            // Try a ref lookup
99003928aee4356845252ac6b662d5c72c29903813eJake Slack            String ref = node.getAttribute("ref");
99103928aee4356845252ac6b662d5c72c29903813eJake Slack            if (ref != null)
99203928aee4356845252ac6b662d5c72c29903813eJake Slack            {
99303928aee4356845252ac6b662d5c72c29903813eJake Slack                value = _configuration.getIdMap().get(ref);
99403928aee4356845252ac6b662d5c72c29903813eJake Slack            }
99503928aee4356845252ac6b662d5c72c29903813eJake Slack            else
99603928aee4356845252ac6b662d5c72c29903813eJake Slack            {
99703928aee4356845252ac6b662d5c72c29903813eJake Slack                // handle trivial case
99803928aee4356845252ac6b662d5c72c29903813eJake Slack                if (node.size() == 0)
99903928aee4356845252ac6b662d5c72c29903813eJake Slack                {
100003928aee4356845252ac6b662d5c72c29903813eJake Slack                    if ("String".equals(type))
100103928aee4356845252ac6b662d5c72c29903813eJake Slack                        return "";
100203928aee4356845252ac6b662d5c72c29903813eJake Slack                    return null;
100303928aee4356845252ac6b662d5c72c29903813eJake Slack                }
100403928aee4356845252ac6b662d5c72c29903813eJake Slack
100503928aee4356845252ac6b662d5c72c29903813eJake Slack                // Trim values
100603928aee4356845252ac6b662d5c72c29903813eJake Slack                int first = 0;
100703928aee4356845252ac6b662d5c72c29903813eJake Slack                int last = node.size() - 1;
100803928aee4356845252ac6b662d5c72c29903813eJake Slack
100903928aee4356845252ac6b662d5c72c29903813eJake Slack                // Handle default trim type
101003928aee4356845252ac6b662d5c72c29903813eJake Slack                if (type == null || !"String".equals(type))
101103928aee4356845252ac6b662d5c72c29903813eJake Slack                {
101203928aee4356845252ac6b662d5c72c29903813eJake Slack                    // Skip leading white
101303928aee4356845252ac6b662d5c72c29903813eJake Slack                    Object item;
101403928aee4356845252ac6b662d5c72c29903813eJake Slack                    while (first <= last)
101503928aee4356845252ac6b662d5c72c29903813eJake Slack                    {
101603928aee4356845252ac6b662d5c72c29903813eJake Slack                        item = node.get(first);
101703928aee4356845252ac6b662d5c72c29903813eJake Slack                        if (!(item instanceof String))
101803928aee4356845252ac6b662d5c72c29903813eJake Slack                            break;
101903928aee4356845252ac6b662d5c72c29903813eJake Slack                        item = ((String)item).trim();
102003928aee4356845252ac6b662d5c72c29903813eJake Slack                        if (((String)item).length() > 0)
102103928aee4356845252ac6b662d5c72c29903813eJake Slack                            break;
102203928aee4356845252ac6b662d5c72c29903813eJake Slack                        first++;
102303928aee4356845252ac6b662d5c72c29903813eJake Slack                    }
102403928aee4356845252ac6b662d5c72c29903813eJake Slack
102503928aee4356845252ac6b662d5c72c29903813eJake Slack                    // Skip trailing white
102603928aee4356845252ac6b662d5c72c29903813eJake Slack                    while (first < last)
102703928aee4356845252ac6b662d5c72c29903813eJake Slack                    {
102803928aee4356845252ac6b662d5c72c29903813eJake Slack                        item = node.get(last);
102903928aee4356845252ac6b662d5c72c29903813eJake Slack                        if (!(item instanceof String))
103003928aee4356845252ac6b662d5c72c29903813eJake Slack                            break;
103103928aee4356845252ac6b662d5c72c29903813eJake Slack                        item = ((String)item).trim();
103203928aee4356845252ac6b662d5c72c29903813eJake Slack                        if (((String)item).length() > 0)
103303928aee4356845252ac6b662d5c72c29903813eJake Slack                            break;
103403928aee4356845252ac6b662d5c72c29903813eJake Slack                        last--;
103503928aee4356845252ac6b662d5c72c29903813eJake Slack                    }
103603928aee4356845252ac6b662d5c72c29903813eJake Slack
103703928aee4356845252ac6b662d5c72c29903813eJake Slack                    // All white, so return null
103803928aee4356845252ac6b662d5c72c29903813eJake Slack                    if (first > last)
103903928aee4356845252ac6b662d5c72c29903813eJake Slack                        return null;
104003928aee4356845252ac6b662d5c72c29903813eJake Slack                }
104103928aee4356845252ac6b662d5c72c29903813eJake Slack
104203928aee4356845252ac6b662d5c72c29903813eJake Slack                if (first == last)
104303928aee4356845252ac6b662d5c72c29903813eJake Slack                    // Single Item value
104403928aee4356845252ac6b662d5c72c29903813eJake Slack                    value = itemValue(obj,node.get(first));
104503928aee4356845252ac6b662d5c72c29903813eJake Slack                else
104603928aee4356845252ac6b662d5c72c29903813eJake Slack                {
104703928aee4356845252ac6b662d5c72c29903813eJake Slack                    // Get the multiple items as a single string
104803928aee4356845252ac6b662d5c72c29903813eJake Slack                    StringBuilder buf = new StringBuilder();
104903928aee4356845252ac6b662d5c72c29903813eJake Slack                    for (int i = first; i <= last; i++)
105003928aee4356845252ac6b662d5c72c29903813eJake Slack                    {
105103928aee4356845252ac6b662d5c72c29903813eJake Slack                        Object item = node.get(i);
105203928aee4356845252ac6b662d5c72c29903813eJake Slack                        buf.append(itemValue(obj,item));
105303928aee4356845252ac6b662d5c72c29903813eJake Slack                    }
105403928aee4356845252ac6b662d5c72c29903813eJake Slack                    value = buf.toString();
105503928aee4356845252ac6b662d5c72c29903813eJake Slack                }
105603928aee4356845252ac6b662d5c72c29903813eJake Slack            }
105703928aee4356845252ac6b662d5c72c29903813eJake Slack
105803928aee4356845252ac6b662d5c72c29903813eJake Slack            // Untyped or unknown
105903928aee4356845252ac6b662d5c72c29903813eJake Slack            if (value == null)
106003928aee4356845252ac6b662d5c72c29903813eJake Slack            {
106103928aee4356845252ac6b662d5c72c29903813eJake Slack                if ("String".equals(type))
106203928aee4356845252ac6b662d5c72c29903813eJake Slack                    return "";
106303928aee4356845252ac6b662d5c72c29903813eJake Slack                return null;
106403928aee4356845252ac6b662d5c72c29903813eJake Slack            }
106503928aee4356845252ac6b662d5c72c29903813eJake Slack
106603928aee4356845252ac6b662d5c72c29903813eJake Slack            // Try to type the object
106703928aee4356845252ac6b662d5c72c29903813eJake Slack            if (type == null)
106803928aee4356845252ac6b662d5c72c29903813eJake Slack            {
106903928aee4356845252ac6b662d5c72c29903813eJake Slack                if (value instanceof String)
107003928aee4356845252ac6b662d5c72c29903813eJake Slack                    return ((String)value).trim();
107103928aee4356845252ac6b662d5c72c29903813eJake Slack                return value;
107203928aee4356845252ac6b662d5c72c29903813eJake Slack            }
107303928aee4356845252ac6b662d5c72c29903813eJake Slack
107403928aee4356845252ac6b662d5c72c29903813eJake Slack            if (isTypeMatchingClass(type,String.class))
107503928aee4356845252ac6b662d5c72c29903813eJake Slack                return value.toString();
107603928aee4356845252ac6b662d5c72c29903813eJake Slack
107703928aee4356845252ac6b662d5c72c29903813eJake Slack            Class<?> pClass = TypeUtil.fromName(type);
107803928aee4356845252ac6b662d5c72c29903813eJake Slack            if (pClass != null)
107903928aee4356845252ac6b662d5c72c29903813eJake Slack                return TypeUtil.valueOf(pClass,value.toString());
108003928aee4356845252ac6b662d5c72c29903813eJake Slack
108103928aee4356845252ac6b662d5c72c29903813eJake Slack            if (isTypeMatchingClass(type,URL.class))
108203928aee4356845252ac6b662d5c72c29903813eJake Slack            {
108303928aee4356845252ac6b662d5c72c29903813eJake Slack                if (value instanceof URL)
108403928aee4356845252ac6b662d5c72c29903813eJake Slack                    return value;
108503928aee4356845252ac6b662d5c72c29903813eJake Slack                try
108603928aee4356845252ac6b662d5c72c29903813eJake Slack                {
108703928aee4356845252ac6b662d5c72c29903813eJake Slack                    return new URL(value.toString());
108803928aee4356845252ac6b662d5c72c29903813eJake Slack                }
108903928aee4356845252ac6b662d5c72c29903813eJake Slack                catch (MalformedURLException e)
109003928aee4356845252ac6b662d5c72c29903813eJake Slack                {
109103928aee4356845252ac6b662d5c72c29903813eJake Slack                    throw new InvocationTargetException(e);
109203928aee4356845252ac6b662d5c72c29903813eJake Slack                }
109303928aee4356845252ac6b662d5c72c29903813eJake Slack            }
109403928aee4356845252ac6b662d5c72c29903813eJake Slack
109503928aee4356845252ac6b662d5c72c29903813eJake Slack            if (isTypeMatchingClass(type,InetAddress.class))
109603928aee4356845252ac6b662d5c72c29903813eJake Slack            {
109703928aee4356845252ac6b662d5c72c29903813eJake Slack                if (value instanceof InetAddress)
109803928aee4356845252ac6b662d5c72c29903813eJake Slack                    return value;
109903928aee4356845252ac6b662d5c72c29903813eJake Slack                try
110003928aee4356845252ac6b662d5c72c29903813eJake Slack                {
110103928aee4356845252ac6b662d5c72c29903813eJake Slack                    return InetAddress.getByName(value.toString());
110203928aee4356845252ac6b662d5c72c29903813eJake Slack                }
110303928aee4356845252ac6b662d5c72c29903813eJake Slack                catch (UnknownHostException e)
110403928aee4356845252ac6b662d5c72c29903813eJake Slack                {
110503928aee4356845252ac6b662d5c72c29903813eJake Slack                    throw new InvocationTargetException(e);
110603928aee4356845252ac6b662d5c72c29903813eJake Slack                }
110703928aee4356845252ac6b662d5c72c29903813eJake Slack            }
110803928aee4356845252ac6b662d5c72c29903813eJake Slack
110903928aee4356845252ac6b662d5c72c29903813eJake Slack            for (Class<?> collectionClass : __supportedCollections)
111003928aee4356845252ac6b662d5c72c29903813eJake Slack            {
111103928aee4356845252ac6b662d5c72c29903813eJake Slack                if (isTypeMatchingClass(type,collectionClass))
111203928aee4356845252ac6b662d5c72c29903813eJake Slack                    return convertArrayToCollection(value,collectionClass);
111303928aee4356845252ac6b662d5c72c29903813eJake Slack            }
111403928aee4356845252ac6b662d5c72c29903813eJake Slack
111503928aee4356845252ac6b662d5c72c29903813eJake Slack            throw new IllegalStateException("Unknown type " + type);
111603928aee4356845252ac6b662d5c72c29903813eJake Slack        }
111703928aee4356845252ac6b662d5c72c29903813eJake Slack
111803928aee4356845252ac6b662d5c72c29903813eJake Slack        /* ------------------------------------------------------------ */
111903928aee4356845252ac6b662d5c72c29903813eJake Slack        private static boolean isTypeMatchingClass(String type, Class<?> classToMatch)
112003928aee4356845252ac6b662d5c72c29903813eJake Slack        {
112103928aee4356845252ac6b662d5c72c29903813eJake Slack            return classToMatch.getSimpleName().equalsIgnoreCase(type) || classToMatch.getName().equals(type);
112203928aee4356845252ac6b662d5c72c29903813eJake Slack        }
112303928aee4356845252ac6b662d5c72c29903813eJake Slack
112403928aee4356845252ac6b662d5c72c29903813eJake Slack        /* ------------------------------------------------------------ */
112503928aee4356845252ac6b662d5c72c29903813eJake Slack        /*
112603928aee4356845252ac6b662d5c72c29903813eJake Slack         * Get the value of a single element. @param obj @param item @return @exception Exception
112703928aee4356845252ac6b662d5c72c29903813eJake Slack         */
112803928aee4356845252ac6b662d5c72c29903813eJake Slack        private Object itemValue(Object obj, Object item) throws Exception
112903928aee4356845252ac6b662d5c72c29903813eJake Slack        {
113003928aee4356845252ac6b662d5c72c29903813eJake Slack            // String value
113103928aee4356845252ac6b662d5c72c29903813eJake Slack            if (item instanceof String)
113203928aee4356845252ac6b662d5c72c29903813eJake Slack                return item;
113303928aee4356845252ac6b662d5c72c29903813eJake Slack
113403928aee4356845252ac6b662d5c72c29903813eJake Slack            XmlParser.Node node = (XmlParser.Node)item;
113503928aee4356845252ac6b662d5c72c29903813eJake Slack            String tag = node.getTag();
113603928aee4356845252ac6b662d5c72c29903813eJake Slack            if ("Call".equals(tag))
113703928aee4356845252ac6b662d5c72c29903813eJake Slack                return call(obj,node);
113803928aee4356845252ac6b662d5c72c29903813eJake Slack            if ("Get".equals(tag))
113903928aee4356845252ac6b662d5c72c29903813eJake Slack                return get(obj,node);
114003928aee4356845252ac6b662d5c72c29903813eJake Slack            if ("New".equals(tag))
114103928aee4356845252ac6b662d5c72c29903813eJake Slack                return newObj(obj,node);
114203928aee4356845252ac6b662d5c72c29903813eJake Slack            if ("Ref".equals(tag))
114303928aee4356845252ac6b662d5c72c29903813eJake Slack                return refObj(obj,node);
114403928aee4356845252ac6b662d5c72c29903813eJake Slack            if ("Array".equals(tag))
114503928aee4356845252ac6b662d5c72c29903813eJake Slack                return newArray(obj,node);
114603928aee4356845252ac6b662d5c72c29903813eJake Slack            if ("Map".equals(tag))
114703928aee4356845252ac6b662d5c72c29903813eJake Slack                return newMap(obj,node);
114803928aee4356845252ac6b662d5c72c29903813eJake Slack            if ("Property".equals(tag))
114903928aee4356845252ac6b662d5c72c29903813eJake Slack                return propertyObj(node);
115003928aee4356845252ac6b662d5c72c29903813eJake Slack
115103928aee4356845252ac6b662d5c72c29903813eJake Slack            if ("SystemProperty".equals(tag))
115203928aee4356845252ac6b662d5c72c29903813eJake Slack            {
115303928aee4356845252ac6b662d5c72c29903813eJake Slack                String name = node.getAttribute("name");
115403928aee4356845252ac6b662d5c72c29903813eJake Slack                String defaultValue = node.getAttribute("default");
115503928aee4356845252ac6b662d5c72c29903813eJake Slack                return System.getProperty(name,defaultValue);
115603928aee4356845252ac6b662d5c72c29903813eJake Slack            }
115703928aee4356845252ac6b662d5c72c29903813eJake Slack
115803928aee4356845252ac6b662d5c72c29903813eJake Slack            if ("Env".equals(tag))
115903928aee4356845252ac6b662d5c72c29903813eJake Slack            {
116003928aee4356845252ac6b662d5c72c29903813eJake Slack                String name = node.getAttribute("name");
116103928aee4356845252ac6b662d5c72c29903813eJake Slack                String defaultValue = node.getAttribute("default");
116203928aee4356845252ac6b662d5c72c29903813eJake Slack                String value=System.getenv(name);
116303928aee4356845252ac6b662d5c72c29903813eJake Slack                return value==null?defaultValue:value;
116403928aee4356845252ac6b662d5c72c29903813eJake Slack            }
116503928aee4356845252ac6b662d5c72c29903813eJake Slack
116603928aee4356845252ac6b662d5c72c29903813eJake Slack            LOG.warn("Unknown value tag: " + node,new Throwable());
116703928aee4356845252ac6b662d5c72c29903813eJake Slack            return null;
116803928aee4356845252ac6b662d5c72c29903813eJake Slack        }
116903928aee4356845252ac6b662d5c72c29903813eJake Slack    }
117003928aee4356845252ac6b662d5c72c29903813eJake Slack
117103928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
117203928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
117303928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
117403928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
117503928aee4356845252ac6b662d5c72c29903813eJake Slack    /**
117603928aee4356845252ac6b662d5c72c29903813eJake Slack     * Run the XML configurations as a main application. The command line is used to obtain properties files (must be named '*.properties') and XmlConfiguration
117703928aee4356845252ac6b662d5c72c29903813eJake Slack     * files.
117803928aee4356845252ac6b662d5c72c29903813eJake Slack     * <p>
117903928aee4356845252ac6b662d5c72c29903813eJake Slack     * Any property file on the command line is added to a combined Property instance that is passed to each configuration file via
118003928aee4356845252ac6b662d5c72c29903813eJake Slack     * {@link XmlConfiguration#setProperties(Map)}.
118103928aee4356845252ac6b662d5c72c29903813eJake Slack     * <p>
118203928aee4356845252ac6b662d5c72c29903813eJake Slack     * Each configuration file on the command line is used to create a new XmlConfiguration instance and the {@link XmlConfiguration#configure()} method is used
118303928aee4356845252ac6b662d5c72c29903813eJake Slack     * to create the configured object. If the resulting object is an instance of {@link LifeCycle}, then it is started.
118403928aee4356845252ac6b662d5c72c29903813eJake Slack     * <p>
118503928aee4356845252ac6b662d5c72c29903813eJake Slack     * Any IDs created in a configuration are passed to the next configuration file on the command line using {@link #getIdMap()} and {@link #setIdMap(Map)} .
118603928aee4356845252ac6b662d5c72c29903813eJake Slack     * This allows objects with IDs created in one config file to be referenced in subsequent config files on the command line.
118703928aee4356845252ac6b662d5c72c29903813eJake Slack     *
118803928aee4356845252ac6b662d5c72c29903813eJake Slack     * @param args
118903928aee4356845252ac6b662d5c72c29903813eJake Slack     *            array of property and xml configuration filenames or {@link Resource}s.
119003928aee4356845252ac6b662d5c72c29903813eJake Slack     * @throws Exception if the XML configurations cannot be run
119103928aee4356845252ac6b662d5c72c29903813eJake Slack     */
119203928aee4356845252ac6b662d5c72c29903813eJake Slack    public static void main(final String[] args) throws Exception
119303928aee4356845252ac6b662d5c72c29903813eJake Slack    {
119403928aee4356845252ac6b662d5c72c29903813eJake Slack
119503928aee4356845252ac6b662d5c72c29903813eJake Slack        final AtomicReference<Throwable> exception = new AtomicReference<Throwable>();
119603928aee4356845252ac6b662d5c72c29903813eJake Slack
119703928aee4356845252ac6b662d5c72c29903813eJake Slack        AccessController.doPrivileged(new PrivilegedAction<Object>()
119803928aee4356845252ac6b662d5c72c29903813eJake Slack        {
119903928aee4356845252ac6b662d5c72c29903813eJake Slack            public Object run()
120003928aee4356845252ac6b662d5c72c29903813eJake Slack            {
120103928aee4356845252ac6b662d5c72c29903813eJake Slack                try
120203928aee4356845252ac6b662d5c72c29903813eJake Slack                {
120303928aee4356845252ac6b662d5c72c29903813eJake Slack
120403928aee4356845252ac6b662d5c72c29903813eJake Slack                    Properties properties = null;
120503928aee4356845252ac6b662d5c72c29903813eJake Slack
120603928aee4356845252ac6b662d5c72c29903813eJake Slack                    // Look for properties from start.jar
120703928aee4356845252ac6b662d5c72c29903813eJake Slack                    try
120803928aee4356845252ac6b662d5c72c29903813eJake Slack                    {
120903928aee4356845252ac6b662d5c72c29903813eJake Slack                        Class<?> config = XmlConfiguration.class.getClassLoader().loadClass("org.eclipse.jetty.start.Config");
121003928aee4356845252ac6b662d5c72c29903813eJake Slack                        properties = (Properties)config.getMethod("getProperties").invoke(null);
121103928aee4356845252ac6b662d5c72c29903813eJake Slack                        LOG.debug("org.eclipse.jetty.start.Config properties = {}",properties);
121203928aee4356845252ac6b662d5c72c29903813eJake Slack                    }
121303928aee4356845252ac6b662d5c72c29903813eJake Slack                    catch (NoClassDefFoundError e)
121403928aee4356845252ac6b662d5c72c29903813eJake Slack                    {
121503928aee4356845252ac6b662d5c72c29903813eJake Slack                        LOG.ignore(e);
121603928aee4356845252ac6b662d5c72c29903813eJake Slack                    }
121703928aee4356845252ac6b662d5c72c29903813eJake Slack                    catch (ClassNotFoundException e)
121803928aee4356845252ac6b662d5c72c29903813eJake Slack                    {
121903928aee4356845252ac6b662d5c72c29903813eJake Slack                        LOG.ignore(e);
122003928aee4356845252ac6b662d5c72c29903813eJake Slack                    }
122103928aee4356845252ac6b662d5c72c29903813eJake Slack                    catch (Exception e)
122203928aee4356845252ac6b662d5c72c29903813eJake Slack                    {
122303928aee4356845252ac6b662d5c72c29903813eJake Slack                        LOG.warn(e);
122403928aee4356845252ac6b662d5c72c29903813eJake Slack                    }
122503928aee4356845252ac6b662d5c72c29903813eJake Slack
122603928aee4356845252ac6b662d5c72c29903813eJake Slack                    // If no start.config properties, use clean slate
122703928aee4356845252ac6b662d5c72c29903813eJake Slack                    if (properties == null)
122803928aee4356845252ac6b662d5c72c29903813eJake Slack                    {
122903928aee4356845252ac6b662d5c72c29903813eJake Slack                        properties = new Properties();
123003928aee4356845252ac6b662d5c72c29903813eJake Slack                        // Add System Properties
123103928aee4356845252ac6b662d5c72c29903813eJake Slack                        Enumeration<?> ensysprop = System.getProperties().propertyNames();
123203928aee4356845252ac6b662d5c72c29903813eJake Slack                        while (ensysprop.hasMoreElements())
123303928aee4356845252ac6b662d5c72c29903813eJake Slack                        {
123403928aee4356845252ac6b662d5c72c29903813eJake Slack                            String name = (String)ensysprop.nextElement();
123503928aee4356845252ac6b662d5c72c29903813eJake Slack                            properties.put(name,System.getProperty(name));
123603928aee4356845252ac6b662d5c72c29903813eJake Slack                        }
123703928aee4356845252ac6b662d5c72c29903813eJake Slack                    }
123803928aee4356845252ac6b662d5c72c29903813eJake Slack
123903928aee4356845252ac6b662d5c72c29903813eJake Slack                    // For all arguments, load properties or parse XMLs
124003928aee4356845252ac6b662d5c72c29903813eJake Slack                    XmlConfiguration last = null;
124103928aee4356845252ac6b662d5c72c29903813eJake Slack                    Object[] obj = new Object[args.length];
124203928aee4356845252ac6b662d5c72c29903813eJake Slack                    for (int i = 0; i < args.length; i++)
124303928aee4356845252ac6b662d5c72c29903813eJake Slack                    {
124403928aee4356845252ac6b662d5c72c29903813eJake Slack                        if (args[i].toLowerCase(Locale.ENGLISH).endsWith(".properties"))
124503928aee4356845252ac6b662d5c72c29903813eJake Slack                        {
124603928aee4356845252ac6b662d5c72c29903813eJake Slack                            properties.load(Resource.newResource(args[i]).getInputStream());
124703928aee4356845252ac6b662d5c72c29903813eJake Slack                        }
124803928aee4356845252ac6b662d5c72c29903813eJake Slack                        else
124903928aee4356845252ac6b662d5c72c29903813eJake Slack                        {
125003928aee4356845252ac6b662d5c72c29903813eJake Slack                            XmlConfiguration configuration = new XmlConfiguration(Resource.newResource(args[i]).getURL());
125103928aee4356845252ac6b662d5c72c29903813eJake Slack                            if (last != null)
125203928aee4356845252ac6b662d5c72c29903813eJake Slack                                configuration.getIdMap().putAll(last.getIdMap());
125303928aee4356845252ac6b662d5c72c29903813eJake Slack                            if (properties.size() > 0)
125403928aee4356845252ac6b662d5c72c29903813eJake Slack                            {
125503928aee4356845252ac6b662d5c72c29903813eJake Slack                                Map<String, String> props = new HashMap<String, String>();
125603928aee4356845252ac6b662d5c72c29903813eJake Slack                                for (Object key : properties.keySet())
125703928aee4356845252ac6b662d5c72c29903813eJake Slack                                {
125803928aee4356845252ac6b662d5c72c29903813eJake Slack                                    props.put(key.toString(),String.valueOf(properties.get(key)));
125903928aee4356845252ac6b662d5c72c29903813eJake Slack                                }
126003928aee4356845252ac6b662d5c72c29903813eJake Slack                                configuration.getProperties().putAll(props);
126103928aee4356845252ac6b662d5c72c29903813eJake Slack                            }
126203928aee4356845252ac6b662d5c72c29903813eJake Slack                            obj[i] = configuration.configure();
126303928aee4356845252ac6b662d5c72c29903813eJake Slack                            last = configuration;
126403928aee4356845252ac6b662d5c72c29903813eJake Slack                        }
126503928aee4356845252ac6b662d5c72c29903813eJake Slack                    }
126603928aee4356845252ac6b662d5c72c29903813eJake Slack
126703928aee4356845252ac6b662d5c72c29903813eJake Slack                    // For all objects created by XmlConfigurations, start them if they are lifecycles.
126803928aee4356845252ac6b662d5c72c29903813eJake Slack                    for (int i = 0; i < args.length; i++)
126903928aee4356845252ac6b662d5c72c29903813eJake Slack                    {
127003928aee4356845252ac6b662d5c72c29903813eJake Slack                        if (obj[i] instanceof LifeCycle)
127103928aee4356845252ac6b662d5c72c29903813eJake Slack                        {
127203928aee4356845252ac6b662d5c72c29903813eJake Slack                            LifeCycle lc = (LifeCycle)obj[i];
127303928aee4356845252ac6b662d5c72c29903813eJake Slack                            if (!lc.isRunning())
127403928aee4356845252ac6b662d5c72c29903813eJake Slack                                lc.start();
127503928aee4356845252ac6b662d5c72c29903813eJake Slack                        }
127603928aee4356845252ac6b662d5c72c29903813eJake Slack                    }
127703928aee4356845252ac6b662d5c72c29903813eJake Slack                }
127803928aee4356845252ac6b662d5c72c29903813eJake Slack                catch (Exception e)
127903928aee4356845252ac6b662d5c72c29903813eJake Slack                {
128003928aee4356845252ac6b662d5c72c29903813eJake Slack                    LOG.debug(Log.EXCEPTION,e);
128103928aee4356845252ac6b662d5c72c29903813eJake Slack                    exception.set(e);
128203928aee4356845252ac6b662d5c72c29903813eJake Slack                }
128303928aee4356845252ac6b662d5c72c29903813eJake Slack                return null;
128403928aee4356845252ac6b662d5c72c29903813eJake Slack            }
128503928aee4356845252ac6b662d5c72c29903813eJake Slack        });
128603928aee4356845252ac6b662d5c72c29903813eJake Slack
128703928aee4356845252ac6b662d5c72c29903813eJake Slack        Throwable th = exception.get();
128803928aee4356845252ac6b662d5c72c29903813eJake Slack        if (th != null)
128903928aee4356845252ac6b662d5c72c29903813eJake Slack        {
129003928aee4356845252ac6b662d5c72c29903813eJake Slack            if (th instanceof RuntimeException)
129103928aee4356845252ac6b662d5c72c29903813eJake Slack                throw (RuntimeException)th;
129203928aee4356845252ac6b662d5c72c29903813eJake Slack            else if (th instanceof Exception)
129303928aee4356845252ac6b662d5c72c29903813eJake Slack                throw (Exception)th;
129403928aee4356845252ac6b662d5c72c29903813eJake Slack            else if (th instanceof Error)
129503928aee4356845252ac6b662d5c72c29903813eJake Slack                throw (Error)th;
129603928aee4356845252ac6b662d5c72c29903813eJake Slack            throw new Error(th);
129703928aee4356845252ac6b662d5c72c29903813eJake Slack        }
129803928aee4356845252ac6b662d5c72c29903813eJake Slack    }
129903928aee4356845252ac6b662d5c72c29903813eJake Slack}
1300