Jetty9 - Introduced configure_9_0.dtd to support constructor injection for the <Configure> element.

Also refactored, simplified, and moved to JDK 7 XmlConfiguration code.
This commit is contained in:
Simone Bordet 2012-08-06 23:11:39 +02:00
parent 365f4d8448
commit 75c2b57f25
7 changed files with 525 additions and 273 deletions

View File

@ -1,5 +1,5 @@
<?xml version="1.0"?>
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure.dtd">
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure_9_0.dtd">
<!-- =============================================================== -->
<!-- Configure the Jetty Server -->
@ -14,9 +14,8 @@
<!-- =========================================================== -->
<!-- Server Thread Pool -->
<!-- =========================================================== -->
<Set name="ThreadPool">
<!-- Default queued blocking threadpool
-->
<Arg name="threadPool">
<!-- Default queued blocking threadpool -->
<New class="org.eclipse.jetty.util.thread.QueuedThreadPool">
<Set name="maxThreads">200</Set>
<Set name="minThreads">10</Set>
@ -28,7 +27,7 @@
<Set name="maximumPoolSize">50</Set>
</New>
-->
</Set>
</Arg>
<!-- =========================================================== -->
<!-- Set connectors -->
@ -37,10 +36,10 @@
<Call name="addConnector">
<Arg>
<New class="org.eclipse.jetty.server.SelectChannelConnector">
<Arg><Ref id="Server" /></Arg>
<Set name="host"></Set>
<Set name="port">0</Set>
<Set name="idleTimeout">300000</Set>
<Set name="confidentialPort">8443</Set>
</New>
</Arg>
</Call>

View File

@ -15,7 +15,11 @@ package org.eclipse.jetty.server;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Enumeration;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@ -25,7 +29,6 @@ import org.eclipse.jetty.http.HttpURI;
import org.eclipse.jetty.server.handler.HandlerWrapper;
import org.eclipse.jetty.util.Attributes;
import org.eclipse.jetty.util.AttributesMap;
import org.eclipse.jetty.util.LazyList;
import org.eclipse.jetty.util.MultiException;
import org.eclipse.jetty.util.TypeUtil;
import org.eclipse.jetty.util.URIUtil;
@ -44,8 +47,6 @@ import org.eclipse.jetty.util.thread.ThreadPool;
* It aggregates Connectors (HTTP request receivers) and request Handlers.
* The server is itself a handler and a ThreadPool. Connectors use the ThreadPool methods
* to run jobs that will eventually call the handle method.
*
* @org.apache.xbean.XBean description="Creates an embedded Jetty web server"
*/
public class Server extends HandlerWrapper implements Attributes
{
@ -65,7 +66,7 @@ public class Server extends HandlerWrapper implements Attributes
private final Container _container=new Container();
private final AttributesMap _attributes = new AttributesMap();
private final ThreadPool _threadPool;
private Connector[] _connectors;
private final List<Connector> _connectors = new CopyOnWriteArrayList<>();
private SessionIdManager _sessionIdManager;
private boolean _sendServerVersion = true; //send Server: header
private boolean _sendDateHeader = false; //send Date: header
@ -112,7 +113,7 @@ public class Server extends HandlerWrapper implements Attributes
public Server(ThreadPool pool)
{
_threadPool=pool!=null?pool:new QueuedThreadPool();
addBean(_threadPool,pool==null);
addBean(_threadPool);
setServer(this);
}
@ -164,23 +165,27 @@ public class Server extends HandlerWrapper implements Attributes
*/
public Connector[] getConnectors()
{
return _connectors;
List<Connector> connectors = new ArrayList<>(_connectors);
return connectors.toArray(new Connector[connectors.size()]);
}
/* ------------------------------------------------------------ */
public void addConnector(Connector connector)
{
setConnectors((Connector[])LazyList.addToArray(getConnectors(), connector, Connector.class));
if (_connectors.add(connector))
_container.update(this, null, connector, "connector");
}
/* ------------------------------------------------------------ */
/**
* Conveniance method which calls {@link #getConnectors()} and {@link #setConnectors(Connector[])} to
* Convenience method which calls {@link #getConnectors()} and {@link #setConnectors(Connector[])} to
* remove a connector.
* @param connector The connector to remove.
*/
public void removeConnector(Connector connector) {
setConnectors((Connector[])LazyList.removeFromArray (getConnectors(), connector));
public void removeConnector(Connector connector)
{
if (_connectors.remove(connector))
_container.update(this, connector, null, "connector");
}
/* ------------------------------------------------------------ */
@ -190,17 +195,21 @@ public class Server extends HandlerWrapper implements Attributes
*/
public void setConnectors(Connector[] connectors)
{
if (connectors!=null)
if (connectors != null)
{
for (int i=0;i<connectors.length;i++)
for (Connector connector : connectors)
{
if (connectors[i].getServer()!=this)
throw new IllegalArgumentException();
if (connector.getServer() != this)
throw new IllegalArgumentException("Connector " + connector +
" cannot be shared among server " + connector.getServer() + " and server " + this);
}
}
_container.update(this, _connectors, connectors, "connector");
_connectors = connectors;
Connector[] oldConnectors = getConnectors();
_container.update(this, oldConnectors, connectors, "connector");
_connectors.removeAll(Arrays.asList(oldConnectors));
if (connectors != null)
_connectors.addAll(Arrays.asList(connectors));
}
/* ------------------------------------------------------------ */
@ -266,12 +275,15 @@ public class Server extends HandlerWrapper implements Attributes
mex.add(e);
}
if (_connectors!=null && mex.size()==0)
if (mex.size()==0)
{
for (int i=0;i<_connectors.length;i++)
for (Connector _connector : _connectors)
{
try{_connectors[i].start();}
catch(Throwable e)
try
{
_connector.start();
}
catch (Throwable e)
{
mex.add(e);
}
@ -293,38 +305,46 @@ public class Server extends HandlerWrapper implements Attributes
MultiException mex=new MultiException();
if (_graceful>0)
long gracefulTimeout = getGracefulShutdown();
if (gracefulTimeout>0)
{
if (_connectors!=null)
for (Connector connector : _connectors)
{
for (int i=_connectors.length;i-->0;)
{
LOG.info("Graceful shutdown {}",_connectors[i]);
if (_connectors[i] instanceof NetworkConnector)
((NetworkConnector)_connectors[i]).close();
}
LOG.info("Graceful shutdown {}", connector);
if (connector instanceof NetworkConnector)
((NetworkConnector)connector).close();
}
Handler[] contexts = getChildHandlersByClass(Graceful.class);
for (int c=0;c<contexts.length;c++)
for (Handler context : contexts)
{
Graceful context=(Graceful)contexts[c];
LOG.info("Graceful shutdown {}",context);
context.setShutdown(true);
Graceful graceful = (Graceful)context;
LOG.info("Graceful shutdown {}", graceful);
graceful.setShutdown(true);
}
Thread.sleep(_graceful);
Thread.sleep(gracefulTimeout);
}
if (_connectors!=null)
for (Connector connector : _connectors)
{
for (int i=_connectors.length;i-->0;)
try
{
if (_connectors[i]!=null)
try{_connectors[i].stop();}catch(Throwable e){mex.add(e);}
connector.stop();
}
catch (Throwable e)
{
mex.add(e);
}
}
try {super.doStop(); } catch(Throwable e) { mex.add(e);}
try
{
super.doStop();
}
catch (Throwable e)
{
mex.add(e);
}
mex.ifExceptionThrow();
@ -440,9 +460,6 @@ public class Server extends HandlerWrapper implements Attributes
}
/* ------------------------------------------------------------ */
/**
* @param sendDateHeader
*/
public void setSendDateHeader(boolean sendDateHeader)
{
_sendDateHeader = sendDateHeader;
@ -454,24 +471,6 @@ public class Server extends HandlerWrapper implements Attributes
return _sendDateHeader;
}
/* ------------------------------------------------------------ */
/**
*/
@Deprecated
public int getMaxCookieVersion()
{
return 1;
}
/* ------------------------------------------------------------ */
/**
*/
@Deprecated
public void setMaxCookieVersion(int maxCookieVersion)
{
}
/* ------------------------------------------------------------ */
/**
* Add an associated bean.
@ -535,7 +534,7 @@ public class Server extends HandlerWrapper implements Attributes
* @see org.eclipse.util.AttributesMap#getAttributeNames()
*/
@Override
public Enumeration getAttributeNames()
public Enumeration<String> getAttributeNames()
{
return AttributesMap.getAttributeNamesCopy(_attributes);
}
@ -600,7 +599,7 @@ public class Server extends HandlerWrapper implements Attributes
public void dump(Appendable out,String indent) throws IOException
{
dumpThis(out);
dump(out,indent,TypeUtil.asList(getHandlers()),getBeans(),TypeUtil.asList(_connectors));
dump(out,indent,TypeUtil.asList(getHandlers()),getBeans(),_connectors);
}
/* ------------------------------------------------------------ */

View File

@ -19,7 +19,6 @@ import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.net.URL;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
@ -44,7 +43,7 @@ public class TypeUtil
public static int LF = '\012';
/* ------------------------------------------------------------ */
private static final HashMap<String, Class<?>> name2Class=new HashMap<String, Class<?>>();
private static final HashMap<String, Class<?>> name2Class=new HashMap<>();
static
{
name2Class.put("boolean",java.lang.Boolean.TYPE);
@ -92,7 +91,7 @@ public class TypeUtil
}
/* ------------------------------------------------------------ */
private static final HashMap<Class<?>, String> class2Name=new HashMap<Class<?>, String>();
private static final HashMap<Class<?>, String> class2Name=new HashMap<>();
static
{
class2Name.put(java.lang.Boolean.TYPE,"boolean");
@ -119,7 +118,7 @@ public class TypeUtil
}
/* ------------------------------------------------------------ */
private static final HashMap<Class<?>, Method> class2Value=new HashMap<Class<?>, Method>();
private static final HashMap<Class<?>, Method> class2Value=new HashMap<>();
static
{
try
@ -168,13 +167,13 @@ public class TypeUtil
* Works like {@link Arrays#asList(Object...)}, but handles null arrays.
* @return a list backed by the array.
*/
public static <T> List<T> asList(T[] a)
public static <T> List<T> asList(T[] a)
{
if (a==null)
return Collections.emptyList();
return Arrays.asList(a);
}
/* ------------------------------------------------------------ */
/** Class from a canonical name for a type.
* @param name A class or type name.
@ -214,28 +213,20 @@ public class TypeUtil
if (type.equals(java.lang.Character.TYPE) ||
type.equals(java.lang.Character.class))
return new Character(value.charAt(0));
return value.charAt(0);
Constructor<?> c = type.getConstructor(java.lang.String.class);
return c.newInstance(value);
}
catch(NoSuchMethodException e)
catch (NoSuchMethodException | IllegalAccessException | InstantiationException x)
{
// LogSupport.ignore(log,e);
LOG.ignore(x);
}
catch(IllegalAccessException e)
catch (InvocationTargetException x)
{
// LogSupport.ignore(log,e);
}
catch(InstantiationException e)
{
// LogSupport.ignore(log,e);
}
catch(InvocationTargetException e)
{
if (e.getTargetException() instanceof Error)
throw (Error)(e.getTargetException());
// LogSupport.ignore(log,e);
if (x.getTargetException() instanceof Error)
throw (Error)x.getTargetException();
LOG.ignore(x);
}
return null;
}
@ -390,7 +381,7 @@ public class TypeUtil
{
return toHexString(new byte[]{b}, 0, 1);
}
/* ------------------------------------------------------------ */
public static String toHexString(byte[] b)
{
@ -499,54 +490,49 @@ public class TypeUtil
return buf;
}
public static URL jarFor(String className)
{
try
{
className=className.replace('.','/')+".class";
// hack to discover jstl libraries
URL url = Loader.getResource(null,className,false);
String s=url.toString();
if (s.startsWith("jar:file:"))
return new URL(s.substring(4,s.indexOf("!/")));
}
catch(Exception e)
{
LOG.ignore(e);
}
return null;
}
public static Object call(Class<?> oClass, String method, Object obj, Object[] arg)
public static Object call(Class<?> oClass, String methodName, Object obj, Object[] arg)
throws InvocationTargetException, NoSuchMethodException
{
// Lets just try all methods for now
Method[] methods = oClass.getMethods();
for (int c = 0; methods != null && c < methods.length; c++)
for (Method method : oClass.getMethods())
{
if (!methods[c].getName().equals(method))
if (!method.getName().equals(methodName))
continue;
if (methods[c].getParameterTypes().length != arg.length)
if (method.getParameterTypes().length != arg.length)
continue;
if (Modifier.isStatic(methods[c].getModifiers()) != (obj == null))
if (Modifier.isStatic(method.getModifiers()) != (obj == null))
continue;
if ((obj == null) && methods[c].getDeclaringClass() != oClass)
if ((obj == null) && method.getDeclaringClass() != oClass)
continue;
try
{
return methods[c].invoke(obj,arg);
return method.invoke(obj, arg);
}
catch (IllegalAccessException e)
{
LOG.ignore(e);
}
catch (IllegalArgumentException e)
catch (IllegalAccessException | IllegalArgumentException e)
{
LOG.ignore(e);
}
}
throw new NoSuchMethodException(methodName);
}
throw new NoSuchMethodException(method);
public static Object construct(Class<?> klass, Object[] arguments) throws InvocationTargetException, NoSuchMethodException
{
for (Constructor<?> constructor : klass.getConstructors())
{
if (constructor.getParameterTypes().length != arguments.length)
continue;
try
{
return constructor.newInstance(arguments);
}
catch (InstantiationException | IllegalAccessException | IllegalArgumentException e)
{
LOG.ignore(e);
}
}
throw new NoSuchMethodException("<init>");
}
}

View File

@ -67,13 +67,13 @@ public class XmlConfiguration
private static final Logger LOG = Log.getLogger(XmlConfiguration.class);
private static final Class<?>[] __primitives =
{ Boolean.TYPE, Character.TYPE, Byte.TYPE, Short.TYPE, Integer.TYPE, Long.TYPE, Float.TYPE, Double.TYPE, Void.TYPE };
{Boolean.TYPE, Character.TYPE, Byte.TYPE, Short.TYPE, Integer.TYPE, Long.TYPE, Float.TYPE, Double.TYPE, Void.TYPE};
private static final Class<?>[] __primitiveHolders =
{ Boolean.class, Character.class, Byte.class, Short.class, Integer.class, Long.class, Float.class, Double.class, Void.class };
private static final Class<?>[] __boxedPrimitives =
{Boolean.class, Character.class, Byte.class, Short.class, Integer.class, Long.class, Float.class, Double.class, Void.class};
private static final Class<?>[] __supportedCollections =
{ ArrayList.class,ArrayQueue.class,HashSet.class,Queue.class,List.class,Set.class,Collection.class,};
{ArrayList.class, ArrayQueue.class, HashSet.class, Queue.class, List.class, Set.class, Collection.class,};
private static final Iterable<?> __factoryLoader;
@ -81,14 +81,14 @@ public class XmlConfiguration
static
{
Iterable<?> loader=null;
Iterable<?> loader = null;
try
{
// Use reflection to look up 1.6 service loader
// loader=ServiceLoader.load(ConfigurationProcessorFactory.class);
Class<?> slc = ClassLoader.getSystemClassLoader().loadClass("java.util.ServiceLoader");
Method load = slc.getMethod("load",Class.class);
loader=(Iterable<?>)load.invoke(null,ConfigurationProcessorFactory.class);
loader = (Iterable<?>)load.invoke(null, ConfigurationProcessorFactory.class);
}
catch(Exception e)
{
@ -96,16 +96,16 @@ public class XmlConfiguration
}
finally
{
__factoryLoader=loader;
__factoryLoader = loader;
}
}
/* ------------------------------------------------------------ */
private URL _url;
private String _dtd;
private final Map<String, Object> _idMap = new HashMap<>();
private final Map<String, String> _propertyMap = new HashMap<>();
private final URL _url;
private final String _dtd;
private ConfigurationProcessor _processor;
private final Map<String, Object> _idMap = new HashMap<String, Object>();
private final Map<String, String> _propertyMap = new HashMap<String, String>();
/* ------------------------------------------------------------ */
private synchronized static XmlParser initParser()
@ -115,20 +115,22 @@ public class XmlConfiguration
{
URL config60 = Loader.getResource(XmlConfiguration.class,"org/eclipse/jetty/xml/configure_6_0.dtd",true);
URL config76 = Loader.getResource(XmlConfiguration.class,"org/eclipse/jetty/xml/configure_7_6.dtd",true);
parser.redirectEntity("configure.dtd",config76);
URL config90 = Loader.getResource(XmlConfiguration.class,"org/eclipse/jetty/xml/configure_9_0.dtd",true);
parser.redirectEntity("configure.dtd",config90);
parser.redirectEntity("configure_1_0.dtd",config60);
parser.redirectEntity("configure_1_1.dtd",config60);
parser.redirectEntity("configure_1_2.dtd",config60);
parser.redirectEntity("configure_1_3.dtd",config60);
parser.redirectEntity("configure_6_0.dtd",config60);
parser.redirectEntity("configure_7_6.dtd",config76);
parser.redirectEntity("configure_9_0.dtd",config90);
parser.redirectEntity("http://jetty.mortbay.org/configure.dtd",config76);
parser.redirectEntity("http://jetty.eclipse.org/configure.dtd",config76);
parser.redirectEntity("http://www.eclipse.org/jetty/configure.dtd",config76);
parser.redirectEntity("http://jetty.mortbay.org/configure.dtd",config90);
parser.redirectEntity("http://jetty.eclipse.org/configure.dtd",config90);
parser.redirectEntity("http://www.eclipse.org/jetty/configure.dtd",config90);
parser.redirectEntity("-//Mort Bay Consulting//DTD Configure//EN",config76);
parser.redirectEntity("-//Jetty//Configure//EN",config76);
parser.redirectEntity("-//Mort Bay Consulting//DTD Configure//EN",config90);
parser.redirectEntity("-//Jetty//Configure//EN",config90);
}
catch (ClassNotFoundException e)
{
@ -167,11 +169,12 @@ public class XmlConfiguration
*/
public XmlConfiguration(String configuration) throws SAXException, IOException
{
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\">"
configuration = "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>\n<!DOCTYPE Configure PUBLIC \"-//Jetty//Configure//EN\" \"http://eclipse.org/jetty/configure.dtd\">"
+ configuration;
InputSource source = new InputSource(new StringReader(configuration));
synchronized (__parser)
{
_url=null;
setConfig( __parser.parse(source));
_dtd=__parser.getDTD();
}
@ -190,6 +193,7 @@ public class XmlConfiguration
InputSource source = new InputSource(configuration);
synchronized (__parser)
{
_url=null;
setConfig(__parser.parse(source));
_dtd=__parser.getDTD();
}
@ -335,15 +339,39 @@ public class XmlConfiguration
Class<?> oClass = nodeClass(_config);
String id = _config.getAttribute("id");
Object obj = id == null?null:_idMap.get(id);
Object obj = id == null ? null : _idMap.get(id);
int index = 0;
if (obj == null && oClass != null)
obj = oClass.newInstance();
{
List<Object> arguments = new ArrayList<>();
for (int i = 0; i < _config.size(); i++)
{
Object o = _config.get(i);
if (o instanceof String)
continue;
if (!((XmlParser.Node)o).getTag().equals("Arg"))
{
index = i;
break;
}
else
{
arguments.add(value(obj, (XmlParser.Node)o));
}
}
if (oClass != null && !oClass.isInstance(obj))
throw new ClassCastException(oClass.toString()+" in "+_url);
try
{
obj = TypeUtil.construct(oClass, arguments.toArray());
}
catch (NoSuchMethodException x)
{
throw new IllegalStateException("No suitable constructor on " + oClass, x);
}
}
configure(obj,_config,0);
configure(obj, _config, index);
return obj;
}
@ -383,24 +411,35 @@ public class XmlConfiguration
try
{
String tag = node.getTag();
if ("Set".equals(tag))
set(obj,node);
else if ("Put".equals(tag))
put(obj,node);
else if ("Call".equals(tag))
call(obj,node);
else if ("Get".equals(tag))
get(obj,node);
else if ("New".equals(tag))
newObj(obj,node);
else if ("Array".equals(tag))
newArray(obj,node);
else if ("Ref".equals(tag))
refObj(obj,node);
else if ("Property".equals(tag))
propertyObj(node);
else
throw new IllegalStateException("Unknown tag: " + tag+" in "+_url);
switch (tag)
{
case "Set":
set(obj, node);
break;
case "Put":
put(obj, node);
break;
case "Call":
call(obj, node);
break;
case "Get":
get(obj, node);
break;
case "New":
newObj(obj, node);
break;
case "Array":
newArray(obj, node);
break;
case "Ref":
refObj(obj, node);
break;
case "Property":
propertyObj(node);
break;
default:
throw new IllegalStateException("Unknown tag: " + tag + " in " + _url);
}
}
catch (Exception e)
{
@ -447,15 +486,7 @@ public class XmlConfiguration
set.invoke(obj,arg);
return;
}
catch (IllegalArgumentException e)
{
LOG.ignore(e);
}
catch (IllegalAccessException e)
{
LOG.ignore(e);
}
catch (NoSuchMethodException e)
catch (IllegalArgumentException | IllegalAccessException | NoSuchMethodException e)
{
LOG.ignore(e);
}
@ -469,19 +500,7 @@ public class XmlConfiguration
set.invoke(obj,arg);
return;
}
catch (NoSuchFieldException e)
{
LOG.ignore(e);
}
catch (IllegalArgumentException e)
{
LOG.ignore(e);
}
catch (IllegalAccessException e)
{
LOG.ignore(e);
}
catch (NoSuchMethodException e)
catch (NoSuchFieldException | IllegalArgumentException | IllegalAccessException | NoSuchMethodException e)
{
LOG.ignore(e);
}
@ -517,11 +536,7 @@ public class XmlConfiguration
sets[s].invoke(obj,arg);
return;
}
catch (IllegalArgumentException e)
{
LOG.ignore(e);
}
catch (IllegalAccessException e)
catch (IllegalArgumentException | IllegalAccessException e)
{
LOG.ignore(e);
}
@ -554,7 +569,7 @@ public class XmlConfiguration
{
if (sClass.equals(__primitives[t]))
{
sClass = __primitiveHolders[t];
sClass = __boxedPrimitives[t];
break;
}
}
@ -564,15 +579,7 @@ public class XmlConfiguration
set.invoke(obj,arg);
return;
}
catch (NoSuchMethodException e)
{
LOG.ignore(e);
}
catch (IllegalAccessException e)
{
LOG.ignore(e);
}
catch (InstantiationException e)
catch (NoSuchMethodException | IllegalAccessException | InstantiationException e)
{
LOG.ignore(e);
}
@ -595,10 +602,10 @@ public class XmlConfiguration
if (collectionType.isAssignableFrom(ArrayList.class))
collection = convertArrayToArrayList(array);
else if (collectionType.isAssignableFrom(HashSet.class))
collection = new HashSet<Object>(convertArrayToArrayList(array));
collection = new HashSet<>(convertArrayToArrayList(array));
else if (collectionType.isAssignableFrom(ArrayQueue.class))
{
ArrayQueue<Object> q= new ArrayQueue<Object>();
ArrayQueue<Object> q= new ArrayQueue<>();
q.addAll(convertArrayToArrayList(array));
collection=q;
}
@ -612,7 +619,7 @@ public class XmlConfiguration
private static ArrayList<Object> convertArrayToArrayList(Object array)
{
int length = Array.getLength(array);
ArrayList<Object> list = new ArrayList<Object>(length);
ArrayList<Object> list = new ArrayList<>(length);
for (int i = 0; i < length; i++)
list.add(Array.get(array,i));
return list;
@ -755,7 +762,6 @@ public class XmlConfiguration
private Object newObj(Object obj, XmlParser.Node node) throws Exception
{
Class<?> oClass = nodeClass(node);
String id = node.getAttribute("id");
int size = 0;
int argi = node.size();
for (int i = 0; i < node.size(); i++)
@ -783,42 +789,16 @@ public class XmlConfiguration
if (LOG.isDebugEnabled())
LOG.debug("XML new " + oClass);
// Lets just try all constructors for now
Constructor<?>[] constructors = oClass.getConstructors();
for (int c = 0; constructors != null && c < constructors.length; c++)
try
{
if (constructors[c].getParameterTypes().length != size)
continue;
Object n = null;
boolean called = false;
try
{
n = constructors[c].newInstance(arg);
called = true;
}
catch (IllegalAccessException e)
{
LOG.ignore(e);
}
catch (InstantiationException e)
{
LOG.ignore(e);
}
catch (IllegalArgumentException e)
{
LOG.ignore(e);
}
if (called)
{
if (id != null)
_idMap.put(id,n);
configure(n,node,argi);
return n;
}
Object n = TypeUtil.construct(oClass, arg);
configure(n,node,argi);
return n;
}
catch (NoSuchMethodException e)
{
throw new IllegalStateException("No suitable constructor: " + node + " on " + obj);
}
throw new IllegalStateException("No Constructor: " + node + " on " + obj);
}
/* ------------------------------------------------------------ */
@ -853,14 +833,21 @@ public class XmlConfiguration
aClass = TypeUtil.fromName(type);
if (aClass == null)
{
if ("String".equals(type))
aClass = java.lang.String.class;
else if ("URL".equals(type))
aClass = java.net.URL.class;
else if ("InetAddress".equals(type))
aClass = java.net.InetAddress.class;
else
aClass = Loader.loadClass(XmlConfiguration.class,type,true);
switch (type)
{
case "String":
aClass = String.class;
break;
case "URL":
aClass = URL.class;
break;
case "InetAddress":
aClass = InetAddress.class;
break;
default:
aClass = Loader.loadClass(XmlConfiguration.class, type, true);
break;
}
}
}
@ -890,7 +877,7 @@ public class XmlConfiguration
{
String id = node.getAttribute("id");
Map<Object, Object> map = new HashMap<Object, Object>();
Map<Object, Object> map = new HashMap<>();
if (id != null)
_idMap.put(id,map);
@ -1180,7 +1167,7 @@ public class XmlConfiguration
public static void main(final String[] args) throws Exception
{
final AtomicReference<Throwable> exception = new AtomicReference<Throwable>();
final AtomicReference<Throwable> exception = new AtomicReference<>();
AccessController.doPrivileged(new PrivilegedAction<Object>()
{
@ -1198,11 +1185,7 @@ public class XmlConfiguration
properties = (Properties)config.getMethod("getProperties").invoke(null);
LOG.debug("org.eclipse.jetty.start.Config properties = {}",properties);
}
catch (NoClassDefFoundError e)
{
LOG.ignore(e);
}
catch (ClassNotFoundException e)
catch (NoClassDefFoundError | ClassNotFoundException e)
{
LOG.ignore(e);
}
@ -1240,7 +1223,7 @@ public class XmlConfiguration
configuration.getIdMap().putAll(last.getIdMap());
if (properties.size() > 0)
{
Map<String, String> props = new HashMap<String, String>();
Map<String, String> props = new HashMap<>();
for (Object key : properties.keySet())
{
props.put(key.toString(),String.valueOf(properties.get(key)));

View File

@ -19,7 +19,7 @@ my be specified if a match is not achieved.
-->
<!ENTITY % CONFIG "Set|Get|Put|Call|New|Ref|Array|Map|Property">
<!ENTITY % VALUE "#PCDATA|Get|Call|New|Ref|Array|Map|SystemProperty|Env|Property">
<!ENTITY % VALUE "#PCDATA|Get|Call|New|Ref|Array|Map|SystemProperty|Property">
<!ENTITY % TYPEATTR "type CDATA #IMPLIED " > <!-- String|Character|Short|Byte|Integer|Long|Boolean|Float|Double|char|short|byte|int|long|boolean|float|double|URL|InetAddress|InetAddrPort| #classname -->
<!ENTITY % IMPLIEDCLASSATTR "class NMTOKEN #IMPLIED" >
@ -245,24 +245,6 @@ This is equivalent to:
<!ELEMENT SystemProperty EMPTY>
<!ATTLIST SystemProperty %NAMEATTR; %DEFAULTATTR; %IDATTR;>
<!--
Environment variable Element.
This element allows OS Environment variables to be retrieved as
part of the value of elements such as Set, Put, Arg, etc.
The name attribute specifies the env variable name and the optional
default argument provides a default value.
<Env name="Test" default="value" />
This is equivalent to:
String v=System.getEnv("Test");
if (v==null) v="value";
-->
<!ELEMENT Env EMPTY>
<!ATTLIST Env %NAMEATTR; %DEFAULTATTR; %IDATTR;>
<!--
Property Element.

View File

@ -19,7 +19,7 @@ my be specified if a match is not achieved.
-->
<!ENTITY % CONFIG "Set|Get|Put|Call|New|Ref|Array|Map|Property">
<!ENTITY % VALUE "#PCDATA|Get|Call|New|Ref|Array|Map|SystemProperty|Property">
<!ENTITY % VALUE "#PCDATA|Get|Call|New|Ref|Array|Map|SystemProperty|Env|Property">
<!ENTITY % TYPEATTR "type CDATA #IMPLIED " > <!-- String|Character|Short|Byte|Integer|Long|Boolean|Float|Double|char|short|byte|int|long|boolean|float|double|URL|InetAddress|InetAddrPort| #classname -->
<!ENTITY % IMPLIEDCLASSATTR "class NMTOKEN #IMPLIED" >
@ -246,6 +246,25 @@ This is equivalent to:
<!ATTLIST SystemProperty %NAMEATTR; %DEFAULTATTR; %IDATTR;>
<!--
Environment variable Element.
This element allows OS Environment variables to be retrieved as
part of the value of elements such as Set, Put, Arg, etc.
The name attribute specifies the env variable name and the optional
default argument provides a default value.
<Env name="Test" default="value" />
This is equivalent to:
String v=System.getEnv("Test");
if (v==null) v="value";
-->
<!ELEMENT Env EMPTY>
<!ATTLIST Env %NAMEATTR; %DEFAULTATTR; %IDATTR;>
<!--
Property Element.
This element allows arbitrary properties to be retrieved by name.

View File

@ -0,0 +1,284 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<!--
This is the document type descriptor for the
org.eclipse.jetty.xml.XmlConfiguration class. It allows a java object to be
configured by with a sequence of Set, Put and Call elements. These tags are
mapped to methods on the object to be configured as follows:
<Set name="Test">value</Set> == obj.setTest("value");
<Put name="Test">value</Put> == obj.put("Test","value");
<Call name="test"><Arg>value</Arg></Call> == obj.test("value");
Values themselves may be configured objects that are created with the
<New> tag or returned from a <Call> tag.
Values are matched to arguments on a best effort approach, but types
my be specified if a match is not achieved.
-->
<!ENTITY % CONFIG "Set|Get|Put|Call|New|Ref|Array|Map|Property">
<!ENTITY % VALUE "#PCDATA|Get|Call|New|Ref|Array|Map|SystemProperty|Env|Property">
<!ENTITY % TYPEATTR "type CDATA #IMPLIED " > <!-- String|Character|Short|Byte|Integer|Long|Boolean|Float|Double|char|short|byte|int|long|boolean|float|double|URL|InetAddress|InetAddrPort| #classname -->
<!ENTITY % IMPLIEDCLASSATTR "class NMTOKEN #IMPLIED" >
<!ENTITY % CLASSATTR "class NMTOKEN #REQUIRED" >
<!ENTITY % NAMEATTR "name NMTOKEN #REQUIRED" >
<!ENTITY % IMPLIEDNAMEATTR "name NMTOKEN #IMPLIED" >
<!ENTITY % DEFAULTATTR "default CDATA #IMPLIED" >
<!ENTITY % IDATTR "id NMTOKEN #IMPLIED" >
<!ENTITY % REQUIREDIDATTR "id NMTOKEN #REQUIRED" >
<!--
Configure Element.
This is the root element that specifies the class of object that
can be configured:
<Configure class="com.acme.MyClass"> ... </Configure>
-->
<!ELEMENT Configure (Arg*,(%CONFIG;)*) >
<!ATTLIST Configure %IMPLIEDCLASSATTR; %IDATTR; >
<!--
Set Element.
This element maps to a call to a setter method or field on the current object.
The name and optional type attributes are used to select the setter
method. If the name given is xxx, then a setXxx method is used, or
the xxx field is used of setXxx cannot be found.
A Set element can contain value text and/or the value objects returned
by other elements such as Call, New, SystemProperty, etc.
If no value type is specified, then white
space is trimmed out of the value. If it contains multiple value
elements they are added as strings before being converted to any
specified type.
A Set with a class attribute is treated as a static set method invocation.
-->
<!ELEMENT Set (%VALUE;)* >
<!ATTLIST Set %NAMEATTR; %TYPEATTR; %IMPLIEDCLASSATTR; >
<!--
Get Element.
This element maps to a call to a getter method or field on the current object.
The name attribute is used to select the get method.
If the name given is xxx, then a getXxx method is used, or
the xxx field is used if getXxx cannot be found.
A Get element can contain other elements such as Set, Put, Call, etc.
which act on the object returned by the get call.
A Get with a class attribute is treated as a static get method or field.
-->
<!ELEMENT Get (%CONFIG;)* >
<!ATTLIST Get %NAMEATTR; %IMPLIEDCLASSATTR; %IDATTR; >
<!--
Put Element.
This element maps to a call to a put method on the current object,
which must implement the Map interface. The name attribute is used
as the put key and the optional type attribute can force the type
of the value.
A Put element can contain value text and/or value elements such as Call,
New, SystemProperty, etc. If no value type is specified, then white
space is trimmed out of the value. If it contains multiple value
elements they are added as strings before being converted to any
specified type.
-->
<!ELEMENT Put (%VALUE;)* >
<!ATTLIST Put %NAMEATTR; %TYPEATTR; >
<!--
Call Element.
This element maps to an arbitrary call to a method on the current object,
The name attribute and Arg elements are used to select the method.
A Call element can contain a sequence of Arg elements followed by
a sequence of other elements such as Set, Put, Call, etc. which act on any object
returned by the original call:
<Call id="o2" name="test">
<Arg>value1</Arg>
<Set name="Test">Value2</Set>
</Call>
This is equivalent to:
Object o2 = o1.test("value1");
o2.setTest("value2");
A Call with a class attribute is treated as a static call.
-->
<!ELEMENT Call (Arg*,(%CONFIG;)*) >
<!ATTLIST Call %NAMEATTR; %IMPLIEDCLASSATTR; %IDATTR; >
<!--
Arg Element.
This element defines a positional argument for the Call element.
The optional type attribute can force the type of the value.
An Arg element can contain value text and/or value elements such as Call,
New, SystemProperty, etc. If no value type is specified, then white
space is trimmed out of the value. If it contains multiple value
elements they are added as strings before being converted to any
specified type.
-->
<!ELEMENT Arg (%VALUE;)* >
<!ATTLIST Arg %TYPEATTR; %IMPLIEDNAMEATTR; >
<!--
New Element.
This element allows the creation of a new object as part of a
value for elements such as Set, Put, Arg, etc. The class attribute determines
the type of the new object and the contained Arg elements
are used to select the constructor for the new object.
A New element can contain a sequence of Arg elements followed by
a sequence of elements such as Set, Put, Call, etc. elements
which act on the new object:
<New id="o" class="com.acme.MyClass">
<Arg>value1</Arg>
<Set name="test">Value2</Set>
</New>
This is equivalent to:
Object o = new com.acme.MyClass("value1");
o.setTest("Value2");
-->
<!ELEMENT New (Arg*,(%CONFIG;)*) >
<!ATTLIST New %CLASSATTR; %IDATTR;>
<!--
Ref Element.
This element allows a previously created object to be referenced by id.
A Ref element can contain a sequence of elements such as Set, Put, Call, etc.
which act on the referenced object:
<Ref id="myobject">
<Set name="Test">Value2</Set>
</New>
-->
<!ELEMENT Ref (%CONFIG;)* >
<!ATTLIST Ref %REQUIREDIDATTR;>
<!--
Array Element.
This element allows the creation of a new array as part of a
value of elements such as Set, Put, Arg, etc. The type attribute determines
the type of the new array and the contained Item elements
are used for each element of the array:
<Array type="java.lang.String">
<Item>value0</Item>
<Item><New class="java.lang.String"><Arg>value1</Arg></New></Item>
</Array>
This is equivalent to:
String[] a = new String[] { "value0", new String("value1") };
-->
<!ELEMENT Array (Item*) >
<!ATTLIST Array %TYPEATTR; %IDATTR; >
<!--
Map Element.
This element allows the creation of a new map as part of a
value of elements such as Set, Put, Arg, etc. The type attribute determines
the type of the new array and the contained Item elements
are used for each element of the array:
<Map>
<Entry>
<Item>keyName</Item>
<Item><New class="java.lang.String"><Arg>value1</Arg></New></Item>
</Entry>
</Map>
This is equivalent to:
Map m = new HashMap();
m.put("keyName", new String("value1"));
-->
<!ELEMENT Map (Entry*) >
<!ATTLIST Map %IDATTR; >
<!ELEMENT Entry (Item,Item) >
<!--
Item Element.
This element defines an entry for the Array or Map Entry elements.
The optional type attribute can force the type of the value.
An Item element can contain value text and/or the value object of
elements such as Call, New, SystemProperty, etc. If no value type
is specified, then white space is trimmed out of the value.
If it contains multiple value elements they are added as strings
before being converted to any specified type.
-->
<!ELEMENT Item (%VALUE;)* >
<!ATTLIST Item %TYPEATTR; %IDATTR; >
<!--
System Property Element.
This element allows JVM System properties to be retrieved as
part of the value of elements such as Set, Put, Arg, etc.
The name attribute specifies the property name and the optional
default argument provides a default value.
<SystemProperty name="Test" default="value" />
This is equivalent to:
System.getProperty("Test","value");
-->
<!ELEMENT SystemProperty EMPTY >
<!ATTLIST SystemProperty %NAMEATTR; %DEFAULTATTR; %IDATTR; >
<!--
Environment variable Element.
This element allows OS Environment variables to be retrieved as
part of the value of elements such as Set, Put, Arg, etc.
The name attribute specifies the env variable name and the optional
default argument provides a default value.
<Env name="Test" default="value" />
This is equivalent to:
String v=System.getEnv("Test");
if (v==null) v="value";
-->
<!ELEMENT Env EMPTY >
<!ATTLIST Env %NAMEATTR; %DEFAULTATTR; %IDATTR; >
<!--
Property Element.
This element allows arbitrary properties to be retrieved by name.
The name attribute specifies the property name and the optional
default argument provides a default value.
A Property element can contain a sequence of elements such as Set, Put, Call, etc.
which act on the retrieved object:
<Property name="Server">
<Call id="jdbcIdMgr" name="getAttribute">
<Arg>jdbcIdMgr</Arg>
</Call>
</Property>
-->
<!ELEMENT Property (%CONFIG;)* >
<!ATTLIST Property %NAMEATTR; %DEFAULTATTR; %IDATTR; >