blob: ab0332f95eb8dd93878f318580f1c009645f2034 [file] [log] [blame]
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<!-- NewPage -->
<html lang="en">
<head>
<!-- Generated by javadoc -->
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>org.apache.axis2.transport.testkit (Apache Axis2)</title>
<link rel="stylesheet" type="text/css" href="../../../../../stylesheet.css" title="Style">
<script type="text/javascript" src="../../../../../script.js"></script>
</head>
<body>
<script type="text/javascript"><!--
try {
if (location.href.indexOf('is-external=true') == -1) {
parent.document.title="org.apache.axis2.transport.testkit (Apache Axis2)";
}
}
catch(err) {
}
//-->
</script>
<noscript>
<div>JavaScript is disabled on your browser.</div>
</noscript>
<!-- ========= START OF TOP NAVBAR ======= -->
<div class="topNav"><a name="navbar.top">
<!-- -->
</a>
<div class="skipNav"><a href="#skip.navbar.top" title="Skip navigation links">Skip navigation links</a></div>
<a name="navbar.top.firstrow">
<!-- -->
</a>
<ul class="navList" title="Navigation">
<li><a href="../../../../../overview-summary.html">Overview</a></li>
<li class="navBarCell1Rev">Package</li>
<li>Class</li>
<li><a href="package-use.html">Use</a></li>
<li><a href="package-tree.html">Tree</a></li>
<li><a href="../../../../../deprecated-list.html">Deprecated</a></li>
<li><a href="../../../../../index-all.html">Index</a></li>
<li><a href="../../../../../help-doc.html">Help</a></li>
</ul>
</div>
<div class="subNav">
<ul class="navList">
<li><a href="../../../../../org/apache/axis2/transport/tcp/package-summary.html">Prev&nbsp;Package</a></li>
<li><a href="../../../../../org/apache/axis2/transport/testkit/axis2/package-summary.html">Next&nbsp;Package</a></li>
</ul>
<ul class="navList">
<li><a href="../../../../../index.html?org/apache/axis2/transport/testkit/package-summary.html" target="_top">Frames</a></li>
<li><a href="package-summary.html" target="_top">No&nbsp;Frames</a></li>
</ul>
<ul class="navList" id="allclasses_navbar_top">
<li><a href="../../../../../allclasses-noframe.html">All&nbsp;Classes</a></li>
</ul>
<div>
<script type="text/javascript"><!--
allClassesLink = document.getElementById("allclasses_navbar_top");
if(window==top) {
allClassesLink.style.display = "block";
}
else {
allClassesLink.style.display = "none";
}
//-->
</script>
</div>
<a name="skip.navbar.top">
<!-- -->
</a></div>
<!-- ========= END OF TOP NAVBAR ========= -->
<div class="header">
<h1 title="Package" class="title">Package&nbsp;org.apache.axis2.transport.testkit</h1>
<div class="docSummary">
<div class="block">Transport test kit base package.</div>
</div>
<p>See:&nbsp;<a href="#package.description">Description</a></p>
</div>
<div class="contentContainer">
<ul class="blockList">
<li class="blockList">
<table class="typeSummary" border="0" cellpadding="3" cellspacing="0" summary="Interface Summary table, listing interfaces, and an explanation">
<caption><span>Interface Summary</span><span class="tabEnd">&nbsp;</span></caption>
<tr>
<th class="colFirst" scope="col">Interface</th>
<th class="colLast" scope="col">Description</th>
</tr>
<tbody>
<tr class="altColor">
<td class="colFirst"><a href="../../../../../org/apache/axis2/transport/testkit/Adapter.html" title="interface in org.apache.axis2.transport.testkit">Adapter</a></td>
<td class="colLast">&nbsp;</td>
</tr>
<tr class="rowColor">
<td class="colFirst"><a href="../../../../../org/apache/axis2/transport/testkit/MessageExchangeValidator.html" title="interface in org.apache.axis2.transport.testkit">MessageExchangeValidator</a></td>
<td class="colLast">&nbsp;</td>
</tr>
</tbody>
</table>
</li>
<li class="blockList">
<table class="typeSummary" border="0" cellpadding="3" cellspacing="0" summary="Class Summary table, listing classes, and an explanation">
<caption><span>Class Summary</span><span class="tabEnd">&nbsp;</span></caption>
<tr>
<th class="colFirst" scope="col">Class</th>
<th class="colLast" scope="col">Description</th>
</tr>
<tbody>
<tr class="altColor">
<td class="colFirst"><a href="../../../../../org/apache/axis2/transport/testkit/AdapterUtils.html" title="class in org.apache.axis2.transport.testkit">AdapterUtils</a></td>
<td class="colLast">&nbsp;</td>
</tr>
<tr class="rowColor">
<td class="colFirst"><a href="../../../../../org/apache/axis2/transport/testkit/ManagedTestSuite.html" title="class in org.apache.axis2.transport.testkit">ManagedTestSuite</a></td>
<td class="colLast">&nbsp;</td>
</tr>
<tr class="altColor">
<td class="colFirst"><a href="../../../../../org/apache/axis2/transport/testkit/MessageTestData.html" title="class in org.apache.axis2.transport.testkit">MessageTestData</a></td>
<td class="colLast">&nbsp;</td>
</tr>
<tr class="rowColor">
<td class="colFirst"><a href="../../../../../org/apache/axis2/transport/testkit/TransportTestSuiteBuilder.html" title="class in org.apache.axis2.transport.testkit">TransportTestSuiteBuilder</a></td>
<td class="colLast">&nbsp;</td>
</tr>
</tbody>
</table>
</li>
</ul>
<a name="package.description">
<!-- -->
</a>
<h2 title="Package org.apache.axis2.transport.testkit Description">Package org.apache.axis2.transport.testkit Description</h2>
<div class="block">Transport test kit base package.
<h2>Introduction and high level overview</h2>
In general a good test suite for an Axis2 transport should contain test cases that
<ul>
<li>test the transport sender in isolation, i.e. with non Axis2 endpoints;</li>
<li>test the transport listener in isolation, i.e. with non Axis2 clients;</li>
<li>test the interoperability between the transport sender and the transport listener.</li>
</ul>
In addition, the test suite should cover
<ul>
<li>different message exchange patterns (at least one-way and request-response);</li>
<li>different content types (SOAP 1.1/1.2, POX, SOAP with attachments, MTOM, plain text, binary, etc.).</li>
</ul>
Also for some transports it is necessary to execute the tests with different transport
configurations or with different protocol providers. For example, HTTP transport implementations
are tested in HTTP 1.0 and HTTP 1.1 mode, and the JMS transport is tested with different
JMS providers (currently Qpid and ActiveMQ).
<p>
The test kit grew out of the idea that is should be possible to apply a common set of tests
(with different MEPs and content types) to several transports with a minimum of code duplication.
By providing non Axis2 test clients and endpoints as well as the code that sets up the
necessary environment as input, the framework should then be able to build a complete test suite
for the transport.
<p>
It is clear that since each transport protocol has its own specificities, a high level of abstraction
is required to achieve this goal. The following sections give a high level overview of the
various abstractions that have been introduced in the test kit.
<h3>Integration with JUnit</h3>
One of the fundamental requirements for the test kit is to integrate well with JUnit.
This requirement ensures that the tests can be executed easily as part of the Maven
build and that other available tools such as test report generators and test coverage
analysis tools can be used.
<p>
The usual approach to write JUnit tests is to extend <code>junit.framework.TestCase.TestCase</code>
and to define a set of methods that implement the different test cases. Since the goal of the framework
is to build test suites in an automated way and the number of test cases can be fairly high, this
approach would not be feasible. Fortunately JUnit supports another way to create a test suite
dynamically. Indeed JUnit scans the test code for methods with the following signature:
<pre>public static TestSuite suite()</pre>
A typical transport test will implement this method and use <a href="../../../../../org/apache/axis2/transport/testkit/TransportTestSuiteBuilder.html" title="class in org.apache.axis2.transport.testkit"><code>TransportTestSuiteBuilder</code></a>
to let the framework create the test suite.
<h3>Test case naming</h3>
One problem that immediately arises when building a test suite dynamically is that each test
case must have a name (which should be unique) and that this name should be sufficiently meaningful
so that when it appears in a report a human should be able to get a basic idea of what the test case does.
The names generated by the test kit have two parts:
<ul>
<li>A numeric ID which is the sequence number of the test case in the test suite.</li>
<li>A set of key-value pairs describing the components that are used in the test case.</li>
</ul>
Example:
<pre>0076:test=REST,client=java.net,endpoint=axis</pre>
The algorithm used by the test kit to collect the key-value pairs is described in the documentation of
the <a href="../../../../../org/apache/axis2/transport/testkit/name/package-summary.html"><code>org.apache.axis2.transport.testkit.name</code></a> package.
<h3>Resource management</h3>
In general setting up the environment in which a given test case is executed may be quite expensive.
For example, running a test case for the JMS transport requires starting a message broker. Also
every test case requires at least an Axis2 client and/or server environment to deploy the transport.
Setting up and tearing down the entire environment for every single test case would be far too
expensive. On the other hand the environments required by different test cases in a single test suite
are in general very different from each other so that it would not possible to set up a common
environment used by all the test cases.
<p>
To overcome this difficulty, the test kit has a mechanism that allows a test case to reuse resources
from the previous test case. This is managed in an entirely transparent way by a lightweight
dependency injection container (see [TODO: need to regroup this code in a single package]), so that
the test case doesn't need to care about it.
<p>
The mechanism is based on a set of simple concepts: [TODO: this is too detailed for a high level overview and
should be moved to the Javadoc of the relevant package]
<ul>
<li><p>Every test case is linked to a set of <em>resources</em> which are plain Java objects (that are not
required to extend any particular class or implement any particular interface).
These objects define the <em>resource set</em> of the test case (which is represented
internally by a <a href="../../../../../org/apache/axis2/transport/testkit/tests/TestResourceSet.html" title="class in org.apache.axis2.transport.testkit.tests"><code>TestResourceSet</code></a>
object).</p></li>
<li><p>The lifecycle of a resource is managed through methods annotated by
<a href="../../../../../org/apache/axis2/transport/testkit/tests/Setup.html" title="annotation in org.apache.axis2.transport.testkit.tests"><code>Setup</code></a> and <a href="../../../../../org/apache/axis2/transport/testkit/tests/TearDown.html" title="annotation in org.apache.axis2.transport.testkit.tests"><code>TearDown</code></a>.
These annotations identify the methods to be called when the framework sets up and tears down the resource.
The arguments of the methods annotated using <a href="../../../../../org/apache/axis2/transport/testkit/tests/Setup.html" title="annotation in org.apache.axis2.transport.testkit.tests"><code>Setup</code></a> also
define the <em>dependencies</em> of that resource.</p>
<p>Example:</p>
<pre>public class MyTestClient {
\@Setup
private void setUp(MyProtocolProvider provider) throws Exception {
provider.connect();
}
}</pre>
<p>As shown in this example, dependencies are specified by class (which may be abstract). The actual
instance that will be injected is selected during <em>resource resolution</em>.</p></li>
<li><p>Resources are (in general) resolved from the resource set of the test case. For example an instance
of the <code>MyTestClient</code> class can only be used as a resource for a given test case
if the resource set of this test case also contains an instance of <code>MyProtocolProvider</code>
(more precisely an object that is assignment compatible with <code>MyProtocolProvider</code>).</p></li>
<li><p>A resource will be reused across two test cases if it is part of the resource sets of both
test cases and all its dependencies (including transitive dependencies) are part of both resource sets.
The precise meaning of "reusing" in this context is using the same instance without calling the
tear down and set up methods.</p>
<p>For example, consider the following test cases and resource sets:</p>
<table border="1">
<tr><th>Test case</th><th>Resource set</th></tr>
<tr><td>T1</td><td><code>c:MyTestClient</code>, <code>p1:MyProtocolProvider</code></td></tr>
<tr><td>T2</td><td><code>c:MyTestClient</code>, <code>p1:MyProtocolProvider</code>, <code>r:SomeOtherResourceType</code></td></tr>
<tr><td>T3</td><td><code>c:MyTestClient</code>, <code>p2:MyProtocolProvider</code>, <code>r:SomeOtherResourceType</code></td></tr>
</table>
<p>Assuming that <code>SomeOtherResourceType</code> is independent of <code>MyTestClient</code> and
<code>MyProtocolProvider</code>, the lifecycle of the different resources will be as follows:</p>
<table border="1">
<tr><th>Transition</th><th>Lifecycle actions</th></tr>
<tr><td>&bull; &rarr; T1</td><td>set up <code>p1</code>, set up <code>c</code></td></tr>
<tr><td>T1 &rarr; T2</td><td>set up <code>r</code></td></tr>
<tr><td>T2 &rarr; T3</td><td>tear down <code>c</code>, tear down <code>p1</code>, set up <code>p2</code>, set up <code>c</code></td></tr>
<tr><td>T3 &rarr; &bull;</td><td>tear down <code>c</code>, tear down <code>p2</code>, tear down <code>r</code></td></tr>
</table>
<p>Even if T2 and T3 use the same instance <code>c</code> of <code>MyTestClient</code>, this resource
is not reused (in the sense defined above) since the <code>MyProtocolProvider</code> dependency
resolves to different instances.</p></li>
</ul>
<h3>Resources required by a transport test case</h3>
Every transport test case (extending <a href="../../../../../org/apache/axis2/transport/testkit/tests/MessageTestCase.html" title="class in org.apache.axis2.transport.testkit.tests"><code>MessageTestCase</code></a>)
at least requires three resources:
<ul>
<li>A test client (<a href="../../../../../org/apache/axis2/transport/testkit/client/AsyncTestClient.html" title="interface in org.apache.axis2.transport.testkit.client"><code>AsyncTestClient</code></a>
or <a href="../../../../../org/apache/axis2/transport/testkit/client/RequestResponseTestClient.html" title="interface in org.apache.axis2.transport.testkit.client"><code>RequestResponseTestClient</code></a>) that
allows the test case to send messages (and receive responses).</li>
<li>A test endpoint (<a href="../../../../../org/apache/axis2/transport/testkit/endpoint/AsyncEndpoint.html" title="interface in org.apache.axis2.transport.testkit.endpoint"><code>AsyncEndpoint</code></a>
or <a href="../../../../../org/apache/axis2/transport/testkit/endpoint/InOutEndpoint.html" title="interface in org.apache.axis2.transport.testkit.endpoint"><code>InOutEndpoint</code></a>). In the one-way case,
this resource is used to receive requests send by the test client. In the request-response
case its responsibility is to generate well defined responses (typically a simple echo).</li>
<li>A channel (<a href="../../../../../org/apache/axis2/transport/testkit/channel/AsyncChannel.html" title="interface in org.apache.axis2.transport.testkit.channel"><code>AsyncChannel</code></a> or
<a href="../../../../../org/apache/axis2/transport/testkit/channel/RequestResponseChannel.html" title="interface in org.apache.axis2.transport.testkit.channel"><code>RequestResponseChannel</code></a>. This resource
manages everything that it necessary to transport a message from a client to an endpoint.
Depending on the transport this task can be fairly complex. For example, in the JMS case,
the channel creates the required JMS destinations and registers them in JNDI, so that
they can be used by the client and by the endpoint. On the other hand, for HTTP the
channel implementation is very simple and basically limited to the computation of the
endpoint reference.</li>
</ul>
<p>The test kit provides the following Axis2 based test client and endpoint implementations:</p>
<table border="1">
<tr>
<th></th>
<th>One-way</th>
<th>Request-response</th>
</tr>
<tr>
<th>Client</th>
<td><a href="../../../../../org/apache/axis2/transport/testkit/axis2/client/AxisAsyncTestClient.html" title="class in org.apache.axis2.transport.testkit.axis2.client"><code>AxisAsyncTestClient</code></a></td>
<td><a href="../../../../../org/apache/axis2/transport/testkit/axis2/client/AxisRequestResponseTestClient.html" title="class in org.apache.axis2.transport.testkit.axis2.client"><code>AxisRequestResponseTestClient</code></a></td>
</tr>
<tr>
<th>Endpoint</th>
<td><a href="../../../../../org/apache/axis2/transport/testkit/axis2/endpoint/AxisAsyncEndpoint.html" title="class in org.apache.axis2.transport.testkit.axis2.endpoint"><code>AxisAsyncEndpoint</code></a></td>
<td><a href="../../../../../org/apache/axis2/transport/testkit/axis2/endpoint/AxisEchoEndpoint.html" title="class in org.apache.axis2.transport.testkit.axis2.endpoint"><code>AxisEchoEndpoint</code></a></td>
</tr>
</table>
<h3>Message encoders and decoders</h3>
Different clients, endpoints and test cases may have fairly different ways to "naturally" represent
a message:
<ul>
<li>To test the listener of an HTTP transport, an obvious choice is to build a test client
that relies on standard Java classes such as <a href="https://docs.oracle.com/javase/7/docs/api/java/net/URLConnection.html?is-external=true" title="class or interface in java.net"><code>URLConnection</code></a>. For that
purpose the most natural way to represent a message is as a byte sequence.</li>
<li>All Axis2 based test clients and endpoints already have a canonical message
representation, which is the SOAP infoset retrieved by
<a href="../../../../../org/apache/axis2/context/MessageContext.html#getEnvelope--"><code>MessageContext.getEnvelope()</code></a>.</li>
<li>A test case for plain text messages would naturally represent the test message
as a string.</li>
</ul>
Since defining a message representation that would be suitable for all clients, endpoints and test
cases (and make their implementation simple) is impossible, a different approach has been chosen
in the framework. Every client, endpoint or test case implementation chooses the Java type that is
considers as best suited to represent the message. When invoking the test client, a test case
uses a <a href="../../../../../org/apache/axis2/transport/testkit/message/MessageEncoder.html" title="interface in org.apache.axis2.transport.testkit.message"><code>MessageEncoder</code></a> to transform the message
from its own representation to the representation used by the test client. In the same way,
a <a href="../../../../../org/apache/axis2/transport/testkit/message/MessageDecoder.html" title="interface in org.apache.axis2.transport.testkit.message"><code>MessageDecoder</code></a> is used to transform the message
intercepted by the endpoint (in the one-way case) or the response message received by the test client
(in the request-response case).
<p>
[TODO: currently message encoders and decoders are chosen at compile time and the transformation is
is invoked indirectly by adapters; this will change in the future so that encoders and decoders are
selected dynamically at runtime]
<h3>Exclusion rules</h3>
Sometimes it is necessary to exclude particular test cases (or entire groups of test cases) from the
test suite generated by the test kit. There are various reasons why one would do that:
<ul>
<li>A test case fails because of some known issue in the transport. In that case it should be excluded
until the issue is fixed. This is necessary to distinguish this type of failure from regressions.
In general the tests checked in to source control should always succeed unless there is a regression.</li>
<li>Sometimes a particular test case doesn't make sense for a given transport. For example a test
case that checks that the transport is able to handle large payloads would not be applicable
to the UDP transport which has a message size limitation.</li>
<li>The test suite builder generates test cases by computing all possible combinations of MEPs, content types,
clients, endpoints and environment setups. For some transports this results in a very high number of test
cases. Since these test cases generally have a high degree of overlap, one can use exclusion rules
to reduce the number of test cases to a more reasonable value.</li>
</ul>
The test kit allows to specify exclusion rules using LDAP filter expressions. It takes advantage of the
fact that each test case has a set of key-value pairs used to build the test case name. The LDAP filters
are evaluated against this set.
For example, <a href="../../../../../org/apache/axis2/transport/testkit/TransportTestSuiteBuilder.html" title="class in org.apache.axis2.transport.testkit"><code>TransportTestSuiteBuilder</code></a> defines the following
default exclusion rule:
<pre>(&amp;(client=*)(endpoint=*)(!(|(client=axis)(endpoint=axis))))</pre>
This rule excludes all test cases that would use a non Axis2 client and a non Axis2 endpoint.
<h3>Logging</h3>
Transport test cases generally involve several interacting components and some of these components
may use multithreading. Also experience has shown that some test cases may randomly fail (often with
a failure probablity highly dependent on the execution platform) because of subtle problems in the
transport under test or in the tests themselves. All this can make debugging extremely difficult.
To simplify this task, the test kit collects (or provides the necessary infrastructure to collect)
a maximum of information during the execution of each test case.
<p>
The collected information is written to a set of log files managed by
<a href="../../../../../org/apache/axis2/transport/testkit/util/TestKitLogManager.html" title="class in org.apache.axis2.transport.testkit.util"><code>TestKitLogManager</code></a>. An instance is added automatically to
the resource set of every test case and other resources can acquire a reference through the dependency
injection mechanism described above. This is the recommended approach. Alternatively, the log manager
can be used as a singleton through <a href="../../../../../org/apache/axis2/transport/testkit/util/TestKitLogManager.html#INSTANCE"><code>TestKitLogManager.INSTANCE</code></a>.
<p>
Logs files are written to subdirectories of <tt>target/testkit-logs</tt>. The directory structure has
a two level hierarchy identifying the test class (by its fully qualified name) and the test case
(by its ID). It should be noted that the test results themselves (in particular the exception in case
of failure) are still written to the standard JUnit/Surefire logs and that these logs should be
consulted first. The test kit specific log files are only meant to provide additional information.
<p>
Each test case at least produces a <tt>01-debug.log</tt> file with the messages that were logged
(using JCL) at level DEBUG during the execution of the test case. In addition, depending on the
components involved in the test, the test kit will produce the following logs (<tt>XX</tt>
denotes a sequence number which is generated automatically):
<dl>
<dt><tt>XX-formatter.log</tt></dt>
<dt><tt>XX-builder.log</tt></dt>
<dd><p>These files are produced when Axis2 test clients and endpoints are used.
<tt>XX-formatter.log</tt> will contain the payload of an incoming message as seen by the
<a href="../../../../../org/apache/axis2/transport/MessageFormatter.html" title="interface in org.apache.axis2.transport"><code>MessageFormatter</code></a>. <tt>XX-builder.log</tt> on the other
hand will contain the payload of an outgoing message as produced by the
<a href="../../../../../org/apache/axis2/builder/Builder.html" title="interface in org.apache.axis2.builder"><code>Builder</code></a>. Note that the number of log files depends on
serveral factors, such as the MEP, whether the client or endpoint is Axis2 based or not and
whether the transport chooses to use message builders and formatters or not.</p>
<p>These files provides extremely valuable information since it is very difficult to get this
data using other debugging techniques. Note that the files are created by
<a href="../../../../../org/apache/axis2/transport/testkit/axis2/LogAspect.html" title="class in org.apache.axis2.transport.testkit.axis2"><code>LogAspect</code></a> which relies on Aspect/J to
intercept calls to message formatters and builders. This will only work if the tests are
run with the Aspect/J weaver.</p></dd>
<dt><tt>XX-service-parameters.log</tt></dt>
<dd><p>If the test case uses an Axis2 based endpoint, this file will contain the parameters
of the <a href="../../../../../org/apache/axis2/description/AxisService.html" title="class in org.apache.axis2.description"><code>AxisService</code></a> implementing this endpoint.
This information is useful since the service configuration is in general determined
by different components involved in the test.</p></dd>
</dl></div>
</div>
<!-- ======= START OF BOTTOM NAVBAR ====== -->
<div class="bottomNav"><a name="navbar.bottom">
<!-- -->
</a>
<div class="skipNav"><a href="#skip.navbar.bottom" title="Skip navigation links">Skip navigation links</a></div>
<a name="navbar.bottom.firstrow">
<!-- -->
</a>
<ul class="navList" title="Navigation">
<li><a href="../../../../../overview-summary.html">Overview</a></li>
<li class="navBarCell1Rev">Package</li>
<li>Class</li>
<li><a href="package-use.html">Use</a></li>
<li><a href="package-tree.html">Tree</a></li>
<li><a href="../../../../../deprecated-list.html">Deprecated</a></li>
<li><a href="../../../../../index-all.html">Index</a></li>
<li><a href="../../../../../help-doc.html">Help</a></li>
</ul>
</div>
<div class="subNav">
<ul class="navList">
<li><a href="../../../../../org/apache/axis2/transport/tcp/package-summary.html">Prev&nbsp;Package</a></li>
<li><a href="../../../../../org/apache/axis2/transport/testkit/axis2/package-summary.html">Next&nbsp;Package</a></li>
</ul>
<ul class="navList">
<li><a href="../../../../../index.html?org/apache/axis2/transport/testkit/package-summary.html" target="_top">Frames</a></li>
<li><a href="package-summary.html" target="_top">No&nbsp;Frames</a></li>
</ul>
<ul class="navList" id="allclasses_navbar_bottom">
<li><a href="../../../../../allclasses-noframe.html">All&nbsp;Classes</a></li>
</ul>
<div>
<script type="text/javascript"><!--
allClassesLink = document.getElementById("allclasses_navbar_bottom");
if(window==top) {
allClassesLink.style.display = "block";
}
else {
allClassesLink.style.display = "none";
}
//-->
</script>
</div>
<a name="skip.navbar.bottom">
<!-- -->
</a></div>
<!-- ======== END OF BOTTOM NAVBAR ======= -->
<p class="legalCopy"><small>Copyright &copy; <a href="https://www.apache.org/">The Apache Software Foundation</a>. All Rights Reserved.</small></p>
</body>
</html>