Merge remote-tracking branch 'origin/jetty-9.3.x' into jetty-9.4.x
This commit is contained in:
commit
25574d2843
|
@ -23,7 +23,6 @@ import org.eclipse.jetty.server.Server;
|
|||
import org.eclipse.jetty.server.handler.DefaultHandler;
|
||||
import org.eclipse.jetty.server.handler.HandlerList;
|
||||
import org.eclipse.jetty.server.handler.ResourceHandler;
|
||||
import org.eclipse.jetty.server.handler.gzip.GzipHandler;
|
||||
|
||||
/**
|
||||
* Simple Jetty FileServer.
|
||||
|
@ -41,6 +40,7 @@ public class FileServer
|
|||
// Create the ResourceHandler. It is the object that will actually handle the request for a given file. It is
|
||||
// a Jetty Handler object so it is suitable for chaining with other handlers as you will see in other examples.
|
||||
ResourceHandler resource_handler = new ResourceHandler();
|
||||
|
||||
// Configure the ResourceHandler. Setting the resource base indicates where the files should be served out of.
|
||||
// In this example it is the current directory but it can be configured to anything that the jvm has access to.
|
||||
resource_handler.setDirectoriesListed(true);
|
||||
|
@ -48,11 +48,8 @@ public class FileServer
|
|||
resource_handler.setResourceBase(".");
|
||||
|
||||
// Add the ResourceHandler to the server.
|
||||
GzipHandler gzip = new GzipHandler();
|
||||
server.setHandler(gzip);
|
||||
HandlerList handlers = new HandlerList();
|
||||
handlers.setHandlers(new Handler[] { resource_handler, new DefaultHandler() });
|
||||
gzip.setHandler(handlers);
|
||||
|
||||
// Start things up! By using the server.join() the server thread will join with the current thread.
|
||||
// See "http://docs.oracle.com/javase/1.5.0/docs/api/java/lang/Thread.html#join()" for more details.
|
||||
|
|
|
@ -30,15 +30,12 @@ For a more in-depth look at the syntax, see xref:jetty-xml-syntax[].
|
|||
|
||||
[source, xml, subs="{sub-order}"]
|
||||
----
|
||||
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure.dtd">
|
||||
|
||||
<Configure class="org.eclipse.jetty.webapp.WebAppContext">
|
||||
..
|
||||
</Configure>
|
||||
|
||||
|
||||
----
|
||||
|
||||
____
|
||||
|
|
|
@ -53,7 +53,7 @@ The following XML configuration file creates some Java objects and sets some att
|
|||
<Set name="name">demo2</Set>
|
||||
</Get>
|
||||
</Ref>
|
||||
</Configure>
|
||||
</Configure>
|
||||
----
|
||||
|
||||
The XML above is equivalent to the following Java code:
|
||||
|
@ -72,7 +72,7 @@ bar.init(false);
|
|||
foo.setNested(bar);
|
||||
|
||||
bar.setWibble(20);
|
||||
bar.getParent().setName("demo2");
|
||||
bar.getParent().setName("demo2");
|
||||
----
|
||||
|
||||
==== Overview
|
||||
|
@ -80,41 +80,27 @@ bar.getParent().setName("demo2");
|
|||
===== Understanding DTD and Parsing
|
||||
|
||||
The document type descriptor
|
||||
(link:{GITBROWSEURL}/jetty-xml/src/main/resources/org/eclipse/jetty/xml/configure_9_0.dtd?h=release-9[configure.dtd])
|
||||
describes all valid elements in a Jetty XML configuration file using the
|
||||
Jetty IoC format. The first two lines of an XML must reference the DTD
|
||||
to be used to validate the XML like:
|
||||
(link:{GITBROWSEURL}/jetty-xml/src/main/resources/org/eclipse/jetty/xml/configure_9_0.dtd?h=release-9[configure.dtd]) describes all valid elements in a Jetty XML configuration file using the Jetty IoC format.
|
||||
The first two lines of an XML must reference the DTD to be used to validate the XML like:
|
||||
|
||||
[source, xml, subs="{sub-order}"]
|
||||
----
|
||||
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE Configure PUBLIC "-//Mort Bay Consulting//DTD Configure//EN" "http://www.eclipse.org/jetty/configure_9_0.dtd">
|
||||
...
|
||||
|
||||
|
||||
----
|
||||
|
||||
Typcically a good XML editor will fetch the DTD from the URL and use it
|
||||
to give syntax highlighting and validation while a configuration file is
|
||||
being edited. Some editors also allows DTD files to be locally cached.
|
||||
The URL may point to configure.dtd if you want the latest current
|
||||
version, or to a specific version like configure_9_0.dtd if you want a
|
||||
particular validation feature set.
|
||||
Typcically a good XML editor will fetch the DTD from the URL and use it to give syntax highlighting and validation while a configuration file is being edited.
|
||||
Some editors also allows DTD files to be locally cached.
|
||||
The URL may point to configure.dtd if you want the latest current version, or to a specific version like configure_9_0.dtd if you want a particular validation feature set.
|
||||
|
||||
Files that conform to the configure.dtd format are processed in Jetty by
|
||||
the `XmlConfiguration` class which may also validate the XML (using a
|
||||
version of the DTD from the classes jar file), but is by default run in
|
||||
a forgiving mode that tries to work around validation failures.
|
||||
Files that conform to the configure.dtd format are processed in Jetty by the `XmlConfiguration` class which may also validate the XML (using a version of the DTD from the classes jar file), but is by default run in a forgiving mode that tries to work around validation failures.
|
||||
|
||||
===== Jetty XML Configuration Scope
|
||||
|
||||
The configuration of object instances with Jetty IoC XML is done on a
|
||||
scoped basis, so that for any given XML element there is a corresponding
|
||||
Object in scope and the nested XML elements apply to that. The outer
|
||||
most scope is given by a Configure element and elements like Call, New
|
||||
and Get establish new scopes. The following example uses the name fields
|
||||
to explain the scope
|
||||
The configuration of object instances with Jetty IoC XML is done on a scoped basis, so that for any given XML element there is a corresponding Object in scope and the nested XML elements apply to that.
|
||||
The outer most scope is given by a Configure element and elements like Call, New and Get establish new scopes.
|
||||
The following example uses the name fields to explain the scope.
|
||||
|
||||
[source, xml, subs="{sub-order}"]
|
||||
----
|
||||
|
@ -134,50 +120,36 @@ to explain the scope
|
|||
<Call name="methodOnObjectReturnedByMethodOnFooWithNoArgs"/>
|
||||
</Call>
|
||||
</Configure>
|
||||
|
||||
----
|
||||
|
||||
===== Coercing Arguments to a Type
|
||||
|
||||
When trying to match XML elements to java elements, Jetty
|
||||
XmlConfiguration may need to coerces values to match method arguments.
|
||||
By default it does so on a best effort basis, but you can also specify
|
||||
explicit types with the `type` attribute. Supported values for type are:
|
||||
String, Character, Short, Byte, Integer, Long, Boolean, Float, Double,
|
||||
char, short, byte, int, long, boolean, float, double, URL, InetAddress,
|
||||
InetAddrPort, void
|
||||
When trying to match XML elements to java elements, Jetty `XmlConfiguration` may need to coerces values to match method arguments.
|
||||
By default it does so on a best effort basis, but you can also specify explicit types with the `type` attribute.
|
||||
Supported values for type are: `String`, `Character`, `Short`, `Byte`, `Integer`, `Long`, `Boolean`, `Float`, `Double`, `char`, `short`, `byte`, `int`, `long`, `boolean`, `float`, `double`, `URL`, `InetAddress`, `InetAddrPort`, and `void`.
|
||||
|
||||
===== Referring to a Class
|
||||
|
||||
If you do not specify the classname, Jetty assumes you are calling the
|
||||
method on the object that is current in scope (eg the object of the
|
||||
surrounding Configure, New or Get clause). If the class attribute is
|
||||
specified to a fully-qualified class name, then it is either used to
|
||||
create a new instance (Configure and New elements) or is used to access
|
||||
a static (Call, Set or Get elements).
|
||||
If you do not specify the classname, Jetty assumes you are calling the method on the object that is current in scope (eg the object of the surrounding `Configure`, `New` or `Get` clause).
|
||||
If the class attribute is specified to a fully-qualified class name, then it is either used to create a new instance (`Configure` and `New` elements) or is used to access a static (`Call`, `Set` or `Get` elements).
|
||||
|
||||
===== Referring to an Object
|
||||
|
||||
You can use the id attribute to store a reference to the current object
|
||||
when first creating or referring to this object. You can then use the
|
||||
link:#jetty-xml-ref[Ref element] to reference the object later. The id
|
||||
must be unique for each object you create.
|
||||
You can use the id attribute to store a reference to the current object when first creating or referring to this object.
|
||||
You can then use the link:#jetty-xml-ref[Ref element] to reference the object later.
|
||||
The ID must be unique for each object you create.
|
||||
|
||||
===== Attribute vs Element Style
|
||||
|
||||
For XML elements that contain only other XML Elements, there is a choice
|
||||
of using attributes or elements style. The following is an example of
|
||||
attribute style:
|
||||
For XML elements that contain only other XML Elements, there is a choice of using attributes or elements style.
|
||||
The following is an example of attribute style:
|
||||
|
||||
....
|
||||
<Call id="result" class="org.example.SomeClass" name="someMethod" arg="value0,value1"/>
|
||||
....
|
||||
|
||||
Attribute style has the benefit of brevity, but is limited by: values
|
||||
can only be Strings; multivalued items can not contain ','; values may
|
||||
not be subject to property expansion or other elements that return
|
||||
values. Thus the more verbose element style is available and the
|
||||
following is semantically equivalent to the attribute style above:
|
||||
Attribute style has the benefit of brevity, but is limited by: values can only be Strings; multivalued items can not contain ','; values may not be subject to property expansion or other elements that return values.
|
||||
Thus, the more verbose element style is available and the following is semantically equivalent to the attribute style above:
|
||||
|
||||
....
|
||||
<Call>
|
||||
|
@ -189,11 +161,8 @@ following is semantically equivalent to the attribute style above:
|
|||
</Call>
|
||||
....
|
||||
|
||||
Note that multivalued elements like Arg, must be repeated and may not be
|
||||
comma separated like they are when provided as attributes. It is
|
||||
possible to use a mix of styles and the following example shows a more
|
||||
typical example that uses property expansion as the reason for element
|
||||
style:
|
||||
Note that multivalued elements like `Arg` must be repeated and may not be comma-separated like they are when provided as attributes.
|
||||
It is possible to use a mix of styles and the following example shows a moretypical example that uses property expansion as the reason for element style:
|
||||
|
||||
....
|
||||
<Call id="result" name="someMethod">
|
||||
|
@ -205,16 +174,14 @@ style:
|
|||
</Call>
|
||||
....
|
||||
|
||||
Attributes may not be expressed as elements when their parent element is
|
||||
one that contains data. Thus Arg, Item, Set, Put and Get elements may
|
||||
not have their attributes expressed as elements.
|
||||
Attributes may not be expressed as elements when their parent element is one that contains data.
|
||||
Thus `Arg`, `Item`, `Set`, `Put` and `Get` elements may not have their attributes expressed as elements.
|
||||
|
||||
[[jetty-xml-configure]]
|
||||
==== <Configure>
|
||||
|
||||
This is the root element that specifies the class of object that is to
|
||||
be configured. It is usually either the Server, in `jetty.xml`, or a
|
||||
WebAppContext in `jetty-web.xml`.
|
||||
This is the root element that specifies the class of object that is to be configured.
|
||||
It is usually either the Server, in `jetty.xml`, or a `WebAppContext` in `jetty-web.xml`.
|
||||
|
||||
[cols=",,",options="header",]
|
||||
|=======================================================================
|
||||
|
@ -226,8 +193,8 @@ You can use this to break up configuration of an object (such as the
|
|||
Server) across multiple files.
|
||||
|
||||
|class |no |The fully qualified classname of the object to be
|
||||
configured. Could be org.eclipse.jetty.server.Server,
|
||||
org.eclipse.jetty.webapp.WebAppContext, a handler, etc.
|
||||
configured. Could be `org.eclipse.jetty.server.Server`,
|
||||
`org.eclipse.jetty.webapp.WebAppContext`, a handler, etc.
|
||||
|=======================================================================
|
||||
|
||||
===== Can Contain
|
||||
|
@ -246,7 +213,7 @@ link:#jetty-xml-property[Property element]
|
|||
----
|
||||
<Configure class="org.eclipse.jetty.server.Server">
|
||||
<Set name="port">8080</Set>
|
||||
</Configure>
|
||||
</Configure>
|
||||
----
|
||||
|
||||
This is equivalent to:
|
||||
|
@ -254,46 +221,43 @@ This is equivalent to:
|
|||
[source, java, subs="{sub-order}"]
|
||||
----
|
||||
org.eclipse.jetty.server.Server server = new org.eclipse.jetty.server.Server();
|
||||
server.setPort(8080);
|
||||
server.setPort(8080);
|
||||
----
|
||||
|
||||
====== Using id to break up configuration of one object across multiple
|
||||
files
|
||||
====== Using id to break up configuration of one object across multiple files
|
||||
|
||||
(etc/jetty.xml)
|
||||
In `etc/jetty.xml`:
|
||||
|
||||
[source, xml, subs="{sub-order}"]
|
||||
----
|
||||
<Configure id="Server" class="org.eclipse.jetty.server.Server">
|
||||
<!-- basic configuration here -->
|
||||
</Configure>
|
||||
</Configure>
|
||||
----
|
||||
|
||||
(etc/jetty-logging.xml)
|
||||
In `etc/jetty-logging.xml`:
|
||||
|
||||
[source, xml, subs="{sub-order}"]
|
||||
----
|
||||
<Configure id="Server" class="org.eclipse.jetty.server.Server">
|
||||
<!-- assumes that you have the basic server configuration set up; this file only contains additional configuration for logging -->
|
||||
</Configure>
|
||||
</Configure>
|
||||
----
|
||||
|
||||
Then run the combined configuration using:
|
||||
|
||||
....
|
||||
java -jar start.jar etc/jetty.xml jetty-logging.xml
|
||||
java -jar start.jar etc/jetty.xml jetty-logging.xml
|
||||
....
|
||||
|
||||
[[jetty-xml-set]]
|
||||
==== <Set>
|
||||
|
||||
A Set element maps to a call to a setter method or field on the current
|
||||
object. It can contain text and/or elements such as Call, New,
|
||||
SystemProperty, etc., as values. The name and optional type attributes
|
||||
are used to select the setter method. If you do not specify a value
|
||||
type, white space is trimmed out of the value. If it contains multiple
|
||||
elements as values, they are added as strings before being converted to
|
||||
any specified type.
|
||||
A Set element maps to a call to a setter method or field on the current object.
|
||||
It can contain text and/or elements such as `Call`, `New`, `SystemProperty`, etc., as values.
|
||||
The name and optional type attributes are used to select the setter method.
|
||||
If you do not specify a value type, white space is trimmed out of the value.
|
||||
If it contains multiple elements as values, they are added as strings before being converted to any specified type.
|
||||
|
||||
[cols=",,",options="header",]
|
||||
|=======================================================================
|
||||
|
@ -325,7 +289,7 @@ link:#jetty-xml-property[Property element]
|
|||
----
|
||||
<Configure id="server" class="org.eclipse.jetty.server.Server">
|
||||
<Set name="port">8080</Set>
|
||||
</Configure>
|
||||
</Configure>
|
||||
----
|
||||
|
||||
====== Set via a System Property
|
||||
|
@ -334,7 +298,7 @@ link:#jetty-xml-property[Property element]
|
|||
----
|
||||
<Configure id="server" class="org.eclipse.jetty.server.Server">
|
||||
<Set name="port"><SystemProperty name="jetty.http.port" /></Set>
|
||||
</Configure>
|
||||
</Configure>
|
||||
----
|
||||
|
||||
====== Creating a NewObject and Setting It on the Server
|
||||
|
@ -348,7 +312,7 @@ link:#jetty-xml-property[Property element]
|
|||
<Set name="maxThreads">1000</Set>
|
||||
</New>
|
||||
</Set>
|
||||
</Configure>
|
||||
</Configure>
|
||||
----
|
||||
|
||||
This is equivalent to:
|
||||
|
@ -361,7 +325,7 @@ org.eclipse.jetty.util.thread.QueuedThreadPool threadPool = new org.eclipse.jett
|
|||
threadPool.setMinThreads(10);
|
||||
threadPool.setMaxThreads(1000);
|
||||
|
||||
server.setThreadPool(threadPool);
|
||||
server.setThreadPool(threadPool);
|
||||
----
|
||||
|
||||
====== Invoking a Static Setter
|
||||
|
@ -370,15 +334,14 @@ server.setThreadPool(threadPool);
|
|||
----
|
||||
<Configure id="server" class="org.eclipse.jetty.server.Server">
|
||||
<Set class="org.eclipse.jetty.util.log.Log" name="logToParent">loggerName</Set>
|
||||
</Configure">
|
||||
</Configure>
|
||||
----
|
||||
|
||||
[[jetty-xml-get]]
|
||||
==== <Get>
|
||||
|
||||
A Get element maps to a call to a getter method or field on the current
|
||||
object. It can contain nested elements such as Set, Put, Call, etc.;
|
||||
these act on the object returned by the Get call.
|
||||
A Get element maps to a call to a getter method or field on the current object.
|
||||
It can contain nested elements such as `Set`, `Put`, `Call`, etc.; these act on the object returned by the `Get` call.
|
||||
|
||||
[cols=",,",options="header",]
|
||||
|=======================================================================
|
||||
|
@ -406,14 +369,14 @@ link:#jetty-xml-property[Property element]
|
|||
|
||||
====== Basic Example
|
||||
|
||||
This simple example doesn't do much on its own. You would normally use
|
||||
this in conjunction with a <Ref id="Logger" />.
|
||||
This simple example doesn't do much on its own.
|
||||
You would normally use this in conjunction with a `<Ref id="Logger" />`.
|
||||
|
||||
[source, xml, subs="{sub-order}"]
|
||||
----
|
||||
<Configure id="server" class="org.eclipse.jetty.server.Server">
|
||||
<Get id="Logger" class="org.eclipse.jetty.util.log.Log" name="log"/>
|
||||
</Configure>
|
||||
</Configure>
|
||||
----
|
||||
|
||||
====== Invoking a Static Getter and Call Methods on the Returned Object
|
||||
|
@ -426,18 +389,16 @@ this in conjunction with a <Ref id="Logger" />.
|
|||
<Arg>Server version is: <Get class="org.eclipse.jetty.server.Server" name="version"/></Arg>
|
||||
</Call>
|
||||
</Get>
|
||||
</Configure>
|
||||
</Configure>
|
||||
----
|
||||
|
||||
[[jetty-xml-put]]
|
||||
==== <Put>
|
||||
|
||||
A Put element maps to a call to a put method on the current object,
|
||||
which must implement the Map interface. It can contain text and/or
|
||||
elements such as Call, New, SystemProperty, etc. as values. If you do
|
||||
not specify a no value type, white space is trimmed out of the value. If
|
||||
it contains multiple elements as values, they are added as strings
|
||||
before being converted to any specified type.
|
||||
A Put element maps to a call to a put method on the current object, which must implement the Map interface.
|
||||
It can contain text and/or elements such as `Call`, `New`, `SystemProperty`, etc. as values.
|
||||
If you do not specify a no value type, white space is trimmed out of the value.
|
||||
If it contains multiple elements as values, they are added as strings before being converted to any specified type.
|
||||
|
||||
[cols=",,",options="header",]
|
||||
|=======================================================================
|
||||
|
@ -450,7 +411,7 @@ Arg for how to define null and empty string values.
|
|||
|
||||
===== Can Contain
|
||||
|
||||
value text , link:#jetty-xml-get[Get element], link:#jetty-xml-call[Call
|
||||
value text, link:#jetty-xml-get[Get element], link:#jetty-xml-call[Call
|
||||
element], link:#jetty-xml-new[New element], link:#jetty-xml-ref[Ref
|
||||
element], link:#jetty-xml-array[Array element], link:#jetty-xml-map[Map
|
||||
element], link:#jetty-xml-system-property[System Property element],
|
||||
|
@ -462,17 +423,15 @@ link:#jetty-xml-property[Property element]
|
|||
----
|
||||
<Get name="someKindOfMap">
|
||||
<Put name="keyName">objectValue</Put>
|
||||
</Get>
|
||||
</Get>
|
||||
----
|
||||
|
||||
[[jetty-xml-call]]
|
||||
==== <Call>
|
||||
|
||||
A Call element maps to an arbitrary call to a method on the current
|
||||
object. It can contain a sequence of Arg elements followed by a sequence
|
||||
of configuration elements, such as Set, Put, Call. The <Arg>s are passed
|
||||
as arguments to the method; the sequence of configuration elements act
|
||||
on the object returned by the original call.
|
||||
A `Call` element maps to an arbitrary call to a method on the current object.
|
||||
It can contain a sequence of Arg elements followed by a sequence of configuration elements, such as Set, Put, Call.
|
||||
The <Arg>s are passed as arguments to the method; the sequence of configuration elements act on the object returned by the original call.
|
||||
|
||||
[cols=",,",options="header",]
|
||||
|=======================================================================
|
||||
|
@ -507,7 +466,7 @@ element], link:#jetty-xml-property[Property element]
|
|||
<Call name="doFoo">
|
||||
<Arg>bar</Arg>
|
||||
<Set name="test">1, 2, 3</Set>
|
||||
</Call>
|
||||
</Call>
|
||||
----
|
||||
|
||||
This is equivalent to:
|
||||
|
@ -515,7 +474,7 @@ This is equivalent to:
|
|||
[source, java, subs="{sub-order}"]
|
||||
----
|
||||
Object o2 = o1.doFoo("bar");
|
||||
o2.setTest("1, 2, 3");
|
||||
o2.setTest("1, 2, 3");
|
||||
----
|
||||
|
||||
====== Invoking a static method
|
||||
|
@ -524,14 +483,14 @@ o2.setTest("1, 2, 3");
|
|||
----
|
||||
<Call class="com.acme.Foo" name="setString">
|
||||
<Arg>somestring</Arg>
|
||||
</Call>
|
||||
</Call>
|
||||
----
|
||||
|
||||
which is equivalent to:
|
||||
Which is equivalent to:
|
||||
|
||||
[source, java, subs="{sub-order}"]
|
||||
----
|
||||
com.acme.Foo.setString("somestring");
|
||||
com.acme.Foo.setString("somestring");
|
||||
----
|
||||
|
||||
====== Invoking the Actual MethodInstead of Relying on Getter/Setter Magic
|
||||
|
@ -545,15 +504,15 @@ com.acme.Foo.setString("somestring");
|
|||
<Ref refid="port"/>
|
||||
</Arg>
|
||||
</Call>
|
||||
</Configure>
|
||||
</Configure>
|
||||
----
|
||||
|
||||
which is equivalent to:
|
||||
Which is equivalent to:
|
||||
|
||||
[source, java, subs="{sub-order}"]
|
||||
----
|
||||
org.mortbay.jetty.Server server = new org.mortbay.jetty.Server();
|
||||
com.acme.Environment.setPort( server.getPort() );
|
||||
com.acme.Environment.setPort( server.getPort() );
|
||||
----
|
||||
|
||||
[[jetty-xml-arg]]
|
||||
|
@ -562,13 +521,11 @@ com.acme.Environment.setPort( server.getPort() );
|
|||
An Arg element can be an argument of either a method or a constructor.
|
||||
Use it within xref:jetty-syntax-call[] and xref:jetty-syntax-new[].
|
||||
|
||||
It can contain text and/or elements, such as Call, New, SystemProperty,
|
||||
etc., as values. The optional type attribute can force the type of the
|
||||
value. If you don't specify a type, white space is trimmed out of the
|
||||
value. If it contains multiple elements as values, they are added as
|
||||
strings before being converted to any specified type. Simple String
|
||||
arguments can also be specified as a string separated arg attribute on
|
||||
the parent element.
|
||||
It can contain text and/or elements, such as `Call`, `New`, `SystemProperty`, etc., as values.
|
||||
The optional type attribute can force the type of the value.
|
||||
If you don't specify a type, white space is trimmed out of the value.
|
||||
If it contains multiple elements as values, they are added as strings before being converted to any specified type.
|
||||
Simple `String` arguments can also be specified as a string separated arg attribute on the parent element.
|
||||
|
||||
[cols=",,",options="header",]
|
||||
|=======================================================================
|
||||
|
@ -597,7 +554,7 @@ link:#jetty-xml-property[Property element]
|
|||
<Arg>1</Arg> <!-- int, long, short, float, double -->
|
||||
<Arg><Ref refid="foo" /></Arg> <!-- any object; reference a previously created object with id "foo", and pass it as a parameter -->
|
||||
<Arg></Arg> <!-- null value -->
|
||||
<Arg type="String"></Arg> <!-- empty string "" ->
|
||||
<Arg type="String"></Arg> <!-- empty string "" -->
|
||||
----
|
||||
|
||||
====== Coercing Type
|
||||
|
@ -606,13 +563,12 @@ This explicitly coerces the type to a boolean:
|
|||
|
||||
[source, xml, subs="{sub-order}"]
|
||||
----
|
||||
<Arg type="boolean">False</Arg>
|
||||
<Arg type="boolean">False</Arg>
|
||||
----
|
||||
|
||||
====== As a Parameter
|
||||
|
||||
Here are a couple of examples of link:#jetty-xml-arg[Arg element] being
|
||||
used as a parameter to methods and to constructors:
|
||||
Here are a couple of examples of link:#jetty-xml-arg[Arg element] being used as a parameter to methods and to constructors:
|
||||
|
||||
[source, xml, subs="{sub-order}"]
|
||||
----
|
||||
|
@ -622,14 +578,14 @@ used as a parameter to methods and to constructors:
|
|||
<Arg>bar</Arg>
|
||||
</New>
|
||||
</Arg>
|
||||
</Call>
|
||||
</Call>
|
||||
----
|
||||
|
||||
This is equivalent to:
|
||||
|
||||
[source, java, subs="{sub-order}"]
|
||||
----
|
||||
com.acme.Environment.setFoo(new com.acme.Foo("bar"));
|
||||
com.acme.Environment.setFoo(new com.acme.Foo("bar"));
|
||||
----
|
||||
|
||||
[source, xml, subs="{sub-order}"]
|
||||
|
@ -640,26 +596,24 @@ com.acme.Environment.setFoo(new com.acme.Foo("bar"));
|
|||
<Arg>2</Arg>
|
||||
</Call>
|
||||
</Arg>
|
||||
</New>
|
||||
</New>
|
||||
----
|
||||
|
||||
This is equivalent to:
|
||||
|
||||
[source, java, subs="{sub-order}"]
|
||||
----
|
||||
new com.acme.Baz(com.acme.MyStaticObjectFactory.createObject(2));
|
||||
new com.acme.Baz(com.acme.MyStaticObjectFactory.createObject(2));
|
||||
----
|
||||
|
||||
[[jetty-xml-new]]
|
||||
==== <New>
|
||||
|
||||
Instantiates an object. Equivalent to new in Java, and allows the
|
||||
creation of a new object. A New element can contain a sequence of
|
||||
link:#jetty-xml-arg[Arg element]'s, followed by a sequence of
|
||||
configuration elements (Set, Put, etc). link:#jetty-xml-arg[Arg
|
||||
element]'s are used to select a constructor for the object to be
|
||||
created. The sequence of configuration elements then acts on the
|
||||
newly-created object.
|
||||
Instantiates an object.
|
||||
Equivalent to `new` in Java, and allows the creation of a new object.
|
||||
A `New` element can contain a sequence of link:#jetty-xml-arg[`Arg` element]'s, followed by a sequence of configuration elements (`Set`, `Put`, etc).
|
||||
link:#jetty-xml-arg[`Arg` element]'s are used to select a constructor for the object to be created.
|
||||
The sequence of configuration elements then acts on the newly-created object.
|
||||
|
||||
[cols=",,",options="header",]
|
||||
|=======================================================================
|
||||
|
@ -691,28 +645,28 @@ element], link:#jetty-xml-property[Property element]
|
|||
----
|
||||
<New class="com.acme.Foo">
|
||||
<Arg>bar</Arg>
|
||||
</New>
|
||||
</New>
|
||||
----
|
||||
|
||||
which is equivalent to:
|
||||
Which is equivalent to:
|
||||
|
||||
[source, java, subs="{sub-order}"]
|
||||
----
|
||||
com.acme.Foo foo = new com.acme.Foo("bar");
|
||||
com.acme.Foo foo = new com.acme.Foo("bar");
|
||||
----
|
||||
|
||||
====== Instantiate with the Default Constructor
|
||||
|
||||
[source, xml, subs="{sub-order}"]
|
||||
----
|
||||
<New class="com.acme.Foo" />
|
||||
<New class="com.acme.Foo" />
|
||||
----
|
||||
|
||||
which is equivalent to:
|
||||
Which is equivalent to:
|
||||
|
||||
[source, java, subs="{sub-order}"]
|
||||
----
|
||||
com.acme.Foo foo = new com.acme.Foo();
|
||||
com.acme.Foo foo = new com.acme.Foo();
|
||||
----
|
||||
|
||||
====== Instantiate with Multiple Arguments, Then Configuring Further
|
||||
|
@ -723,10 +677,10 @@ com.acme.Foo foo = new com.acme.Foo();
|
|||
<Arg>bar</Arg>
|
||||
<Arg>baz</Arg>
|
||||
<Set name="test">1, 2, 3</Set>
|
||||
</New>
|
||||
</New>
|
||||
----
|
||||
|
||||
which is equivalent to:
|
||||
Which is equivalent to:
|
||||
|
||||
[source, java, subs="{sub-order}"]
|
||||
----
|
||||
|
@ -737,17 +691,14 @@ foo.setTest("1, 2, 3");
|
|||
[[jetty-xml-ref]]
|
||||
==== <Ref>
|
||||
|
||||
A Ref element allows a previously created object to be referenced by a
|
||||
unique id. It can contain a sequence of elements, such as Set or Put
|
||||
which then act on the referenced object. You can also use a Ref element
|
||||
as a value for other elements such as Set and Arg.
|
||||
A `Ref` element allows a previously created object to be referenced by a unique id.
|
||||
It can contain a sequence of elements, such as `Set` or `Put` which then act on the referenced object.
|
||||
You can also use a `Ref` element as a value for other elements such as `Set` and `Arg`.
|
||||
|
||||
The Ref element provides convenience and eases readability. You can
|
||||
usually achieve the effect of the Ref by nesting elements (method
|
||||
calls), but this can get complicated very easily. The Ref element makes
|
||||
it possible to refer to the same object if you're using it multiple
|
||||
times, or passing it into multiple methods. It also makes it possible to
|
||||
split up configuration across multiple files.
|
||||
The `Ref` element provides convenience and eases readability.
|
||||
You can usually achieve the effect of the `Ref` by nesting elements (method calls), but this can get complicated very easily.
|
||||
The Ref element makes it possible to refer to the same object if you're using it multiple times, or passing it into multiple methods.
|
||||
It also makes it possible to split up configuration across multiple files.
|
||||
|
||||
[cols=",,",options="header",]
|
||||
|=======================================================================
|
||||
|
@ -768,13 +719,12 @@ link:#jetty-xml-property[Property element]
|
|||
|
||||
====== Basic example
|
||||
|
||||
Use the referenced object as an argument to a method call or
|
||||
constructor:
|
||||
Use the referenced object as an argument to a method call or constructor:
|
||||
|
||||
[source, xml, subs="{sub-order}"]
|
||||
----
|
||||
<Get id="foo" name="xFoo" />
|
||||
<Set name="test"><Ref refid="foo"/></Set>
|
||||
<Set name="test"><Ref refid="foo"/></Set>
|
||||
----
|
||||
|
||||
This is equivalent to:
|
||||
|
@ -782,7 +732,7 @@ This is equivalent to:
|
|||
[source, java, subs="{sub-order}"]
|
||||
----
|
||||
foo = getXFoo();
|
||||
setSomeMethod(foo);
|
||||
setSomeMethod(foo);
|
||||
----
|
||||
|
||||
====== Manipulating the Object Returned by Ref
|
||||
|
@ -792,7 +742,7 @@ setSomeMethod(foo);
|
|||
<Get id="foo" name="xFoo" />
|
||||
<Ref refid="foo">
|
||||
<Set name="test">1, 2, 3</Set>
|
||||
</Ref>
|
||||
</Ref>
|
||||
----
|
||||
|
||||
This is equivalent to:
|
||||
|
@ -800,13 +750,13 @@ This is equivalent to:
|
|||
[source, java, subs="{sub-order}"]
|
||||
----
|
||||
foo = getXFoo();
|
||||
foo.setTest("1, 2, 3");
|
||||
foo.setTest("1, 2, 3");
|
||||
----
|
||||
|
||||
====== Ref vs. Nested Elements
|
||||
|
||||
Here is an example of the difference in syntax between using the Ref
|
||||
element, and nesting method calls. They are exactly equivalent:
|
||||
Here is an example of the difference in syntax between using the `Ref` element, and nesting method calls.
|
||||
They are exactly equivalent:
|
||||
|
||||
[source, xml, subs="{sub-order}"]
|
||||
----
|
||||
|
@ -822,11 +772,10 @@ element, and nesting method calls. They are exactly equivalent:
|
|||
<Get class="org.eclipse.jetty.util.log.Log" name="log">
|
||||
<Set name="debugEnabled">true</Set>
|
||||
</Get>
|
||||
</Configure>
|
||||
</Configure>
|
||||
----
|
||||
|
||||
Here is a more practical example, taken from the handler configuration
|
||||
section in ` etc/jetty.xml`:
|
||||
Here is a more practical example, taken from the handler configuration section in `etc/jetty.xml`:
|
||||
|
||||
[source, xml, subs="{sub-order}"]
|
||||
----
|
||||
|
@ -862,13 +811,13 @@ section in ` etc/jetty.xml`:
|
|||
<!-- configure the RequestLogHandler object ("RequestLog") that we created earlier -->
|
||||
<Ref refid="RequestLog">
|
||||
....
|
||||
</Ref>
|
||||
</Ref>
|
||||
----
|
||||
|
||||
[[jetty-xml-array]]
|
||||
==== <Array>
|
||||
|
||||
An Array element allows the creation of a new array.
|
||||
An `Array` element allows the creation of a new array.
|
||||
|
||||
[cols=",,",options="header",]
|
||||
|==================================================================
|
||||
|
@ -895,13 +844,13 @@ This is equivalent to:
|
|||
|
||||
[source, java, subs="{sub-order}"]
|
||||
----
|
||||
String[] a = new String[] { "value0", new String("value1") };
|
||||
String[] a = new String[] { "value0", new String("value1") };
|
||||
----
|
||||
|
||||
[[jetty-xml-item]]
|
||||
==== <Item>
|
||||
|
||||
An Item element defines an entry for Array and Map elements.
|
||||
An `Item` element defines an entry for Array and Map elements.
|
||||
|
||||
[cols=",,",options="header",]
|
||||
|=======================================================================
|
||||
|
@ -921,8 +870,7 @@ link:#jetty-xml-property[Property element]
|
|||
[[jetty-xml-map]]
|
||||
==== <Map>
|
||||
|
||||
A Map element allows the creation of a new HashMap and to populate it
|
||||
with (key, value) pairs.
|
||||
A `Map` element allows the creation of a new HashMap and to populate it with `(key, value)` pairs.
|
||||
|
||||
[cols=",,",options="header",]
|
||||
|================================================================
|
||||
|
@ -943,7 +891,7 @@ link:#jetty-xml-entry[Entry element]
|
|||
<Item>keyName</Item>
|
||||
<Item><New class="java.lang.String"><Arg>value1</Arg></New></Item>
|
||||
</Entry>
|
||||
</Map>
|
||||
</Map>
|
||||
----
|
||||
|
||||
This is equivalent to:
|
||||
|
@ -951,14 +899,13 @@ This is equivalent to:
|
|||
[source, java, subs="{sub-order}"]
|
||||
----
|
||||
Map m = new HashMap();
|
||||
m.put("keyName", new String("value1"));
|
||||
m.put("keyName", new String("value1"));
|
||||
----
|
||||
|
||||
[[jetty-xml-entry]]
|
||||
==== <Entry>
|
||||
|
||||
An Entry element contains a key-value link:#jetty-xml-item[Item element]
|
||||
pair for a Map.
|
||||
An `Entry` element contains a key-value link:#jetty-xml-item[Item element] pair for a `Map`.
|
||||
|
||||
===== Can Contain
|
||||
|
||||
|
@ -967,8 +914,8 @@ link:#jetty-xml-item[Item element]
|
|||
[[jetty-xml-system-property]]
|
||||
==== <SystemProperty>
|
||||
|
||||
A SystemProperty element gets the value of a JVM system property. It can
|
||||
be used within elements that accept values, such as Set, Put, Arg.
|
||||
A `SystemProperty` element gets the value of a JVM system property.
|
||||
It can be used within elements that accept values, such as `Set`, `Put`, `Arg`.
|
||||
|
||||
[cols=",,",options="header",]
|
||||
|=======================================================================
|
||||
|
@ -983,31 +930,30 @@ later.
|
|||
|
||||
===== Can Contain
|
||||
|
||||
Only attributes as Elements (Id, Name, Default).
|
||||
Only attributes as Elements (`Id`, `Name`, `Default`).
|
||||
|
||||
===== Example
|
||||
|
||||
[source, xml, subs="{sub-order}"]
|
||||
----
|
||||
<SystemProperty name="jetty.http.port" default="8080"/>
|
||||
<SystemProperty name="jetty.http.port" default="8080"/>
|
||||
----
|
||||
|
||||
That is equivalent to:
|
||||
|
||||
[source, java, subs="{sub-order}"]
|
||||
----
|
||||
System.getProperty("jetty.http.port", "8080");
|
||||
System.getProperty("jetty.http.port", "8080");
|
||||
----
|
||||
|
||||
Both try to retrieve the value of jetty.http.port. If jetty.http.port is
|
||||
not set, then 8080 is used.
|
||||
Both try to retrieve the value of `jetty.http.port`.
|
||||
If `jetty.http.port` is not set, then 8080 is used.
|
||||
|
||||
[[jetty-xml-property]]
|
||||
==== <Property>
|
||||
|
||||
A Property element allows arbitrary properties to be retrieved by name.
|
||||
It can contain a sequence of elements, such as Set, Put, Call that act
|
||||
on the retrieved object.
|
||||
A `Property` element allows arbitrary properties to be retrieved by name.
|
||||
It can contain a sequence of elements, such as `Set`, `Put`, `Call` that act on the retrieved object.
|
||||
|
||||
[cols=",,",options="header",]
|
||||
|=======================================================================
|
||||
|
@ -1020,17 +966,13 @@ on the retrieved object.
|
|||
later.
|
||||
|=======================================================================
|
||||
|
||||
The `name` attribute may be a comma separated list of property names,
|
||||
with the first property name being the "official" name, and the others
|
||||
names being old, deprecated property names that are kept for backward
|
||||
compatibility. A warning log is issued when deprecated property names
|
||||
are used. The `default` attribute contains the value to use in case none
|
||||
of the property names is found.
|
||||
The `Name` attribute may be a comma separated list of property names, with the first property name being the "official" name, and the others names being old, deprecated property names that are kept for backward compatibility.
|
||||
A warning log is issued when deprecated property names are used.
|
||||
The `Default` attribute contains the value to use in case none of the property names is found.
|
||||
|
||||
===== Can Contain
|
||||
|
||||
The attributes may be expressed as contained Elements (Id, Name,
|
||||
Default).
|
||||
The attributes may be expressed as contained Elements (`Id`, `Name`, `Default`).
|
||||
|
||||
===== Example
|
||||
|
||||
|
@ -1040,5 +982,5 @@ Default).
|
|||
<Call id="jdbcIdMgr" name="getAttribute">
|
||||
<Arg>jdbcIdMgr</Arg>
|
||||
</Call>
|
||||
</Property>
|
||||
</Property>
|
||||
----
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
=== Jetty XML Usage
|
||||
|
||||
Jetty provides an XML-based configuration.
|
||||
It is grounded in Java's Reflection API. Classes in the java.lang.reflect represent Java methods and classes, such that you can instantiate objects and invoke their methods based on their names and argument types.
|
||||
It is grounded in Java's Reflection API. Classes in the `java.lang.reflect` represent Java methods and classes, such that you can instantiate objects and invoke their methods based on their names and argument types.
|
||||
Behind the scenes, Jetty's XML config parser translates the XML elements and attributes into Reflection calls.
|
||||
|
||||
[[using-jettyxml]]
|
||||
|
@ -28,7 +28,7 @@ To use `jetty.xml`, specify it as a configuration file when running Jetty.
|
|||
|
||||
[source, java, subs="{sub-order}"]
|
||||
----
|
||||
java -jar start.jar etc/jetty.xml
|
||||
java -jar start.jar etc/jetty.xml
|
||||
----
|
||||
|
||||
____
|
||||
|
@ -48,24 +48,24 @@ If you use the same ID across multiple configuration files, those configurations
|
|||
[[setting-parameters-in-configuration-files]]
|
||||
==== Setting Parameters in Configuration Files
|
||||
|
||||
You can set parameters in configuration files either with system properties (using ` <SystemProperty>`) or properties files (using `<Property>`) passed via the command line.
|
||||
You can set parameters in configuration files either with system properties (using `<SystemProperty>`) or properties files (using `<Property>`) passed via the command line.
|
||||
For example, this code in `jetty.xml` allows the port to be defined on the command line, falling back onto `8080`if the port is not specified:
|
||||
|
||||
[source, xml, subs="{sub-order}"]
|
||||
----
|
||||
<Set name="port"><SystemProperty name="jetty.http.port" default="8080"/></Set>
|
||||
<Set name="port"><SystemProperty name="jetty.http.port" default="8080"/></Set>
|
||||
----
|
||||
|
||||
Then you modify the port while running Jetty by using this command:
|
||||
|
||||
[source, java, subs="{sub-order}"]
|
||||
----
|
||||
java -Djetty.http.port=8888 -jar start.jar etc/jetty.xml
|
||||
java -Djetty.http.port=8888 -jar start.jar etc/jetty.xml
|
||||
----
|
||||
|
||||
An example of defining both system properties and properties files from the command line:
|
||||
|
||||
[source, java, subs="{sub-order}"]
|
||||
----
|
||||
java -Djetty.http.port=8888 -jar start.jar myjetty.properties etc/jetty.xml etc/other.xml
|
||||
java -Djetty.http.port=8888 -jar start.jar myjetty.properties etc/jetty.xml etc/other.xml
|
||||
----
|
||||
|
|
|
@ -22,33 +22,31 @@ The challenge is to do so without changing the webapp itself. You can use a `jet
|
|||
But there are some changes that `jetty.xml` cannot accomplish, for example, modifications to servlet init-params and context init-params.
|
||||
Using `webdefault.xml` is not an option because Jetty applies `webdefault.xml` to a web application _before_ the application's own `WEB-INF/web.xml`, which means that it cannot override values inside the webapp's ` web.xml`.
|
||||
|
||||
The solution is `override-web.xml`. It is a `web.xml` file that Jetty applies to a web application _after_ the application's own `WEB-INF/web.xml`, which means that it can override values or add new elements.
|
||||
You define it per-webapp, using the xref:jetty-xml-syntax[].
|
||||
The solution is `override-web.xml`.
|
||||
It is a `web.xml` file that Jetty applies to a web application _after_ the application's own `WEB-INF/web.xml`, which means that it can override values or add new elements.
|
||||
This is defined on a per-webapp basis, using the xref:jetty-xml-syntax[].
|
||||
|
||||
[[using-override-web-xml]]
|
||||
==== Using `override-web.xml`
|
||||
==== Using override-web.xml
|
||||
|
||||
You can specify the `override-web.xml` to use for an individual web application, in that webapp's xref:jetty-web-xml-config[].
|
||||
You can specify the `override-web.xml` to use for an individual web application in a deployable xml file located in Jetty webapps folder .
|
||||
For example, if you had a webapp named MyApp, you would place a deployable xml file named `myapp.xml` in `${jetty.base}/webapps` which includes an `overrideDescriptor` entry for the `override-web.xml` file.
|
||||
|
||||
[source, xml, subs="{sub-order}"]
|
||||
----
|
||||
|
||||
<Configure class="org.eclipse.jetty.webapp.WebAppContext">
|
||||
...
|
||||
<!-- Set up the path to the custom override descriptor,
|
||||
<!-- Set up the path to the custom override descriptor,
|
||||
relative to your $(jetty.home) directory or to the current directory -->
|
||||
<Set name="overrideDescriptor"><SystemProperty name="jetty.home" default="."/>/my/path/to/override-web.xml</Set>
|
||||
...
|
||||
</Configure>
|
||||
|
||||
|
||||
----
|
||||
|
||||
The equivalent in code is:
|
||||
|
||||
[source, java, subs="{sub-order}"]
|
||||
----
|
||||
|
||||
import org.eclipse.jetty.webapp.WebAppContext;
|
||||
|
||||
...
|
||||
|
@ -58,11 +56,9 @@ import org.eclipse.jetty.webapp.WebAppContext;
|
|||
//Set the path to the override descriptor, based on your $(jetty.home) directory
|
||||
wac.setOverrideDescriptor(System.getProperty("jetty.home")+"/my/path/to/override-web.xml");
|
||||
...
|
||||
|
||||
|
||||
----
|
||||
|
||||
Alternatively, use the classloader (xref:jetty-classloading[]) to get the path to the override descriptor as a resource.
|
||||
Alternatively, you can use the classloader (xref:jetty-classloading[]) to get the path to the override descriptor as a resource.
|
||||
|
||||
[[override-using-jetty-maven-plugin]]
|
||||
==== Using the Jetty Maven Plugin
|
||||
|
@ -71,7 +67,6 @@ Use the `<overrideDescriptor>` tag as follows:
|
|||
|
||||
[source, xml, subs="{sub-order}"]
|
||||
----
|
||||
|
||||
<project>
|
||||
...
|
||||
<plugins>
|
||||
|
@ -89,8 +84,6 @@ Use the `<overrideDescriptor>` tag as follows:
|
|||
</plugins>
|
||||
...
|
||||
</project>
|
||||
|
||||
|
||||
----
|
||||
|
||||
[[override-web-xml-additional-resources]]
|
||||
|
|
|
@ -38,7 +38,7 @@ You can specify a custom `webdefault.xml` for an individual web application in t
|
|||
|
||||
[source, xml, subs="{sub-order}"]
|
||||
----
|
||||
|
||||
|
||||
<Configure class="org.eclipse.jetty.webapp.WebAppContext">
|
||||
...
|
||||
<!-- Set up the absolute path to the custom webdefault.xml -->
|
||||
|
@ -46,14 +46,14 @@ You can specify a custom `webdefault.xml` for an individual web application in t
|
|||
...
|
||||
</Configure>
|
||||
|
||||
|
||||
|
||||
----
|
||||
|
||||
The equivalent in code is:
|
||||
|
||||
[source, java, subs="{sub-order}"]
|
||||
----
|
||||
|
||||
|
||||
import org.eclipse.jetty.webapp.WebAppContext;
|
||||
|
||||
...
|
||||
|
@ -64,7 +64,7 @@ import org.eclipse.jetty.webapp.WebAppContext;
|
|||
wac.setDefaultsDescriptor("/my/path/to/webdefault.xml");
|
||||
...
|
||||
|
||||
|
||||
|
||||
----
|
||||
|
||||
Alternatively, you can use a xref:jetty-classloading[] to find the resource representing your custom `webdefault.xml`.
|
||||
|
@ -86,7 +86,7 @@ Similarly, when using the link:#jetty-maven-plugin[Jetty Maven Plugin] you provi
|
|||
|
||||
[source, xml, subs="{sub-order}"]
|
||||
----
|
||||
|
||||
|
||||
<project>
|
||||
...
|
||||
<plugins>
|
||||
|
@ -105,7 +105,7 @@ Similarly, when using the link:#jetty-maven-plugin[Jetty Maven Plugin] you provi
|
|||
...
|
||||
</project>
|
||||
|
||||
|
||||
|
||||
----
|
||||
|
||||
[[webdefault-xml-additional-resources]]
|
||||
|
|
|
@ -18,7 +18,6 @@
|
|||
|
||||
package org.eclipse.jetty.http;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Objects;
|
||||
|
||||
import org.eclipse.jetty.util.StringUtil;
|
||||
|
@ -85,113 +84,9 @@ public class HttpField
|
|||
{
|
||||
if (_value == null)
|
||||
return null;
|
||||
|
||||
ArrayList<String> list = new ArrayList<>();
|
||||
int state = 0;
|
||||
int start=0;
|
||||
int end=0;
|
||||
StringBuilder builder = new StringBuilder();
|
||||
|
||||
for (int i=0;i<_value.length();i++)
|
||||
{
|
||||
char c = _value.charAt(i);
|
||||
switch(state)
|
||||
{
|
||||
case 0: // initial white space
|
||||
switch(c)
|
||||
{
|
||||
case '"': // open quote
|
||||
state=2;
|
||||
break;
|
||||
|
||||
case ',': // ignore leading empty field
|
||||
break;
|
||||
|
||||
case ' ': // more white space
|
||||
case '\t':
|
||||
break;
|
||||
|
||||
default: // character
|
||||
start=i;
|
||||
end=i;
|
||||
state=1;
|
||||
}
|
||||
break;
|
||||
|
||||
case 1: // In token
|
||||
switch(c)
|
||||
{
|
||||
case ',': // next field
|
||||
list.add(_value.substring(start,end+1));
|
||||
state=0;
|
||||
break;
|
||||
|
||||
case ' ': // more white space
|
||||
case '\t':
|
||||
break;
|
||||
|
||||
default:
|
||||
end=i;
|
||||
}
|
||||
break;
|
||||
|
||||
case 2: // In Quoted
|
||||
switch(c)
|
||||
{
|
||||
case '\\': // next field
|
||||
state=3;
|
||||
break;
|
||||
|
||||
case '"': // end quote
|
||||
list.add(builder.toString());
|
||||
builder.setLength(0);
|
||||
state=4;
|
||||
break;
|
||||
|
||||
default:
|
||||
builder.append(c);
|
||||
}
|
||||
break;
|
||||
|
||||
case 3: // In Quoted Quoted
|
||||
builder.append(c);
|
||||
state=2;
|
||||
break;
|
||||
|
||||
case 4: // WS after end quote
|
||||
switch(c)
|
||||
{
|
||||
case ' ': // white space
|
||||
case '\t': // white space
|
||||
break;
|
||||
|
||||
case ',': // white space
|
||||
state=0;
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new IllegalArgumentException("c="+(int)c);
|
||||
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
switch(state)
|
||||
{
|
||||
case 0:
|
||||
break;
|
||||
case 1:
|
||||
list.add(_value.substring(start,end+1));
|
||||
break;
|
||||
case 4:
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new IllegalArgumentException("state="+state);
|
||||
}
|
||||
|
||||
return list.toArray(new String[list.size()]);
|
||||
|
||||
QuotedCSV list = new QuotedCSV(false,_value);
|
||||
return list.getValues().toArray(new String[list.size()]);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -282,6 +282,100 @@ public class HttpFields implements Iterable<HttpField>
|
|||
return list;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Add comma separated values, but only if not already
|
||||
* present.
|
||||
* @param header The header to add the value(s) to
|
||||
* @param values The value(s) to add
|
||||
* @return True if headers were modified
|
||||
*/
|
||||
public boolean addCSV(HttpHeader header,String... values)
|
||||
{
|
||||
QuotedCSV existing = null;
|
||||
for (HttpField f : this)
|
||||
{
|
||||
if (f.getHeader()==header)
|
||||
{
|
||||
if (existing==null)
|
||||
existing = new QuotedCSV(false);
|
||||
existing.addValue(f.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
String value = addCSV(existing,values);
|
||||
if (value!=null)
|
||||
{
|
||||
add(header,value);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add comma separated values, but only if not already
|
||||
* present.
|
||||
* @param header The header to add the value(s) to
|
||||
* @param values The value(s) to add
|
||||
* @return True if headers were modified
|
||||
*/
|
||||
public boolean addCSV(String name,String... values)
|
||||
{
|
||||
QuotedCSV existing = null;
|
||||
for (HttpField f : this)
|
||||
{
|
||||
if (f.getName().equalsIgnoreCase(name))
|
||||
{
|
||||
if (existing==null)
|
||||
existing = new QuotedCSV(false);
|
||||
existing.addValue(f.getValue());
|
||||
}
|
||||
}
|
||||
String value = addCSV(existing,values);
|
||||
if (value!=null)
|
||||
{
|
||||
add(name,value);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
protected String addCSV(QuotedCSV existing,String... values)
|
||||
{
|
||||
// remove any existing values from the new values
|
||||
boolean add = true;
|
||||
if (existing!=null && !existing.isEmpty())
|
||||
{
|
||||
add = false;
|
||||
|
||||
for (int i=values.length;i-->0;)
|
||||
{
|
||||
String unquoted = QuotedCSV.unquote(values[i]);
|
||||
if (existing.getValues().contains(unquoted))
|
||||
values[i] = null;
|
||||
else
|
||||
add = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (add)
|
||||
{
|
||||
StringBuilder value = new StringBuilder();
|
||||
for (String v:values)
|
||||
{
|
||||
if (v==null)
|
||||
continue;
|
||||
if (value.length()>0)
|
||||
value.append(", ");
|
||||
value.append(v);
|
||||
}
|
||||
if (value.length()>0)
|
||||
return value.toString();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get multiple field values of the same name, split
|
||||
* as a {@link QuotedCSV}
|
||||
|
@ -292,11 +386,17 @@ public class HttpFields implements Iterable<HttpField>
|
|||
*/
|
||||
public List<String> getCSV(HttpHeader header,boolean keepQuotes)
|
||||
{
|
||||
QuotedCSV values = new QuotedCSV(keepQuotes);
|
||||
QuotedCSV values = null;
|
||||
for (HttpField f : this)
|
||||
{
|
||||
if (f.getHeader()==header)
|
||||
{
|
||||
if (values==null)
|
||||
values = new QuotedCSV(keepQuotes);
|
||||
values.addValue(f.getValue());
|
||||
return values.getValues();
|
||||
}
|
||||
}
|
||||
return values==null?Collections.emptyList():values.getValues();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -309,11 +409,17 @@ public class HttpFields implements Iterable<HttpField>
|
|||
*/
|
||||
public List<String> getCSV(String name,boolean keepQuotes)
|
||||
{
|
||||
QuotedCSV values = new QuotedCSV(keepQuotes);
|
||||
QuotedCSV values = null;
|
||||
for (HttpField f : this)
|
||||
{
|
||||
if (f.getName().equalsIgnoreCase(name))
|
||||
{
|
||||
if (values==null)
|
||||
values = new QuotedCSV(keepQuotes);
|
||||
values.addValue(f.getValue());
|
||||
return values.getValues();
|
||||
}
|
||||
}
|
||||
return values==null?Collections.emptyList():values.getValues();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -325,11 +431,18 @@ public class HttpFields implements Iterable<HttpField>
|
|||
*/
|
||||
public List<String> getQualityCSV(HttpHeader header)
|
||||
{
|
||||
QuotedQualityCSV values = new QuotedQualityCSV();
|
||||
QuotedQualityCSV values = null;
|
||||
for (HttpField f : this)
|
||||
{
|
||||
if (f.getHeader()==header)
|
||||
{
|
||||
if (values==null)
|
||||
values = new QuotedQualityCSV();
|
||||
values.addValue(f.getValue());
|
||||
return values.getValues();
|
||||
}
|
||||
}
|
||||
|
||||
return values==null?Collections.emptyList():values.getValues();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -341,11 +454,17 @@ public class HttpFields implements Iterable<HttpField>
|
|||
*/
|
||||
public List<String> getQualityCSV(String name)
|
||||
{
|
||||
QuotedQualityCSV values = new QuotedQualityCSV();
|
||||
QuotedQualityCSV values = null;
|
||||
for (HttpField f : this)
|
||||
{
|
||||
if (f.getName().equalsIgnoreCase(name))
|
||||
{
|
||||
if (values==null)
|
||||
values = new QuotedQualityCSV();
|
||||
values.addValue(f.getValue());
|
||||
return values.getValues();
|
||||
}
|
||||
}
|
||||
return values==null?Collections.emptyList():values.getValues();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -22,6 +22,8 @@ import java.util.ArrayList;
|
|||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import org.eclipse.jetty.util.QuotedStringTokenizer;
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* Implements a quoted comma separated list of values
|
||||
|
@ -52,6 +54,9 @@ public class QuotedCSV implements Iterable<String>
|
|||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/** Add and parse a value string(s)
|
||||
* @param value A value that may contain one or more Quoted CSV items.
|
||||
*/
|
||||
public void addValue(String value)
|
||||
{
|
||||
StringBuffer buffer = new StringBuffer();
|
||||
|
@ -241,6 +246,15 @@ public class QuotedCSV implements Iterable<String>
|
|||
{
|
||||
}
|
||||
|
||||
public int size()
|
||||
{
|
||||
return _values.size();
|
||||
}
|
||||
|
||||
public boolean isEmpty()
|
||||
{
|
||||
return _values.isEmpty();
|
||||
}
|
||||
|
||||
public List<String> getValues()
|
||||
{
|
||||
|
@ -252,7 +266,7 @@ public class QuotedCSV implements Iterable<String>
|
|||
{
|
||||
return _values.iterator();
|
||||
}
|
||||
|
||||
|
||||
public static String unquote(String s)
|
||||
{
|
||||
// handle trivial cases
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
package org.eclipse.jetty.http;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.Collections;
|
||||
import java.util.Enumeration;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
@ -340,7 +341,89 @@ public class HttpFieldsTest
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testGetQualityValues() throws Exception
|
||||
public void testGetCSV() throws Exception
|
||||
{
|
||||
HttpFields fields = new HttpFields();
|
||||
|
||||
fields.put("name0", "value0A,value0B");
|
||||
fields.add("name0", "value0C,value0D");
|
||||
fields.put("name1", "value1A, \"value\t, 1B\" ");
|
||||
fields.add("name1", "\"value1C\",\tvalue1D");
|
||||
|
||||
Enumeration<String> e = fields.getValues("name0");
|
||||
assertEquals(true, e.hasMoreElements());
|
||||
assertEquals(e.nextElement(), "value0A,value0B");
|
||||
assertEquals(true, e.hasMoreElements());
|
||||
assertEquals(e.nextElement(), "value0C,value0D");
|
||||
assertEquals(false, e.hasMoreElements());
|
||||
|
||||
e = Collections.enumeration(fields.getCSV("name0",false));
|
||||
assertEquals(true, e.hasMoreElements());
|
||||
assertEquals(e.nextElement(), "value0A");
|
||||
assertEquals(true, e.hasMoreElements());
|
||||
assertEquals(e.nextElement(), "value0B");
|
||||
assertEquals(true, e.hasMoreElements());
|
||||
assertEquals(e.nextElement(), "value0C");
|
||||
assertEquals(true, e.hasMoreElements());
|
||||
assertEquals(e.nextElement(), "value0D");
|
||||
assertEquals(false, e.hasMoreElements());
|
||||
|
||||
e = Collections.enumeration(fields.getCSV("name1",false));
|
||||
assertEquals(true, e.hasMoreElements());
|
||||
assertEquals(e.nextElement(), "value1A");
|
||||
assertEquals(true, e.hasMoreElements());
|
||||
assertEquals(e.nextElement(), "value\t, 1B");
|
||||
assertEquals(true, e.hasMoreElements());
|
||||
assertEquals(e.nextElement(), "value1C");
|
||||
assertEquals(true, e.hasMoreElements());
|
||||
assertEquals(e.nextElement(), "value1D");
|
||||
assertEquals(false, e.hasMoreElements());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAddQuotedCSV() throws Exception
|
||||
{
|
||||
HttpFields fields = new HttpFields();
|
||||
|
||||
fields.put("some", "value");
|
||||
fields.add("name", "\"zero\"");
|
||||
fields.add("name", "one, \"1 + 1\"");
|
||||
fields.put("other", "value");
|
||||
fields.add("name", "three");
|
||||
fields.add("name", "four, I V");
|
||||
|
||||
List<String> list = fields.getCSV("name",false);
|
||||
assertEquals("zero",HttpFields.valueParameters(list.get(0),null));
|
||||
assertEquals("one",HttpFields.valueParameters(list.get(1),null));
|
||||
assertEquals("1 + 1",HttpFields.valueParameters(list.get(2),null));
|
||||
assertEquals("three",HttpFields.valueParameters(list.get(3),null));
|
||||
assertEquals("four",HttpFields.valueParameters(list.get(4),null));
|
||||
assertEquals("I V",HttpFields.valueParameters(list.get(5),null));
|
||||
|
||||
fields.addCSV("name","six");
|
||||
list = fields.getCSV("name",false);
|
||||
assertEquals("zero",HttpFields.valueParameters(list.get(0),null));
|
||||
assertEquals("one",HttpFields.valueParameters(list.get(1),null));
|
||||
assertEquals("1 + 1",HttpFields.valueParameters(list.get(2),null));
|
||||
assertEquals("three",HttpFields.valueParameters(list.get(3),null));
|
||||
assertEquals("four",HttpFields.valueParameters(list.get(4),null));
|
||||
assertEquals("I V",HttpFields.valueParameters(list.get(5),null));
|
||||
assertEquals("six",HttpFields.valueParameters(list.get(6),null));
|
||||
|
||||
fields.addCSV("name","1 + 1","7","zero");
|
||||
list = fields.getCSV("name",false);
|
||||
assertEquals("zero",HttpFields.valueParameters(list.get(0),null));
|
||||
assertEquals("one",HttpFields.valueParameters(list.get(1),null));
|
||||
assertEquals("1 + 1",HttpFields.valueParameters(list.get(2),null));
|
||||
assertEquals("three",HttpFields.valueParameters(list.get(3),null));
|
||||
assertEquals("four",HttpFields.valueParameters(list.get(4),null));
|
||||
assertEquals("I V",HttpFields.valueParameters(list.get(5),null));
|
||||
assertEquals("six",HttpFields.valueParameters(list.get(6),null));
|
||||
assertEquals("7",HttpFields.valueParameters(list.get(7),null));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetQualityCSV() throws Exception
|
||||
{
|
||||
HttpFields fields = new HttpFields();
|
||||
|
||||
|
@ -351,7 +434,8 @@ public class HttpFieldsTest
|
|||
fields.add("name", "one;q=0.4");
|
||||
fields.add("name", "three;x=y;q=0.2;a=b,two;q=0.3");
|
||||
|
||||
List<String> list = HttpFields.qualityList(fields.getValues("name",","));
|
||||
|
||||
List<String> list = fields.getQualityCSV("name");
|
||||
assertEquals("zero",HttpFields.valueParameters(list.get(0),null));
|
||||
assertEquals("one",HttpFields.valueParameters(list.get(1),null));
|
||||
assertEquals("two",HttpFields.valueParameters(list.get(2),null));
|
||||
|
|
|
@ -320,7 +320,7 @@ public class HttpTester
|
|||
@Override
|
||||
public void parsedHeader(HttpField field)
|
||||
{
|
||||
put(field.getName(),field.getValue());
|
||||
add(field.getName(),field.getValue());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -30,10 +30,8 @@ import javax.servlet.http.HttpServletResponse;
|
|||
|
||||
import org.eclipse.jetty.http.CompressedContentFormat;
|
||||
import org.eclipse.jetty.http.HttpField;
|
||||
import org.eclipse.jetty.http.HttpFields;
|
||||
import org.eclipse.jetty.http.HttpHeader;
|
||||
import org.eclipse.jetty.http.HttpMethod;
|
||||
import org.eclipse.jetty.http.HttpVersion;
|
||||
import org.eclipse.jetty.http.MimeTypes;
|
||||
import org.eclipse.jetty.http.pathmap.PathSpecSet;
|
||||
import org.eclipse.jetty.server.HttpOutput;
|
||||
|
@ -489,11 +487,21 @@ public class GzipHandler extends HandlerWrapper implements GzipFactory
|
|||
}
|
||||
}
|
||||
|
||||
// install interceptor and handle
|
||||
out.setInterceptor(new GzipHttpOutputInterceptor(this,getVaryField(),baseRequest.getHttpChannel(),out.getInterceptor(),isSyncFlush()));
|
||||
HttpOutput.Interceptor orig_interceptor = out.getInterceptor();
|
||||
try
|
||||
{
|
||||
// install interceptor and handle
|
||||
out.setInterceptor(new GzipHttpOutputInterceptor(this,getVaryField(),baseRequest.getHttpChannel(),orig_interceptor,isSyncFlush()));
|
||||
|
||||
if (_handler!=null)
|
||||
_handler.handle(target,baseRequest, request, response);
|
||||
if (_handler!=null)
|
||||
_handler.handle(target,baseRequest, request, response);
|
||||
}
|
||||
finally
|
||||
{
|
||||
// reset interceptor if request not handled
|
||||
if (!baseRequest.isHandled() && !baseRequest.isAsyncStarted())
|
||||
out.setInterceptor(orig_interceptor);
|
||||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
|
|
@ -29,6 +29,7 @@ import org.eclipse.jetty.http.HttpFields;
|
|||
import org.eclipse.jetty.http.HttpHeader;
|
||||
import org.eclipse.jetty.http.MimeTypes;
|
||||
import org.eclipse.jetty.http.PreEncodedHttpField;
|
||||
import org.eclipse.jetty.http.QuotedCSV;
|
||||
import org.eclipse.jetty.server.HttpChannel;
|
||||
import org.eclipse.jetty.server.HttpOutput;
|
||||
import org.eclipse.jetty.server.Response;
|
||||
|
@ -190,7 +191,8 @@ public class GzipHttpOutputInterceptor implements HttpOutput.Interceptor
|
|||
}
|
||||
|
||||
// Has the Content-Encoding header already been set?
|
||||
String ce=response.getHeader("Content-Encoding");
|
||||
HttpFields fields = response.getHttpFields();
|
||||
String ce=fields.get(HttpHeader.CONTENT_ENCODING);
|
||||
if (ce != null)
|
||||
{
|
||||
LOG.debug("{} exclude by content-encoding {}",this,ce);
|
||||
|
@ -203,9 +205,13 @@ public class GzipHttpOutputInterceptor implements HttpOutput.Interceptor
|
|||
if (_state.compareAndSet(GZState.MIGHT_COMPRESS,GZState.COMMITTING))
|
||||
{
|
||||
// We are varying the response due to accept encoding header.
|
||||
HttpFields fields = response.getHttpFields();
|
||||
if (_vary != null)
|
||||
fields.add(_vary);
|
||||
{
|
||||
if (fields.contains(HttpHeader.VARY))
|
||||
fields.addCSV(HttpHeader.VARY,_vary.getValues());
|
||||
else
|
||||
fields.add(_vary);
|
||||
}
|
||||
|
||||
long content_length = response.getContentLength();
|
||||
if (content_length<0 && complete)
|
||||
|
|
|
@ -134,6 +134,8 @@ public class GzipHandlerTest
|
|||
@Override
|
||||
protected void doGet(HttpServletRequest req, HttpServletResponse response) throws ServletException, IOException
|
||||
{
|
||||
if (req.getParameter("vary")!=null)
|
||||
response.addHeader("Vary",req.getParameter("vary"));
|
||||
response.setHeader("ETag",__contentETag);
|
||||
String ifnm = req.getHeader("If-None-Match");
|
||||
if (ifnm!=null && ifnm.equals(__contentETag))
|
||||
|
@ -181,25 +183,25 @@ public class GzipHandlerTest
|
|||
HttpTester.Response response;
|
||||
|
||||
request.setMethod("GET");
|
||||
request.setURI("/ctx/content");
|
||||
request.setURI("/ctx/content?vary=Other");
|
||||
request.setVersion("HTTP/1.0");
|
||||
request.setHeader("Host","tester");
|
||||
|
||||
response = HttpTester.parseResponse(_connector.getResponses(request.generate()));
|
||||
|
||||
|
||||
assertThat(response.getStatus(),is(200));
|
||||
assertThat(response.get("Content-Encoding"),not(equalToIgnoringCase("gzip")));
|
||||
assertThat(response.get("ETag"),is(__contentETag));
|
||||
assertThat(response.get("Vary"),is("Accept-Encoding"));
|
||||
assertThat(response.getValuesList("Vary"),Matchers.contains("Other","Accept-Encoding"));
|
||||
|
||||
InputStream testIn = new ByteArrayInputStream(response.getContentBytes());
|
||||
ByteArrayOutputStream testOut = new ByteArrayOutputStream();
|
||||
IO.copy(testIn,testOut);
|
||||
|
||||
assertEquals(__content, testOut.toString("UTF8"));
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testGzipHandler() throws Exception
|
||||
{
|
||||
|
@ -208,7 +210,7 @@ public class GzipHandlerTest
|
|||
HttpTester.Response response;
|
||||
|
||||
request.setMethod("GET");
|
||||
request.setURI("/ctx/content");
|
||||
request.setURI("/ctx/content?vary=Accept-Encoding,Other");
|
||||
request.setVersion("HTTP/1.0");
|
||||
request.setHeader("Host","tester");
|
||||
request.setHeader("accept-encoding","gzip");
|
||||
|
@ -218,7 +220,7 @@ public class GzipHandlerTest
|
|||
assertThat(response.getStatus(),is(200));
|
||||
assertThat(response.get("Content-Encoding"),Matchers.equalToIgnoringCase("gzip"));
|
||||
assertThat(response.get("ETag"),is(__contentETagGzip));
|
||||
assertThat(response.get("Vary"),is("Accept-Encoding"));
|
||||
assertThat(response.getCSV("Vary",false),Matchers.contains("Accept-Encoding","Other"));
|
||||
|
||||
InputStream testIn = new GZIPInputStream(new ByteArrayInputStream(response.getContentBytes()));
|
||||
ByteArrayOutputStream testOut = new ByteArrayOutputStream();
|
||||
|
|
Loading…
Reference in New Issue