Merge branch 'master' into release-9

This commit is contained in:
Jesse McConnell 2012-11-05 11:56:52 -06:00
commit 0d78b07595
719 changed files with 17477 additions and 30723 deletions

View File

@ -1,9 +0,0 @@
BUILDING JETTY
--------------
Jetty is built with maven 3.x+
$ cd /my/work/directory/jetty-7
$ mvn clean install

View File

@ -1,202 +0,0 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

View File

@ -6,7 +6,7 @@
<meta name="Generator" content="Microsoft Word 9">
<meta name="Originator" content="Microsoft Word 9">
<link rel="File-List" href="http://www.eclipse.org/legal/Eclipse%20EPL%202003_11_10%20Final_files/filelist.xml">
<title>Eclipse Public License - Version 1.0</title>
<title>Eclipse Public License - Version 1.0 / Apache License - Version 2.0</title>
<!--[if gte mso 9]><xml>
<o:DocumentProperties>
<o:Revision>2</o:Revision>
@ -317,4 +317,260 @@ its rights to a jury trial in any resulting litigation.</span> </p>
</div>
<div class="Section2">
<p style="text-align: center;" align="center"><b>Apache License</b></br>
Version 2.0, January 2004<br/>
http://www.apache.org/licenses/<br/>
</p>
<p><span style="font-size: 10pt;">TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION</spam></p>
<p><b><span style="font-size: 10pt;">1. Definitions.</span></b> </p>
<p><span style="font-size: 10pt;">
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.</span></p>
<p><span style="font-size: 10pt;">
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.</span></p>
<p><span style="font-size: 10pt;">
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.</span></p>
<p><span style="font-size: 10pt;">
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.</span></p>
<p><span style="font-size: 10pt;">
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.</span></p>
<p><span style="font-size: 10pt;">
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.</span></p>
<p><span style="font-size: 10pt;">
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).</span></p>
<p><span style="font-size: 10pt;">
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.</span></p>
<p><span style="font-size: 10pt;">
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."</span></p>
<p><span style="font-size: 10pt;">
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.</span></p>
<p><b><span style="font-size: 10pt;">2. Grant of Copyright License.</span></b> </p>
<p><span style="font-size: 10pt;">
Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.</span></p>
<p><b><span style="font-size: 10pt;">3. Grant of Patent License.</span></b><p>
<p><span style="font-size: 10pt;">
Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
</span></p>
<p><b><span style="font-size: 10pt;">
4. Redistribution.
</span></b></p>
<p><span style="font-size: 10pt;">You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:</span><p>
<ul>
<li><span style="font-size: 10pt;">
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and</span><p>
</li>
<li><span style="font-size: 10pt;">
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and</span><p>
</li>
</li><span style="font-size: 10pt;">
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and</span><p>
</li>
<li><span style="font-size: 10pt;">
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.</span><p>
</li>
</ul>
</span></p>
<p><span style="font-size: 10pt;">
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
</span></p>
<p><b><span style="font-size: 10pt;">
5. Submission of Contributions.
</span></b></p>
<p><span style="font-size: 10pt;">Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
</span></p>
<p><b><span style="font-size: 10pt;">
6. Trademarks.
</span></b></p>
<p><span style="font-size: 10pt;">This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
</span></p>
<p><b><span style="font-size: 10pt;">
7. Disclaimer of Warranty.
</span></b></p>
<p><span style="font-size: 10pt;">Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
</span></p>
<p><b><span style="font-size: 10pt;">
8. Limitation of Liability.
</span></b></p>
<p><span style="font-size: 10pt;">In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
</span></p>
<p><b><span style="font-size: 10pt;">
9. Accepting Warranty or Additional Liability.
</span></b></p>
<p><span style="font-size: 10pt;">While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
</span></p>
<p><span style="font-size: 10pt;">
END OF TERMS AND CONDITIONS
</span></p>
<p><span style="font-size: 10pt;">
APPENDIX: How to apply the Apache License to your work.
</span></p>
<p><span style="font-size: 10pt;">
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
</span></p>
<p><span style="font-size: 10pt;">
Copyright [yyyy] [name of copyright owner]
</span></p>
<p><span style="font-size: 10pt;">
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
</span></p>
<p><span style="font-size: 10pt;">
http://www.apache.org/licenses/LICENSE-2.0
</span></p>
<p><span style="font-size: 10pt;">
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
</span></p>
</div>
</body></html>

View File

@ -1,4 +1,3 @@
This is a source checkout of the Jetty webserver.
To build, use:

File diff suppressed because it is too large Load Diff

View File

@ -1,8 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<templates>
<template autoinsert="true" context="java" deleted="false" description="Create Jetty Logger constant" enabled="true" name="logjetty">${:import(
org.eclipse.jetty.util.log.Log,
org.eclipse.jetty.util.log.Logger)
}private static final Logger LOG = Log.getLogger(${enclosing_type}.class);
</template>
</templates>

View File

@ -16,30 +16,34 @@
// ========================================================================
//
package org.eclipse.jetty.nested;
package org.eclipse.jetty.embedded;
import org.eclipse.jetty.server.Connector;
import org.eclipse.jetty.server.Handler;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.nio.SelectChannelConnector;
import org.eclipse.jetty.webapp.WebAppContext;
import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.server.handler.DefaultHandler;
import org.eclipse.jetty.server.handler.HandlerCollection;
import org.eclipse.jetty.servlet.ServletContextHandler;
public class NestedServer
public class ExampleServer
{
public static void main(String[] args) throws Exception
{
Server server = new Server();
Connector connector = new SelectChannelConnector();
connector.setPort(Integer.getInteger("jetty.port",8080).intValue());
server.setConnectors(new Connector[]
{ connector });
ServerConnector connector=new ServerConnector(server);
connector.setPort(8080);
server.setConnectors(new Connector[]{connector});
ServletContextHandler context = new ServletContextHandler();
context.setContextPath("/hello");
context.addServlet(HelloServlet.class,"/");
WebAppContext webapp = new WebAppContext();
webapp.setContextPath("/jnest");
webapp.setWar("src/main/webapp");
webapp.setParentLoaderPriority(true);
server.setHandler(webapp);
HandlerCollection handlers = new HandlerCollection();
handlers.setHandlers(new Handler[]{context,new DefaultHandler()});
server.setHandler(handlers);
server.start();
server.join();

View File

@ -16,15 +16,16 @@
// ========================================================================
//
package org.eclipse.jetty.client;
package org.eclipse.jetty.embedded;
public class SelectConnectionTest extends AbstractConnectionTest
import org.eclipse.jetty.util.resource.Resource;
import org.eclipse.jetty.xml.XmlConfiguration;
public class ExampleServerXml
{
protected HttpClient newHttpClient()
public static void main(String[] args) throws Exception
{
HttpClient httpClient = new HttpClient();
httpClient.setConnectorType(HttpClient.CONNECTOR_SELECT_CHANNEL);
httpClient.setConnectBlocking(true);
return httpClient;
Resource fileserver_xml = Resource.newSystemResource("exampleserver.xml");
XmlConfiguration.main(fileserver_xml.getFile().getAbsolutePath());
}
}

View File

@ -41,7 +41,7 @@ public class LikeJettyXml
{
public static void main(String[] args) throws Exception
{
String jetty_home = System.getProperty("jetty.home","../jetty-distribution/target/distribution");
String jetty_home = System.getProperty("jetty.home","../../jetty-distribution/target/distribution");
System.setProperty("jetty.home",jetty_home);
// Setup Threadpool
@ -59,7 +59,7 @@ public class LikeJettyXml
// Setup Connectors
HttpConnectionFactory http = new HttpConnectionFactory();
http.getHttpChannelConfig().setSecurePort(8443);
http.getHttpConfiguration().setSecurePort(8443);
ServerConnector connector = new ServerConnector(server,http);
connector.setPort(8080);
connector.setIdleTimeout(30000);

View File

@ -22,7 +22,7 @@ import org.eclipse.jetty.io.ArrayByteBufferPool;
import org.eclipse.jetty.io.ByteBufferPool;
import org.eclipse.jetty.server.Connector;
import org.eclipse.jetty.server.ForwardedRequestCustomizer;
import org.eclipse.jetty.server.HttpChannelConfig;
import org.eclipse.jetty.server.HttpConfiguration;
import org.eclipse.jetty.server.HttpConnectionFactory;
import org.eclipse.jetty.server.SecureRequestCustomizer;
import org.eclipse.jetty.server.Server;
@ -67,7 +67,7 @@ public class ManyConnectors
// A verbosely fully configured connector with SSL, SPDY and HTTP
HttpChannelConfig config = new HttpChannelConfig();
HttpConfiguration config = new HttpConfiguration();
config.setSecureScheme("https");
config.setSecurePort(8443);
config.setOutputBufferSize(32768);

View File

@ -21,13 +21,6 @@ package org.eclipse.jetty.embedded;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.handler.ContextHandler;
/* ------------------------------------------------------------ */
/**
* A {@link ContextHandler} provides a common environment for multiple Handlers,
* such as: URI context path, class loader, static resource base.
*
* Typically a ContextHandler is used only when multiple contexts are likely.
*/
public class OneContext
{
public static void main(String[] args) throws Exception
@ -38,10 +31,10 @@ public class OneContext
context.setContextPath("/");
context.setResourceBase(".");
context.setClassLoader(Thread.currentThread().getContextClassLoader());
server.setHandler(context);
context.setHandler(new HelloHandler());
server.setHandler(context);
server.start();
server.join();
}

View File

@ -22,15 +22,11 @@ import java.lang.management.ManagementFactory;
import org.eclipse.jetty.deploy.DeploymentManager;
import org.eclipse.jetty.deploy.providers.WebAppProvider;
import org.eclipse.jetty.io.ArrayByteBufferPool;
import org.eclipse.jetty.io.ByteBufferPool;
import org.eclipse.jetty.io.FilterConnection;
import org.eclipse.jetty.jmx.MBeanContainer;
import org.eclipse.jetty.security.HashLoginService;
import org.eclipse.jetty.server.FilterConnectionFactory;
import org.eclipse.jetty.server.ForwardedRequestCustomizer;
import org.eclipse.jetty.server.Handler;
import org.eclipse.jetty.server.HttpChannelConfig;
import org.eclipse.jetty.server.HttpConfiguration;
import org.eclipse.jetty.server.HttpConnectionFactory;
import org.eclipse.jetty.server.NCSARequestLog;
import org.eclipse.jetty.server.SecureRequestCustomizer;
@ -49,13 +45,12 @@ import org.eclipse.jetty.spdy.server.http.PushStrategy;
import org.eclipse.jetty.spdy.server.http.ReferrerPushStrategy;
import org.eclipse.jetty.util.ssl.SslContextFactory;
import org.eclipse.jetty.util.thread.QueuedThreadPool;
import org.eclipse.jetty.util.thread.TimerScheduler;
public class SpdyServer
{
public static void main(String[] args) throws Exception
{
String jetty_home = System.getProperty("jetty.home","../jetty-distribution/target/distribution");
String jetty_home = System.getProperty("jetty.home","../../jetty-distribution/target/distribution");
System.setProperty("jetty.home",jetty_home);
// Setup Threadpool
@ -73,7 +68,7 @@ public class SpdyServer
// Common HTTP configuration
HttpChannelConfig config = new HttpChannelConfig();
HttpConfiguration config = new HttpConfiguration();
config.setSecurePort(8443);
config.addCustomizer(new ForwardedRequestCustomizer());
config.addCustomizer(new SecureRequestCustomizer());
@ -81,15 +76,13 @@ public class SpdyServer
// Http Connector
HttpConnectionFactory http = new HttpConnectionFactory(config);
FilterConnectionFactory filter = new FilterConnectionFactory(http.getProtocol());
filter.addFilter(new FilterConnection.DumpToFileFilter("http-"));
ServerConnector httpConnector = new ServerConnector(server,filter,http);
ServerConnector httpConnector = new ServerConnector(server,http);
httpConnector.setPort(8080);
httpConnector.setIdleTimeout(30000);
httpConnector.setIdleTimeout(10000);
server.addConnector(httpConnector);
// SSL configurations
SslContextFactory sslContextFactory = new SslContextFactory();
sslContextFactory.setKeyStorePath(jetty_home + "/etc/keystore");
@ -123,15 +116,10 @@ public class SpdyServer
NPNServerConnectionFactory npn = new NPNServerConnectionFactory(spdy3.getProtocol(),spdy2.getProtocol(),http.getProtocol());
npn.setDefaultProtocol(http.getProtocol());
npn.setInputBufferSize(1024);
FilterConnectionFactory npn_filter = new FilterConnectionFactory(npn.getProtocol());
npn_filter.addFilter(new FilterConnection.DumpToFileFilter("npn-"));
SslConnectionFactory ssl = new SslConnectionFactory(sslContextFactory,npn_filter.getProtocol());
FilterConnectionFactory ssl_filter = new FilterConnectionFactory(ssl.getProtocol());
ssl_filter.addFilter(new FilterConnection.DumpToFileFilter("ssl-"));
ServerConnector spdyConnector = new ServerConnector(server,ssl_filter,ssl,npn_filter,npn,spdy3,spdy2,http);
SslConnectionFactory ssl = new SslConnectionFactory(sslContextFactory,npn.getProtocol());
ServerConnector spdyConnector = new ServerConnector(server,ssl,npn,spdy3,spdy2,http);
spdyConnector.setPort(8443);
server.addConnector(spdyConnector);

View File

@ -0,0 +1,39 @@
<?xml version="1.0"?>
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure.dtd">
<Configure id="ExampleServer" class="org.eclipse.jetty.server.Server">
<Set name="connectors">
<Array type="org.eclipse.jetty.server.Connector">
<Item>
<New class="org.eclipse.jetty.server.ServerConnector">
<Arg><Ref id="ExampleServer"/></Arg>
<Set name="port">8080</Set>
</New>
</Item>
</Array>
</Set>
<New id="context" class="org.eclipse.jetty.servlet.ServletContextHandler">
<Set name="contextPath">/hello</Set>
<Call name="addServlet">
<Arg>org.eclipse.jetty.embedded.HelloServlet</Arg>
<Arg>/</Arg>
</Call>
</New>
<Set name="handler">
<New class="org.eclipse.jetty.server.handler.HandlerCollection">
<Set name="handlers">
<Array type="org.eclipse.jetty.server.Handler">
<Item>
<Ref id="context" />
</Item>
<Item>
<New class="org.eclipse.jetty.server.handler.DefaultHandler" />
</Item>
</Array>
</Set>
</New>
</Set>
</Configure>

View File

@ -5,7 +5,8 @@
<Call name="addConnector">
<Arg>
<New class="org.eclipse.jetty.server.nio.ServerConnector">
<New class="org.eclipse.jetty.server.ServerConnector">
<Arg><Ref id="ExampleServer"/></Arg>
<Set name="port">8080</Set>
</New>
</Arg>

View File

@ -0,0 +1,9 @@
org.eclipse.jetty.util.log.class=org.eclipse.jetty.util.log.StdErrLog
org.eclipse.jetty.LEVEL=INFO
org.eclipse.jetty.STACKS=true
org.eclipse.jetty.SOURCE=false
#org.eclipse.jetty.STACKS=false
#org.eclipse.jetty.spdy.LEVEL=DEBUG
#org.eclipse.jetty.server.LEVEL=DEBUG
#org.eclipse.jetty.io.ssl.LEVEL=DEBUG
#org.eclipse.jetty.spdy.server.LEVEL=DEBUG

View File

@ -25,10 +25,8 @@ import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Locale;
import java.util.jar.JarEntry;
import org.eclipse.jetty.util.Loader;
@ -105,11 +103,13 @@ public class AnnotationParser
{
_val=val;
}
@Override
public Object getValue()
{
return _val;
}
@Override
public String toString()
{
return "("+getName()+":"+_val+")";
@ -126,6 +126,7 @@ public class AnnotationParser
_val = new ArrayList<Value>();
}
@Override
public Object getValue()
{
return _val;
@ -146,6 +147,7 @@ public class AnnotationParser
return _val.size();
}
@Override
public String toString()
{
StringBuffer buff = new StringBuffer();
@ -300,6 +302,7 @@ public class AnnotationParser
* Visit a single-valued (name,value) pair for this annotation
* @see org.objectweb.asm.AnnotationVisitor#visit(java.lang.String, java.lang.Object)
*/
@Override
public void visit(String aname, Object avalue)
{
SimpleValue v = new SimpleValue(aname);
@ -311,6 +314,7 @@ public class AnnotationParser
* Visit a (name,value) pair whose value is another Annotation
* @see org.objectweb.asm.AnnotationVisitor#visitAnnotation(java.lang.String, java.lang.String)
*/
@Override
public AnnotationVisitor visitAnnotation(String name, String desc)
{
String s = normalize(desc);
@ -324,6 +328,7 @@ public class AnnotationParser
* Visit an array valued (name, value) pair for this annotation
* @see org.objectweb.asm.AnnotationVisitor#visitArray(java.lang.String)
*/
@Override
public AnnotationVisitor visitArray(String name)
{
ListValue v = new ListValue(name);
@ -336,11 +341,13 @@ public class AnnotationParser
* Visit a enum-valued (name,value) pair for this annotation
* @see org.objectweb.asm.AnnotationVisitor#visitEnum(java.lang.String, java.lang.String, java.lang.String)
*/
@Override
public void visitEnum(String name, String desc, String value)
{
//TODO
}
@Override
public void visitEnd()
{
}
@ -364,6 +371,7 @@ public class AnnotationParser
int _version;
@Override
public void visit (int version,
final int access,
final String name,
@ -398,10 +406,12 @@ public class AnnotationParser
}
}
@Override
public AnnotationVisitor visitAnnotation (String desc, boolean visible)
{
MyAnnotationVisitor visitor = new MyAnnotationVisitor(normalize(desc), new ArrayList<Value>())
{
@Override
public void visitEnd()
{
super.visitEnd();
@ -422,6 +432,7 @@ public class AnnotationParser
return visitor;
}
@Override
public MethodVisitor visitMethod (final int access,
final String name,
final String methodDesc,
@ -431,10 +442,12 @@ public class AnnotationParser
return new EmptyVisitor ()
{
@Override
public AnnotationVisitor visitAnnotation(String desc, boolean visible)
{
MyAnnotationVisitor visitor = new MyAnnotationVisitor (normalize(desc), new ArrayList<Value>())
{
@Override
public void visitEnd()
{
super.visitEnd();
@ -456,6 +469,7 @@ public class AnnotationParser
};
}
@Override
public FieldVisitor visitField (final int access,
final String fieldName,
final String fieldType,
@ -465,10 +479,12 @@ public class AnnotationParser
return new EmptyVisitor ()
{
@Override
public AnnotationVisitor visitAnnotation(String desc, boolean visible)
{
MyAnnotationVisitor visitor = new MyAnnotationVisitor(normalize(desc), new ArrayList<Value>())
{
@Override
public void visitEnd()
{
super.visitEnd();
@ -498,6 +514,7 @@ public class AnnotationParser
* @param annotationName
* @param handler
*/
@Deprecated
public void registerAnnotationHandler (String annotationName, DiscoverableAnnotationHandler handler)
{
_handlers.add(handler);
@ -509,6 +526,7 @@ public class AnnotationParser
* @param annotationName
* @return
*/
@Deprecated
public List<DiscoverableAnnotationHandler> getAnnotationHandlers(String annotationName)
{
List<DiscoverableAnnotationHandler> handlers = new ArrayList<DiscoverableAnnotationHandler>();
@ -529,6 +547,7 @@ public class AnnotationParser
* @deprecated
* @return
*/
@Deprecated
public List<DiscoverableAnnotationHandler> getAnnotationHandlers()
{
List<DiscoverableAnnotationHandler> allAnnotationHandlers = new ArrayList<DiscoverableAnnotationHandler>();
@ -544,6 +563,7 @@ public class AnnotationParser
* @deprecated see registerHandler(Handler)
* @param handler
*/
@Deprecated
public void registerClassHandler (ClassHandler handler)
{
_handlers.add(handler);
@ -649,10 +669,10 @@ public class AnnotationParser
* @param visitSuperClasses
* @throws Exception
*/
public void parse (Class clazz, ClassNameResolver resolver, boolean visitSuperClasses)
public void parse (Class<?> clazz, ClassNameResolver resolver, boolean visitSuperClasses)
throws Exception
{
Class cz = clazz;
Class<?> cz = clazz;
while (cz != null)
{
if (!resolver.isExcluded(cz.getName()))
@ -782,12 +802,13 @@ public class AnnotationParser
JarScanner scanner = new JarScanner()
{
@Override
public void processEntry(URI jarUri, JarEntry entry)
{
try
{
String name = entry.getName();
if (name.toLowerCase().endsWith(".class"))
if (name.toLowerCase(Locale.ENGLISH).endsWith(".class"))
{
String shortName = name.replace('/', '.').substring(0,name.length()-6);
if ((resolver == null)
@ -827,12 +848,13 @@ public class AnnotationParser
JarScanner scanner = new JarScanner()
{
@Override
public void processEntry(URI jarUri, JarEntry entry)
{
try
{
String name = entry.getName();
if (name.toLowerCase().endsWith(".class"))
if (name.toLowerCase(Locale.ENGLISH).endsWith(".class"))
{
String shortName = name.replace('/', '.').substring(0,name.length()-6);

View File

@ -21,6 +21,7 @@ package org.eclipse.jetty.annotations;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Locale;
import javax.annotation.Resource;
import javax.naming.InitialContext;
import javax.naming.NameNotFoundException;
@ -261,7 +262,7 @@ public class ResourceAnnotationHandler extends AbstractIntrospectableAnnotationH
//default name is the javabean property name
String name = method.getName().substring(3);
name = name.substring(0,1).toLowerCase()+name.substring(1);
name = name.substring(0,1).toLowerCase(Locale.ENGLISH)+name.substring(1);
name = clazz.getCanonicalName()+"/"+name;
name = (resource.name()!=null && !resource.name().trim().equals("")? resource.name(): name);

View File

@ -90,30 +90,27 @@ public class ResourceA implements javax.servlet.Servlet
{
System.err.println("ResourceA.x");
}
@Override
public void destroy()
{
// TODO Auto-generated method stub
}
@Override
public ServletConfig getServletConfig()
{
// TODO Auto-generated method stub
return null;
}
@Override
public String getServletInfo()
{
// TODO Auto-generated method stub
return null;
}
@Override
public void init(ServletConfig arg0) throws ServletException
{
// TODO Auto-generated method stub
}
@Override
public void service(ServletRequest arg0, ServletResponse arg1)
throws ServletException, IOException
{
// TODO Auto-generated method stub
}
}

View File

@ -1,122 +0,0 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
<version>9.0.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-client</artifactId>
<name>Jetty :: Asynchronous HTTP Client</name>
<url>{$jetty.url}</url>
<properties>
<bundle-symbolic-name>${project.groupId}.client</bundle-symbolic-name>
<jetty.test.policy.loc>target/test-policy</jetty.test.policy.loc>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<extensions>true</extensions>
<executions>
<execution>
<goals>
<goal>manifest</goal>
</goals>
<configuration>
<instructions>
<Import-Package>javax.net.*,*</Import-Package>
</instructions>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<!--
Required for OSGI
-->
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<manifestFile>${project.build.outputDirectory}/META-INF/MANIFEST.MF</manifestFile>
</archive>
</configuration>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>findbugs-maven-plugin</artifactId>
<configuration>
<onlyAnalyze>org.eclipse.jetty.client.*</onlyAnalyze>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>unpack</id>
<phase>generate-test-resources</phase>
<goals>
<goal>unpack</goal>
</goals>
<configuration>
<artifactItems>
<artifactItem>
<groupId>org.eclipse.jetty.toolchain</groupId>
<artifactId>jetty-test-policy</artifactId>
<version>${jetty-test-policy-version}</version>
<type>jar</type>
<overWrite>true</overWrite>
<includes>**/*.keystore,**/*.pem</includes>
<outputDirectory>${jetty.test.policy.loc}</outputDirectory>
</artifactItem>
</artifactItems>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-http</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-server</artifactId>
<version>${project.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-security</artifactId>
<version>${project.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-servlet</artifactId>
<version>${project.version}</version>
<scope>test</scope>
</dependency>
<!--
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-websocket</artifactId>
<version>${project.version}</version>
<scope>test</scope>
</dependency>-->
<dependency>
<groupId>org.eclipse.jetty.toolchain</groupId>
<artifactId>jetty-test-helper</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>

View File

@ -1,570 +0,0 @@
//
// ========================================================================
// Copyright (c) 1995-2012 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
//
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
//
package org.eclipse.jetty.client;
import java.io.IOException;
import java.io.InputStream;
import java.util.Collections;
import java.util.concurrent.atomic.AtomicBoolean;
import org.eclipse.jetty.client.security.Authentication;
import org.eclipse.jetty.http.HttpFields;
import org.eclipse.jetty.http.HttpGenerator;
import org.eclipse.jetty.http.HttpHeaderValue;
import org.eclipse.jetty.http.HttpHeader;
import org.eclipse.jetty.http.HttpMethod;
import org.eclipse.jetty.http.HttpParser;
import org.eclipse.jetty.http.HttpScheme;
import org.eclipse.jetty.http.HttpStatus;
import org.eclipse.jetty.http.HttpVersion;
import org.eclipse.jetty.io.AbstractConnection;
import org.eclipse.jetty.io.Buffers;
import org.eclipse.jetty.io.ByteArrayBuffer;
import org.eclipse.jetty.io.Connection;
import org.eclipse.jetty.io.EndPoint;
import org.eclipse.jetty.io.EofException;
import org.eclipse.jetty.io.View;
import org.eclipse.jetty.util.component.AggregateLifeCycle;
import org.eclipse.jetty.util.component.Dumpable;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.util.thread.Timeout;
/**
*
* @version $Revision: 879 $ $Date: 2009-09-11 16:13:28 +0200 (Fri, 11 Sep 2009) $
*/
public abstract class AbstractHttpConnection extends AbstractConnection implements Dumpable
{
private static final Logger LOG = Log.getLogger(AbstractHttpConnection.class);
protected HttpDestination _destination;
protected HttpGenerator _generator;
protected HttpParser _parser;
protected boolean _http11 = true;
protected int _status;
protected ByteBuffer _connectionHeader;
protected boolean _reserved;
// The current exchange waiting for a response
protected volatile HttpExchange _exchange;
protected HttpExchange _pipeline;
private final Timeout.Task _idleTimeout = new ConnectionIdleTask();
private AtomicBoolean _idle = new AtomicBoolean(false);
AbstractHttpConnection(Buffers requestBuffers, Buffers responseBuffers, EndPoint endp)
{
super(endp);
_generator = new HttpGenerator(requestBuffers,endp);
_parser = new HttpParser(responseBuffers,endp,new Handler());
}
public void setReserved (boolean reserved)
{
_reserved = reserved;
}
public boolean isReserved()
{
return _reserved;
}
public HttpDestination getDestination()
{
return _destination;
}
public void setDestination(HttpDestination destination)
{
_destination = destination;
}
public boolean send(HttpExchange ex) throws IOException
{
LOG.debug("Send {} on {}",ex,this);
synchronized (this)
{
if (_exchange != null)
{
if (_pipeline != null)
throw new IllegalStateException(this + " PIPELINED!!! _exchange=" + _exchange);
_pipeline = ex;
return true;
}
_exchange = ex;
_exchange.associate(this);
// The call to associate() may have closed the connection, check if it's the case
if (!_endp.isOpen())
{
_exchange.disassociate();
_exchange = null;
return false;
}
_exchange.setStatus(HttpExchange.STATUS_WAITING_FOR_COMMIT);
adjustIdleTimeout();
return true;
}
}
private void adjustIdleTimeout() throws IOException
{
// Adjusts the idle timeout in case the default or exchange timeout
// are greater. This is needed for long polls, where one wants an
// aggressive releasing of idle connections (so idle timeout is small)
// but still allow long polls to complete normally
long timeout = _exchange.getTimeout();
if (timeout <= 0)
timeout = _destination.getHttpClient().getTimeout();
long endPointTimeout = _endp.getMaxIdleTime();
if (timeout > 0 && timeout > endPointTimeout)
{
// Make it larger than the exchange timeout so that there are
// no races between the idle timeout and the exchange timeout
// when trying to close the endpoint
_endp.setMaxIdleTime(2 * (int)timeout);
}
}
public abstract Connection handle() throws IOException;
public boolean isIdle()
{
synchronized (this)
{
return _exchange == null;
}
}
public boolean isSuspended()
{
return false;
}
public void onClose()
{
}
/**
* @throws IOException
*/
protected void commitRequest() throws IOException
{
synchronized (this)
{
_status=0;
if (_exchange.getStatus() != HttpExchange.STATUS_WAITING_FOR_COMMIT)
throw new IllegalStateException();
_exchange.setStatus(HttpExchange.STATUS_SENDING_REQUEST);
_generator.setVersion(_exchange.getVersion());
String method=_exchange.getMethod();
String uri = _exchange.getRequestURI();
if (_destination.isProxied())
{
if (!HttpMethod.CONNECT.equals(method) && uri.startsWith("/"))
{
boolean secure = _destination.isSecure();
String host = _destination.getAddress().getHost();
int port = _destination.getAddress().getPort();
StringBuilder absoluteURI = new StringBuilder();
absoluteURI.append(secure ? HttpScheme.HTTPS : HttpScheme.HTTP);
absoluteURI.append("://");
absoluteURI.append(host);
// Avoid adding default ports
if (!(secure && port == 443 || !secure && port == 80))
absoluteURI.append(":").append(port);
absoluteURI.append(uri);
uri = absoluteURI.toString();
}
Authentication auth = _destination.getProxyAuthentication();
if (auth != null)
auth.setCredentials(_exchange);
}
_generator.setRequest(method, uri);
_parser.setHeadResponse(HttpMethod.HEAD.equalsIgnoreCase(method));
HttpFields requestHeaders = _exchange.getRequestFields();
if (_exchange.getVersion() >= HttpVersion.HTTP_1_1_ORDINAL)
{
if (!requestHeaders.containsKey(HttpHeader.HOST_BUFFER))
requestHeaders.add(HttpHeader.HOST_BUFFER,_destination.getHostHeader());
}
ByteBuffer requestContent = _exchange.getRequestContent();
if (requestContent != null)
{
requestHeaders.putLongField(HttpHeader.CONTENT_LENGTH, requestContent.length());
_generator.completeHeader(requestHeaders,false);
_generator.addContent(new View(requestContent),true);
_exchange.setStatus(HttpExchange.STATUS_WAITING_FOR_RESPONSE);
}
else
{
InputStream requestContentStream = _exchange.getRequestContentSource();
if (requestContentStream != null)
{
_generator.completeHeader(requestHeaders, false);
}
else
{
requestHeaders.remove(HttpHeader.CONTENT_LENGTH);
_generator.completeHeader(requestHeaders, true);
_exchange.setStatus(HttpExchange.STATUS_WAITING_FOR_RESPONSE);
}
}
}
}
protected void reset() throws IOException
{
_connectionHeader = null;
_parser.reset();
_generator.reset();
_http11 = true;
}
private class Handler extends HttpParser.EventHandler
{
@Override
public void startRequest(ByteBuffer method, ByteBuffer url, ByteBuffer version) throws IOException
{
// System.out.println( method.toString() + "///" + url.toString() +
// "///" + version.toString() );
// TODO validate this is acceptable, the <!DOCTYPE goop was coming
// out here
// throw new IllegalStateException();
}
@Override
public void startResponse(ByteBuffer version, int status, ByteBuffer reason) throws IOException
{
HttpExchange exchange = _exchange;
if (exchange==null)
{
LOG.warn("No exchange for response");
_endp.close();
return;
}
switch(status)
{
case HttpStatus.CONTINUE_100:
case HttpStatus.PROCESSING_102:
// TODO check if appropriate expect was sent in the request.
exchange.setEventListener(new NonFinalResponseListener(exchange));
break;
case HttpStatus.OK_200:
// handle special case for CONNECT 200 responses
if (HttpMethod.CONNECT.equalsIgnoreCase(exchange.getMethod()))
_parser.setHeadResponse(true);
break;
}
_http11 = HttpVersion.HTTP_1_1_BUFFER.equals(version);
_status=status;
exchange.getEventListener().onResponseStatus(version,status,reason);
exchange.setStatus(HttpExchange.STATUS_PARSING_HEADERS);
}
@Override
public void parsedHeader(ByteBuffer name, ByteBuffer value) throws IOException
{
HttpExchange exchange = _exchange;
if (exchange!=null)
{
if (HttpHeader.CACHE.getOrdinal(name) == HttpHeader.CONNECTION_ORDINAL)
{
_connectionHeader = HttpHeaderValue.CACHE.lookup(value);
}
exchange.getEventListener().onResponseHeader(name,value);
}
}
@Override
public void headerComplete() throws IOException
{
HttpExchange exchange = _exchange;
if (exchange!=null)
exchange.setStatus(HttpExchange.STATUS_PARSING_CONTENT);
}
@Override
public void content(ByteBuffer ref) throws IOException
{
HttpExchange exchange = _exchange;
if (exchange!=null)
exchange.getEventListener().onResponseContent(ref);
}
@Override
public void messageComplete(long contextLength) throws IOException
{
HttpExchange exchange = _exchange;
if (exchange!=null)
exchange.setStatus(HttpExchange.STATUS_COMPLETED);
}
@Override
public void earlyEOF()
{
HttpExchange exchange = _exchange;
if (exchange!=null)
{
if (!exchange.isDone())
{
if (exchange.setStatus(HttpExchange.STATUS_EXCEPTED))
exchange.getEventListener().onException(new EofException("early EOF"));
}
}
}
}
@Override
public String toString()
{
return String.format("%s %s g=%s p=%s",
super.toString(),
_destination == null ? "?.?.?.?:??" : _destination.getAddress(),
_generator,
_parser);
}
public String toDetailString()
{
return toString() + " ex=" + _exchange + " idle for " + _idleTimeout.getAge();
}
public void close() throws IOException
{
//if there is a live, unfinished exchange, set its status to be
//excepted and wake up anyone waiting on waitForDone()
HttpExchange exchange = _exchange;
if (exchange != null && !exchange.isDone())
{
switch (exchange.getStatus())
{
case HttpExchange.STATUS_CANCELLED:
case HttpExchange.STATUS_CANCELLING:
case HttpExchange.STATUS_COMPLETED:
case HttpExchange.STATUS_EXCEPTED:
case HttpExchange.STATUS_EXPIRED:
break;
case HttpExchange.STATUS_PARSING_CONTENT:
if (_endp.isInputShutdown() && _parser.isState(HttpParser.STATE_EOF_CONTENT))
break;
default:
String exch= exchange.toString();
String reason = _endp.isOpen()?(_endp.isInputShutdown()?"half closed: ":"local close: "):"closed: ";
if (exchange.setStatus(HttpExchange.STATUS_EXCEPTED))
exchange.getEventListener().onException(new EofException(reason+exch));
}
}
if (_endp.isOpen())
{
_endp.close();
_destination.returnConnection(this, true);
}
}
public void setIdleTimeout()
{
synchronized (this)
{
if (_idle.compareAndSet(false, true))
_destination.getHttpClient().scheduleIdle(_idleTimeout);
else
throw new IllegalStateException();
}
}
public boolean cancelIdleTimeout()
{
synchronized (this)
{
if (_idle.compareAndSet(true, false))
{
_destination.getHttpClient().cancel(_idleTimeout);
return true;
}
}
return false;
}
protected void exchangeExpired(HttpExchange exchange)
{
synchronized (this)
{
// We are expiring an exchange, but the exchange is pending
// Cannot reuse the connection because the reply may arrive, so close it
if (_exchange == exchange)
{
try
{
_destination.returnConnection(this, true);
}
catch (IOException x)
{
LOG.ignore(x);
}
}
}
}
/* ------------------------------------------------------------ */
/**
* @see org.eclipse.jetty.util.component.Dumpable#dump()
*/
public String dump()
{
return AggregateLifeCycle.dump(this);
}
/* ------------------------------------------------------------ */
/**
* @see org.eclipse.jetty.util.component.Dumpable#dump(java.lang.Appendable, java.lang.String)
*/
public void dump(Appendable out, String indent) throws IOException
{
synchronized (this)
{
out.append(String.valueOf(this)).append("\n");
AggregateLifeCycle.dump(out,indent,Collections.singletonList(_endp));
}
}
/* ------------------------------------------------------------ */
private class ConnectionIdleTask extends Timeout.Task
{
/* ------------------------------------------------------------ */
@Override
public void expired()
{
// Connection idle, close it
if (_idle.compareAndSet(true, false))
{
_destination.returnIdleConnection(AbstractHttpConnection.this);
}
}
}
/* ------------------------------------------------------------ */
private class NonFinalResponseListener implements HttpEventListener
{
final HttpExchange _exchange;
final HttpEventListener _next;
/* ------------------------------------------------------------ */
public NonFinalResponseListener(HttpExchange exchange)
{
_exchange=exchange;
_next=exchange.getEventListener();
}
/* ------------------------------------------------------------ */
public void onRequestCommitted() throws IOException
{
}
/* ------------------------------------------------------------ */
public void onRequestComplete() throws IOException
{
}
/* ------------------------------------------------------------ */
public void onResponseStatus(ByteBuffer version, int status, ByteBuffer reason) throws IOException
{
}
/* ------------------------------------------------------------ */
public void onResponseHeader(ByteBuffer name, ByteBuffer value) throws IOException
{
_next.onResponseHeader(name,value);
}
/* ------------------------------------------------------------ */
public void onResponseHeaderComplete() throws IOException
{
_next.onResponseHeaderComplete();
}
/* ------------------------------------------------------------ */
public void onResponseContent(ByteBuffer content) throws IOException
{
}
/* ------------------------------------------------------------ */
public void onResponseComplete() throws IOException
{
_exchange.setEventListener(_next);
_exchange.setStatus(HttpExchange.STATUS_WAITING_FOR_RESPONSE);
_parser.reset();
}
/* ------------------------------------------------------------ */
public void onConnectionFailed(Throwable ex)
{
_exchange.setEventListener(_next);
_next.onConnectionFailed(ex);
}
/* ------------------------------------------------------------ */
public void onException(Throwable ex)
{
_exchange.setEventListener(_next);
_next.onException(ex);
}
/* ------------------------------------------------------------ */
public void onExpire()
{
_exchange.setEventListener(_next);
_next.onExpire();
}
/* ------------------------------------------------------------ */
public void onRetry()
{
_exchange.setEventListener(_next);
_next.onRetry();
}
}
}

View File

@ -1,96 +0,0 @@
//
// ========================================================================
// Copyright (c) 1995-2012 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
//
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
//
package org.eclipse.jetty.client;
import java.net.InetSocketAddress;
/**
* @version $Revision: 4135 $ $Date: 2008-12-02 11:57:07 +0100 (Tue, 02 Dec 2008) $
*/
public class Address
{
private final String host;
private final int port;
public static Address from(String hostAndPort)
{
String host;
int port;
int colon = hostAndPort.indexOf(':');
if (colon >= 0)
{
host = hostAndPort.substring(0, colon);
port = Integer.parseInt(hostAndPort.substring(colon + 1));
}
else
{
host = hostAndPort;
port = 0;
}
return new Address(host, port);
}
public Address(String host, int port)
{
if (host == null)
throw new IllegalArgumentException("Host is null");
this.host = host.trim();
this.port = port;
}
@Override
public boolean equals(Object obj)
{
if (this == obj) return true;
if (obj == null || getClass() != obj.getClass()) return false;
Address that = (Address)obj;
if (!host.equals(that.host)) return false;
return port == that.port;
}
@Override
public int hashCode()
{
int result = host.hashCode();
result = 31 * result + port;
return result;
}
public String getHost()
{
return host;
}
public int getPort()
{
return port;
}
public InetSocketAddress toSocketAddress()
{
return new InetSocketAddress(getHost(), getPort());
}
@Override
public String toString()
{
return host + ":" + port;
}
}

View File

@ -1,267 +0,0 @@
//
// ========================================================================
// Copyright (c) 1995-2012 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
//
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
//
package org.eclipse.jetty.client;
import java.io.IOException;
import org.eclipse.jetty.http.AbstractGenerator;
import org.eclipse.jetty.http.HttpStatus;
import org.eclipse.jetty.io.AsyncEndPoint;
import org.eclipse.jetty.io.Buffers;
import org.eclipse.jetty.io.Connection;
import org.eclipse.jetty.io.EndPoint;
import org.eclipse.jetty.io.nio.AsyncConnection;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
/* ------------------------------------------------------------ */
/** Asynchronous Client HTTP Connection
*/
public class AsyncHttpConnection extends AbstractHttpConnection implements AsyncConnection
{
private static final Logger LOG = Log.getLogger(AsyncHttpConnection.class);
private boolean _requestComplete;
private ByteBuffer _requestContentChunk;
private final AsyncEndPoint _asyncEndp;
AsyncHttpConnection(Buffers requestBuffers, Buffers responseBuffers, EndPoint endp)
{
super(requestBuffers,responseBuffers,endp);
_asyncEndp=(AsyncEndPoint)endp;
}
protected void reset() throws IOException
{
_requestComplete = false;
super.reset();
}
public Connection handle() throws IOException
{
Connection connection = this;
boolean progress=true;
try
{
boolean failed = false;
// While we are making progress and have not changed connection
while (progress && connection==this)
{
LOG.debug("while open={} more={} progress={}",_endp.isOpen(),_parser.isMoreInBuffer(),progress);
progress=false;
HttpExchange exchange=_exchange;
LOG.debug("exchange {} on {}",exchange,this);
try
{
// Should we commit the request?
if (!_generator.isCommitted() && exchange!=null && exchange.getStatus() == HttpExchange.STATUS_WAITING_FOR_COMMIT)
{
LOG.debug("commit {}",exchange);
progress=true;
commitRequest();
}
// Generate output
if (_generator.isCommitted() && !_generator.isComplete())
{
if (_generator.flushBuffer()>0)
{
LOG.debug("flushed");
progress=true;
}
// Is there more content to send or should we complete the generator
if (_generator.isState(AbstractGenerator.STATE_CONTENT))
{
// Look for more content to send.
if (_requestContentChunk==null)
_requestContentChunk = exchange.getRequestContentChunk(null);
if (_requestContentChunk==null)
{
LOG.debug("complete {}",exchange);
progress=true;
_generator.complete();
}
else if (_generator.isEmpty())
{
LOG.debug("addChunk");
progress=true;
ByteBuffer chunk=_requestContentChunk;
_requestContentChunk=exchange.getRequestContentChunk(null);
_generator.addContent(chunk,_requestContentChunk==null);
if (_requestContentChunk==null)
exchange.setStatus(HttpExchange.STATUS_WAITING_FOR_RESPONSE);
}
}
}
// Signal request completion
if (_generator.isComplete() && !_requestComplete)
{
LOG.debug("requestComplete {}",exchange);
progress=true;
_requestComplete = true;
exchange.getEventListener().onRequestComplete();
}
// Read any input that is available
if (!_parser.isComplete() && _parser.parseAvailable())
{
LOG.debug("parsed {}",exchange);
progress=true;
}
// Flush output
_endp.flush();
// Has any IO been done by the endpoint itself since last loop
if (_asyncEndp.hasProgressed())
{
LOG.debug("hasProgressed {}",exchange);
progress=true;
}
}
catch (Throwable e)
{
LOG.debug("Failure on " + _exchange, e);
failed = true;
synchronized (this)
{
if (exchange != null)
{
// Cancelling the exchange causes an exception as we close the connection,
// but we don't report it as it is normal cancelling operation
if (exchange.getStatus() != HttpExchange.STATUS_CANCELLING &&
exchange.getStatus() != HttpExchange.STATUS_CANCELLED &&
!exchange.isDone())
{
if (exchange.setStatus(HttpExchange.STATUS_EXCEPTED))
exchange.getEventListener().onException(e);
}
}
else
{
if (e instanceof IOException)
throw (IOException)e;
if (e instanceof Error)
throw (Error)e;
if (e instanceof RuntimeException)
throw (RuntimeException)e;
throw new RuntimeException(e);
}
}
}
finally
{
LOG.debug("finally {} on {} progress={} {}",exchange,this,progress,_endp);
boolean complete = failed || _generator.isComplete() && _parser.isComplete();
if (complete)
{
boolean persistent = !failed && _parser.isPersistent() && _generator.isPersistent();
_generator.setPersistent(persistent);
reset();
if (persistent)
_endp.setMaxIdleTime((int)_destination.getHttpClient().getIdleTimeout());
synchronized (this)
{
exchange=_exchange;
_exchange = null;
// Cancel the exchange
if (exchange!=null)
{
exchange.cancelTimeout(_destination.getHttpClient());
// TODO should we check the exchange is done?
}
// handle switched protocols
if (_status==HttpStatus.SWITCHING_PROTOCOLS_101)
{
Connection switched=exchange.onSwitchProtocol(_endp);
if (switched!=null)
{
// switched protocol!
if (_pipeline!=null)
{
_destination.send(_pipeline);
}
_pipeline = null;
connection=switched;
}
}
// handle pipelined requests
if (_pipeline!=null)
{
if (!persistent || connection!=this)
_destination.send(_pipeline);
else
_exchange=_pipeline;
_pipeline=null;
}
if (_exchange==null && !isReserved()) // TODO how do we return switched connections?
_destination.returnConnection(this, !persistent);
}
}
}
}
}
finally
{
_parser.returnBuffers();
_generator.returnBuffers();
LOG.debug("unhandle {} on {}",_exchange,_endp);
}
return connection;
}
public void onInputShutdown() throws IOException
{
if (_generator.isIdle())
_endp.shutdownOutput();
}
@Override
public boolean send(HttpExchange ex) throws IOException
{
boolean sent=super.send(ex);
if (sent)
_asyncEndp.asyncDispatch();
return sent;
}
}

View File

@ -1,264 +0,0 @@
//
// ========================================================================
// Copyright (c) 1995-2012 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
//
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
//
package org.eclipse.jetty.client;
import java.io.IOException;
import java.io.InterruptedIOException;
import org.eclipse.jetty.http.AbstractGenerator;
import org.eclipse.jetty.http.HttpStatus;
import org.eclipse.jetty.io.Buffers;
import org.eclipse.jetty.io.Connection;
import org.eclipse.jetty.io.EndPoint;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
/* ------------------------------------------------------------ */
/** Blocking HTTP Connection
*/
public class BlockingHttpConnection extends AbstractHttpConnection
{
private static final Logger LOG = Log.getLogger(BlockingHttpConnection.class);
private boolean _requestComplete;
private ByteBuffer _requestContentChunk;
BlockingHttpConnection(Buffers requestBuffers, Buffers responseBuffers, EndPoint endPoint)
{
super(requestBuffers, responseBuffers, endPoint);
}
protected void reset() throws IOException
{
_requestComplete = false;
super.reset();
}
@Override
public Connection handle() throws IOException
{
Connection connection = this;
try
{
boolean failed = false;
// While we are making progress and have not changed connection
while (_endp.isOpen() && connection==this)
{
LOG.debug("open={} more={}",_endp.isOpen(),_parser.isMoreInBuffer());
HttpExchange exchange;
synchronized (this)
{
exchange=_exchange;
while (exchange == null)
{
try
{
this.wait();
exchange=_exchange;
}
catch (InterruptedException e)
{
throw new InterruptedIOException();
}
}
}
LOG.debug("exchange {}",exchange);
try
{
// Should we commit the request?
if (!_generator.isCommitted() && exchange!=null && exchange.getStatus() == HttpExchange.STATUS_WAITING_FOR_COMMIT)
{
LOG.debug("commit");
commitRequest();
}
// Generate output
while (_generator.isCommitted() && !_generator.isComplete())
{
if (_generator.flushBuffer()>0)
{
LOG.debug("flushed");
}
// Is there more content to send or should we complete the generator
if (_generator.isState(AbstractGenerator.STATE_CONTENT))
{
// Look for more content to send.
if (_requestContentChunk==null)
_requestContentChunk = exchange.getRequestContentChunk(null);
if (_requestContentChunk==null)
{
LOG.debug("complete");
_generator.complete();
}
else if (_generator.isEmpty())
{
LOG.debug("addChunk");
ByteBuffer chunk=_requestContentChunk;
_requestContentChunk=exchange.getRequestContentChunk(null);
_generator.addContent(chunk,_requestContentChunk==null);
if (_requestContentChunk==null)
exchange.setStatus(HttpExchange.STATUS_WAITING_FOR_RESPONSE);
}
}
}
// Signal request completion
if (_generator.isComplete() && !_requestComplete)
{
LOG.debug("requestComplete");
_requestComplete = true;
exchange.getEventListener().onRequestComplete();
}
// Read any input that is available
if (!_parser.isComplete() && _parser.parseAvailable())
{
LOG.debug("parsed");
}
// Flush output
_endp.flush();
}
catch (Throwable e)
{
LOG.debug("Failure on " + _exchange, e);
failed = true;
synchronized (this)
{
if (exchange != null)
{
// Cancelling the exchange causes an exception as we close the connection,
// but we don't report it as it is normal cancelling operation
if (exchange.getStatus() != HttpExchange.STATUS_CANCELLING &&
exchange.getStatus() != HttpExchange.STATUS_CANCELLED &&
!exchange.isDone())
{
if(exchange.setStatus(HttpExchange.STATUS_EXCEPTED))
exchange.getEventListener().onException(e);
}
}
else
{
if (e instanceof IOException)
throw (IOException)e;
if (e instanceof Error)
throw (Error)e;
if (e instanceof RuntimeException)
throw (RuntimeException)e;
throw new RuntimeException(e);
}
}
}
finally
{
LOG.debug("{} {}",_generator, _parser);
LOG.debug("{}",_endp);
boolean complete = failed || _generator.isComplete() && _parser.isComplete();
if (complete)
{
boolean persistent = !failed && _parser.isPersistent() && _generator.isPersistent();
_generator.setPersistent(persistent);
reset();
if (persistent)
_endp.setMaxIdleTime((int)_destination.getHttpClient().getIdleTimeout());
synchronized (this)
{
exchange=_exchange;
_exchange = null;
// Cancel the exchange
if (exchange!=null)
{
exchange.cancelTimeout(_destination.getHttpClient());
// TODO should we check the exchange is done?
}
// handle switched protocols
if (_status==HttpStatus.SWITCHING_PROTOCOLS_101)
{
Connection switched=exchange.onSwitchProtocol(_endp);
if (switched!=null)
connection=switched;
{
// switched protocol!
_pipeline = null;
if (_pipeline!=null)
_destination.send(_pipeline);
_pipeline = null;
connection=switched;
}
}
// handle pipelined requests
if (_pipeline!=null)
{
if (!persistent || connection!=this)
_destination.send(_pipeline);
else
_exchange=_pipeline;
_pipeline=null;
}
if (_exchange==null && !isReserved()) // TODO how do we return switched connections?
_destination.returnConnection(this, !persistent);
}
}
}
}
}
finally
{
_parser.returnBuffers();
_generator.returnBuffers();
}
return connection;
}
@Override
public boolean send(HttpExchange ex) throws IOException
{
boolean sent=super.send(ex);
if (sent)
{
synchronized (this)
{
notifyAll();
}
}
return sent;
}
}

View File

@ -1,75 +0,0 @@
//
// ========================================================================
// Copyright (c) 1995-2012 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
//
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
//
package org.eclipse.jetty.client;
import java.io.IOException;
import org.eclipse.jetty.http.HttpFields;
/**
* An exchange that retains response status and response headers for later use.
*/
public class CachedExchange extends HttpExchange
{
private final HttpFields _responseFields;
private volatile int _responseStatus;
/**
* Creates a new CachedExchange.
*
* @param cacheHeaders true to cache response headers, false to not cache them
*/
public CachedExchange(boolean cacheHeaders)
{
_responseFields = cacheHeaders ? new HttpFields() : null;
}
public synchronized int getResponseStatus()
{
if (getStatus() < HttpExchange.STATUS_PARSING_HEADERS)
throw new IllegalStateException("Response not received yet");
return _responseStatus;
}
public synchronized HttpFields getResponseFields()
{
if (getStatus() < HttpExchange.STATUS_PARSING_CONTENT)
throw new IllegalStateException("Headers not completely received yet");
return _responseFields;
}
@Override
protected synchronized void onResponseStatus(ByteBuffer version, int status, ByteBuffer reason) throws IOException
{
_responseStatus = status;
super.onResponseStatus(version, status, reason);
}
@Override
protected synchronized void onResponseHeader(ByteBuffer name, ByteBuffer value) throws IOException
{
if (_responseFields != null)
{
_responseFields.add(name, value.asImmutableBuffer());
}
super.onResponseHeader(name, value);
}
}

View File

@ -1,135 +0,0 @@
//
// ========================================================================
// Copyright (c) 1995-2012 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
//
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
//
package org.eclipse.jetty.client;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import org.eclipse.jetty.http.HttpHeader;
import org.eclipse.jetty.util.StringUtil;
/**
* A exchange that retains response content for later use.
*/
public class ContentExchange extends CachedExchange
{
private int _bufferSize = 4096;
private String _encoding = "utf-8";
private ByteArrayOutputStream _responseContent;
private File _fileForUpload;
public ContentExchange()
{
super(false);
}
public ContentExchange(boolean cacheFields)
{
super(cacheFields);
}
public synchronized String getResponseContent() throws UnsupportedEncodingException
{
if (_responseContent != null)
return _responseContent.toString(_encoding);
return null;
}
public synchronized byte[] getResponseContentBytes()
{
if (_responseContent != null)
return _responseContent.toByteArray();
return null;
}
@Override
protected synchronized void onResponseStatus(ByteBuffer version, int status, ByteBuffer reason) throws IOException
{
if (_responseContent!=null)
_responseContent.reset();
super.onResponseStatus(version,status,reason);
}
@Override
protected synchronized void onResponseHeader(ByteBuffer name, ByteBuffer value) throws IOException
{
super.onResponseHeader(name, value);
int header = HttpHeader.CACHE.getOrdinal(name);
switch (header)
{
case HttpHeader.CONTENT_LENGTH_ORDINAL:
_bufferSize = BufferUtil.toInt(value);
break;
case HttpHeader.CONTENT_TYPE_ORDINAL:
String mime = StringUtil.asciiToLowerCase(value.toString());
int i = mime.indexOf("charset=");
if (i > 0)
{
_encoding = mime.substring(i + 8);
i = _encoding.indexOf(';');
if (i > 0)
_encoding = _encoding.substring(0, i);
}
break;
}
}
@Override
protected synchronized void onResponseContent(ByteBuffer content) throws IOException
{
super.onResponseContent(content);
if (_responseContent == null)
_responseContent = new ByteArrayOutputStream(_bufferSize);
content.writeTo(_responseContent);
}
@Override
protected synchronized void onRetry() throws IOException
{
if (_fileForUpload != null)
{
setRequestContent(null);
setRequestContentSource(getInputStream());
}
else
super.onRetry();
}
private synchronized InputStream getInputStream() throws IOException
{
return new FileInputStream(_fileForUpload);
}
public synchronized File getFileForUpload()
{
return _fileForUpload;
}
public synchronized void setFileForUpload(File fileForUpload) throws IOException
{
this._fileForUpload = fileForUpload;
setRequestContentSource(getInputStream());
}
}

View File

@ -1,906 +0,0 @@
//
// ========================================================================
// Copyright (c) 1995-2012 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
//
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
//
package org.eclipse.jetty.client;
import java.io.IOException;
import java.io.InputStream;
import java.net.UnknownHostException;
import java.util.Enumeration;
import java.util.LinkedList;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import javax.net.ssl.SSLContext;
import org.eclipse.jetty.client.security.Authentication;
import org.eclipse.jetty.client.security.RealmResolver;
import org.eclipse.jetty.client.security.SecurityListener;
import org.eclipse.jetty.http.HttpBuffers;
import org.eclipse.jetty.http.HttpBuffersImpl;
import org.eclipse.jetty.http.HttpScheme;
import org.eclipse.jetty.io.Buffers;
import org.eclipse.jetty.io.Buffers.Type;
import org.eclipse.jetty.util.Attributes;
import org.eclipse.jetty.util.AttributesMap;
import org.eclipse.jetty.util.component.AggregateLifeCycle;
import org.eclipse.jetty.util.component.Dumpable;
import org.eclipse.jetty.util.component.LifeCycle;
import org.eclipse.jetty.util.ssl.SslContextFactory;
import org.eclipse.jetty.util.thread.QueuedThreadPool;
import org.eclipse.jetty.util.thread.ThreadPool;
import org.eclipse.jetty.util.thread.Timeout;
/**
* Http Client.
* <p/>
* HttpClient is the main active component of the client API implementation.
* It is the opposite of the Connectors in standard Jetty, in that it listens
* for responses rather than requests. Just like the connectors, there is a
* blocking socket version and a non-blocking NIO version (implemented as nested classes
* selected by {@link #setConnectorType(int)}).
* <p/>
* The an instance of {@link HttpExchange} is passed to the {@link #send(HttpExchange)} method
* to send a request. The exchange contains both the headers and content (source) of the request
* plus the callbacks to handle responses. A HttpClient can have many exchanges outstanding
* and they may be queued on the {@link HttpDestination} waiting for a {@link AbstractHttpConnection},
* queued in the {@link AbstractHttpConnection} waiting to be transmitted or pipelined on the actual
* TCP/IP connection waiting for a response.
* <p/>
* The {@link HttpDestination} class is an aggregation of {@link AbstractHttpConnection}s for the
* same host, port and protocol. A destination may limit the number of connections
* open and they provide a pool of open connections that may be reused. Connections may also
* be allocated from a destination, so that multiple request sources are not multiplexed
* over the same connection.
*
* @see HttpExchange
* @see HttpDestination
*/
public class HttpClient extends AggregateLifeCycle implements HttpBuffers, Attributes, Dumpable
{
public static final int CONNECTOR_SOCKET = 0;
public static final int CONNECTOR_SELECT_CHANNEL = 2;
private int _connectorType = CONNECTOR_SELECT_CHANNEL;
private boolean _useDirectBuffers = true;
private boolean _connectBlocking = true;
private int _maxConnectionsPerAddress = Integer.MAX_VALUE;
private int _maxQueueSizePerAddress = Integer.MAX_VALUE;
private ConcurrentMap<Address, HttpDestination> _destinations = new ConcurrentHashMap<Address, HttpDestination>();
ThreadPool _threadPool;
Connector _connector;
private long _idleTimeout = 20000;
private long _timeout = 320000;
private int _connectTimeout = 75000;
private Timeout _timeoutQ = new Timeout();
private Timeout _idleTimeoutQ = new Timeout();
private Address _proxy;
private Authentication _proxyAuthentication;
private Set<String> _noProxy;
private int _maxRetries = 3;
private int _maxRedirects = 20;
private LinkedList<String> _registeredListeners;
private final SslContextFactory _sslContextFactory;
private RealmResolver _realmResolver;
private AttributesMap _attributes=new AttributesMap();
private final HttpBuffersImpl _buffers= new HttpBuffersImpl();
/* ------------------------------------------------------------------------------- */
private void setBufferTypes()
{
if (_connectorType==CONNECTOR_SOCKET)
{
_buffers.setRequestBufferType(Type.BYTE_ARRAY);
_buffers.setRequestHeaderType(Type.BYTE_ARRAY);
_buffers.setResponseBufferType(Type.BYTE_ARRAY);
_buffers.setResponseHeaderType(Type.BYTE_ARRAY);
}
else
{
_buffers.setRequestBufferType(Type.DIRECT);
_buffers.setRequestHeaderType(_useDirectBuffers?Type.DIRECT:Type.INDIRECT);
_buffers.setResponseBufferType(Type.DIRECT);
_buffers.setResponseHeaderType(_useDirectBuffers?Type.DIRECT:Type.INDIRECT);
}
}
/* ------------------------------------------------------------------------------- */
public HttpClient()
{
this(new SslContextFactory());
}
/* ------------------------------------------------------------------------------- */
public HttpClient(SslContextFactory sslContextFactory)
{
_sslContextFactory = sslContextFactory;
addBean(_sslContextFactory);
addBean(_buffers);
}
/* ------------------------------------------------------------------------------- */
/**
* @return True if connects will be in blocking mode.
*/
public boolean isConnectBlocking()
{
return _connectBlocking;
}
/* ------------------------------------------------------------------------------- */
/**
* @param connectBlocking True if connects will be in blocking mode.
*/
public void setConnectBlocking(boolean connectBlocking)
{
_connectBlocking = connectBlocking;
}
/* ------------------------------------------------------------------------------- */
public void send(HttpExchange exchange) throws IOException
{
boolean ssl = HttpScheme.HTTPS_BUFFER.equalsIgnoreCase(exchange.getScheme());
exchange.setStatus(HttpExchange.STATUS_WAITING_FOR_CONNECTION);
HttpDestination destination = getDestination(exchange.getAddress(), ssl);
destination.send(exchange);
}
/* ------------------------------------------------------------ */
/**
* @return the threadpool
*/
public ThreadPool getThreadPool()
{
return _threadPool;
}
/* ------------------------------------------------------------ */
/** Set the ThreadPool.
* The threadpool passed is added via {@link #addBean(Object)} so that
* it's lifecycle may be managed as a {@link AggregateLifeCycle}.
* @param threadPool the threadPool to set
*/
public void setThreadPool(ThreadPool threadPool)
{
removeBean(_threadPool);
_threadPool = threadPool;
addBean(_threadPool);
}
/* ------------------------------------------------------------ */
/**
* @param name
* @return Attribute associated with client
*/
public Object getAttribute(String name)
{
return _attributes.getAttribute(name);
}
/* ------------------------------------------------------------ */
/**
* @return names of attributes associated with client
*/
public Enumeration getAttributeNames()
{
return _attributes.getAttributeNames();
}
/* ------------------------------------------------------------ */
/**
* @param name
*/
public void removeAttribute(String name)
{
_attributes.removeAttribute(name);
}
/* ------------------------------------------------------------ */
/**
* Set an attribute on the HttpClient.
* Attributes are not used by the client, but are provided for
* so that users of a shared HttpClient may share other structures.
* @param name
* @param attribute
*/
public void setAttribute(String name, Object attribute)
{
_attributes.setAttribute(name,attribute);
}
/* ------------------------------------------------------------ */
public void clearAttributes()
{
_attributes.clearAttributes();
}
/* ------------------------------------------------------------------------------- */
public HttpDestination getDestination(Address remote, boolean ssl) throws IOException
{
if (remote == null)
throw new UnknownHostException("Remote socket address cannot be null.");
HttpDestination destination = _destinations.get(remote);
if (destination == null)
{
destination = new HttpDestination(this, remote, ssl);
if (_proxy != null && (_noProxy == null || !_noProxy.contains(remote.getHost())))
{
destination.setProxy(_proxy);
if (_proxyAuthentication != null)
destination.setProxyAuthentication(_proxyAuthentication);
}
HttpDestination other =_destinations.putIfAbsent(remote, destination);
if (other!=null)
destination=other;
}
return destination;
}
/* ------------------------------------------------------------ */
public void schedule(Timeout.Task task)
{
_timeoutQ.schedule(task);
}
/* ------------------------------------------------------------ */
public void schedule(Timeout.Task task, long timeout)
{
_timeoutQ.schedule(task, timeout - _timeoutQ.getDuration());
}
/* ------------------------------------------------------------ */
public void scheduleIdle(Timeout.Task task)
{
_idleTimeoutQ.schedule(task);
}
/* ------------------------------------------------------------ */
public void cancel(Timeout.Task task)
{
task.cancel();
}
/* ------------------------------------------------------------ */
/**
* Get whether the connector can use direct NIO buffers.
*/
public boolean getUseDirectBuffers()
{
return _useDirectBuffers;
}
/* ------------------------------------------------------------ */
/** Set a RealmResolver for client Authentication.
* If a realmResolver is set, then the HttpDestinations created by
* this client will instantiate a {@link SecurityListener} so that
* BASIC and DIGEST authentication can be performed.
* @param resolver
*/
public void setRealmResolver(RealmResolver resolver)
{
_realmResolver = resolver;
}
/* ------------------------------------------------------------ */
/**
* returns the SecurityRealmResolver reg_realmResolveristered with the HttpClient or null
*
* @return the SecurityRealmResolver reg_realmResolveristered with the HttpClient or null
*/
public RealmResolver getRealmResolver()
{
return _realmResolver;
}
/* ------------------------------------------------------------ */
public boolean hasRealms()
{
return _realmResolver == null ? false : true;
}
/* ------------------------------------------------------------ */
/**
* Registers a listener that can listen to the stream of execution between the client and the
* server and influence events. Sequential calls to the method wrapper sequentially wrap the preceding
* listener in a delegation model.
* <p/>
* NOTE: the SecurityListener is a special listener which doesn't need to be added via this
* mechanic, if you register security realms then it will automatically be added as the top listener of the
* delegation stack.
*
* @param listenerClass
*/
public void registerListener(String listenerClass)
{
if (_registeredListeners == null)
{
_registeredListeners = new LinkedList<String>();
}
_registeredListeners.add(listenerClass);
}
/* ------------------------------------------------------------ */
public LinkedList<String> getRegisteredListeners()
{
return _registeredListeners;
}
/* ------------------------------------------------------------ */
/**
* Set to use NIO direct buffers.
*
* @param direct If True (the default), the connector can use NIO direct
* buffers. Some JVMs have memory management issues (bugs) with
* direct buffers.
*/
public void setUseDirectBuffers(boolean direct)
{
_useDirectBuffers = direct;
setBufferTypes();
}
/* ------------------------------------------------------------ */
/**
* Get the type of connector (socket, blocking or select) in use.
*/
public int getConnectorType()
{
return _connectorType;
}
/* ------------------------------------------------------------ */
public void setConnectorType(int connectorType)
{
this._connectorType = connectorType;
setBufferTypes();
}
/* ------------------------------------------------------------ */
public int getMaxConnectionsPerAddress()
{
return _maxConnectionsPerAddress;
}
/* ------------------------------------------------------------ */
public void setMaxConnectionsPerAddress(int maxConnectionsPerAddress)
{
_maxConnectionsPerAddress = maxConnectionsPerAddress;
}
public int getMaxQueueSizePerAddress()
{
return _maxQueueSizePerAddress;
}
public void setMaxQueueSizePerAddress(int maxQueueSizePerAddress)
{
this._maxQueueSizePerAddress = maxQueueSizePerAddress;
}
/* ------------------------------------------------------------ */
@Override
protected void doStart() throws Exception
{
setBufferTypes();
_timeoutQ.setDuration(_timeout);
_timeoutQ.setNow();
_idleTimeoutQ.setDuration(_idleTimeout);
_idleTimeoutQ.setNow();
if (_threadPool==null)
{
QueuedThreadPool pool = new LocalQueuedThreadPool();
pool.setMaxThreads(16);
pool.setDaemon(true);
pool.setName("HttpClient");
_threadPool = pool;
addBean(_threadPool,true);
}
_connector=(_connectorType == CONNECTOR_SELECT_CHANNEL)?new SelectConnector(this):new SocketConnector(this);
addBean(_connector,true);
super.doStart();
_threadPool.dispatch(new Runnable()
{
public void run()
{
while (isRunning())
{
_timeoutQ.tick(System.currentTimeMillis());
_idleTimeoutQ.tick(_timeoutQ.getNow());
try
{
Thread.sleep(200);
}
catch (InterruptedException ignored)
{
}
}
}
});
}
/* ------------------------------------------------------------ */
@Override
protected void doStop() throws Exception
{
for (HttpDestination destination : _destinations.values())
destination.close();
_timeoutQ.cancelAll();
_idleTimeoutQ.cancelAll();
super.doStop();
if (_threadPool instanceof LocalQueuedThreadPool)
{
removeBean(_threadPool);
_threadPool = null;
}
removeBean(_connector);
}
/* ------------------------------------------------------------ */
interface Connector extends LifeCycle
{
public void startConnection(HttpDestination destination) throws IOException;
}
/* ------------------------------------------------------------ */
/**
* if a keystore location has been provided then client will attempt to use it as the keystore,
* otherwise we simply ignore certificates and run with a loose ssl context.
*
* @return the SSL context
*/
protected SSLContext getSSLContext()
{
return _sslContextFactory.getSslContext();
}
/* ------------------------------------------------------------ */
/**
* @return the instance of SslContextFactory associated with the client
*/
public SslContextFactory getSslContextFactory()
{
return _sslContextFactory;
}
/* ------------------------------------------------------------ */
/**
* @return the period in milliseconds a {@link AbstractHttpConnection} can be idle for before it is closed.
*/
public long getIdleTimeout()
{
return _idleTimeout;
}
/* ------------------------------------------------------------ */
/**
* @param ms the period in milliseconds a {@link AbstractHttpConnection} can be idle for before it is closed.
*/
public void setIdleTimeout(long ms)
{
_idleTimeout = ms;
}
/* ------------------------------------------------------------ */
/**
* @return the period in ms that an exchange will wait for a response from the server.
* @deprecated use {@link #getTimeout()} instead.
*/
@Deprecated
public int getSoTimeout()
{
return Long.valueOf(getTimeout()).intValue();
}
/* ------------------------------------------------------------ */
/**
* @deprecated use {@link #setTimeout(long)} instead.
* @param timeout the period in ms that an exchange will wait for a response from the server.
*/
@Deprecated
public void setSoTimeout(int timeout)
{
setTimeout(timeout);
}
/* ------------------------------------------------------------ */
/**
* @return the period in ms that an exchange will wait for a response from the server.
*/
public long getTimeout()
{
return _timeout;
}
/* ------------------------------------------------------------ */
/**
* @param timeout the period in ms that an exchange will wait for a response from the server.
*/
public void setTimeout(long timeout)
{
_timeout = timeout;
}
/* ------------------------------------------------------------ */
/**
* @return the period in ms before timing out an attempt to connect
*/
public int getConnectTimeout()
{
return _connectTimeout;
}
/* ------------------------------------------------------------ */
/**
* @param connectTimeout the period in ms before timing out an attempt to connect
*/
public void setConnectTimeout(int connectTimeout)
{
this._connectTimeout = connectTimeout;
}
/* ------------------------------------------------------------ */
public Address getProxy()
{
return _proxy;
}
/* ------------------------------------------------------------ */
public void setProxy(Address proxy)
{
this._proxy = proxy;
}
/* ------------------------------------------------------------ */
public Authentication getProxyAuthentication()
{
return _proxyAuthentication;
}
/* ------------------------------------------------------------ */
public void setProxyAuthentication(Authentication authentication)
{
_proxyAuthentication = authentication;
}
/* ------------------------------------------------------------ */
public boolean isProxied()
{
return this._proxy != null;
}
/* ------------------------------------------------------------ */
public Set<String> getNoProxy()
{
return _noProxy;
}
/* ------------------------------------------------------------ */
public void setNoProxy(Set<String> noProxyAddresses)
{
_noProxy = noProxyAddresses;
}
/* ------------------------------------------------------------ */
public int maxRetries()
{
return _maxRetries;
}
/* ------------------------------------------------------------ */
public void setMaxRetries(int retries)
{
_maxRetries = retries;
}
/* ------------------------------------------------------------ */
public int maxRedirects()
{
return _maxRedirects;
}
/* ------------------------------------------------------------ */
public void setMaxRedirects(int redirects)
{
_maxRedirects = redirects;
}
public int getRequestBufferSize()
{
return _buffers.getRequestBufferSize();
}
public void setRequestBufferSize(int requestBufferSize)
{
_buffers.setRequestBufferSize(requestBufferSize);
}
public int getRequestHeaderSize()
{
return _buffers.getRequestHeaderSize();
}
public void setRequestHeaderSize(int requestHeaderSize)
{
_buffers.setRequestHeaderSize(requestHeaderSize);
}
public int getResponseBufferSize()
{
return _buffers.getResponseBufferSize();
}
public void setResponseBufferSize(int responseBufferSize)
{
_buffers.setResponseBufferSize(responseBufferSize);
}
public int getResponseHeaderSize()
{
return _buffers.getResponseHeaderSize();
}
public void setResponseHeaderSize(int responseHeaderSize)
{
_buffers.setResponseHeaderSize(responseHeaderSize);
}
public Type getRequestBufferType()
{
return _buffers.getRequestBufferType();
}
public Type getRequestHeaderType()
{
return _buffers.getRequestHeaderType();
}
public Type getResponseBufferType()
{
return _buffers.getResponseBufferType();
}
public Type getResponseHeaderType()
{
return _buffers.getResponseHeaderType();
}
public void setRequestBuffers(Buffers requestBuffers)
{
_buffers.setRequestBuffers(requestBuffers);
}
public void setResponseBuffers(Buffers responseBuffers)
{
_buffers.setResponseBuffers(responseBuffers);
}
public Buffers getRequestBuffers()
{
return _buffers.getRequestBuffers();
}
public Buffers getResponseBuffers()
{
return _buffers.getResponseBuffers();
}
public void setMaxBuffers(int maxBuffers)
{
_buffers.setMaxBuffers(maxBuffers);
}
public int getMaxBuffers()
{
return _buffers.getMaxBuffers();
}
/* ------------------------------------------------------------ */
@Deprecated
public String getTrustStoreLocation()
{
return _sslContextFactory.getTrustStore();
}
/* ------------------------------------------------------------ */
@Deprecated
public void setTrustStoreLocation(String trustStoreLocation)
{
_sslContextFactory.setTrustStore(trustStoreLocation);
}
/* ------------------------------------------------------------ */
@Deprecated
public InputStream getTrustStoreInputStream()
{
return _sslContextFactory.getTrustStoreInputStream();
}
/* ------------------------------------------------------------ */
@Deprecated
public void setTrustStoreInputStream(InputStream trustStoreInputStream)
{
_sslContextFactory.setTrustStoreInputStream(trustStoreInputStream);
}
/* ------------------------------------------------------------ */
@Deprecated
public String getKeyStoreLocation()
{
return _sslContextFactory.getKeyStorePath();
}
/* ------------------------------------------------------------ */
@Deprecated
public void setKeyStoreLocation(String keyStoreLocation)
{
_sslContextFactory.setKeyStorePath(keyStoreLocation);
}
@Deprecated
public InputStream getKeyStoreInputStream()
{
return _sslContextFactory.getKeyStoreInputStream();
}
@Deprecated
public void setKeyStoreInputStream(InputStream keyStoreInputStream)
{
_sslContextFactory.setKeyStoreInputStream(keyStoreInputStream);
}
/* ------------------------------------------------------------ */
@Deprecated
public void setKeyStorePassword(String keyStorePassword)
{
_sslContextFactory.setKeyStorePassword(keyStorePassword);
}
/* ------------------------------------------------------------ */
@Deprecated
public void setKeyManagerPassword(String keyManagerPassword)
{
_sslContextFactory.setKeyManagerPassword(keyManagerPassword);
}
/* ------------------------------------------------------------ */
@Deprecated
public void setTrustStorePassword(String trustStorePassword)
{
_sslContextFactory.setTrustStorePassword(trustStorePassword);
}
/* ------------------------------------------------------------ */
@Deprecated
public String getKeyStoreType()
{
return _sslContextFactory.getKeyStoreType();
}
/* ------------------------------------------------------------ */
@Deprecated
public void setKeyStoreType(String keyStoreType)
{
_sslContextFactory.setKeyStoreType(keyStoreType);
}
/* ------------------------------------------------------------ */
@Deprecated
public String getTrustStoreType()
{
return _sslContextFactory.getTrustStoreType();
}
/* ------------------------------------------------------------ */
@Deprecated
public void setTrustStoreType(String trustStoreType)
{
_sslContextFactory.setTrustStoreType(trustStoreType);
}
/* ------------------------------------------------------------ */
@Deprecated
public String getKeyManagerAlgorithm()
{
return _sslContextFactory.getSslKeyManagerFactoryAlgorithm();
}
/* ------------------------------------------------------------ */
@Deprecated
public void setKeyManagerAlgorithm(String keyManagerAlgorithm)
{
_sslContextFactory.setSslKeyManagerFactoryAlgorithm(keyManagerAlgorithm);
}
/* ------------------------------------------------------------ */
@Deprecated
public String getTrustManagerAlgorithm()
{
return _sslContextFactory.getTrustManagerFactoryAlgorithm();
}
/* ------------------------------------------------------------ */
@Deprecated
public void setTrustManagerAlgorithm(String trustManagerAlgorithm)
{
_sslContextFactory.setTrustManagerFactoryAlgorithm(trustManagerAlgorithm);
}
/* ------------------------------------------------------------ */
@Deprecated
public String getProtocol()
{
return _sslContextFactory.getProtocol();
}
/* ------------------------------------------------------------ */
@Deprecated
public void setProtocol(String protocol)
{
_sslContextFactory.setProtocol(protocol);
}
/* ------------------------------------------------------------ */
@Deprecated
public String getProvider()
{
return _sslContextFactory.getProvider();
}
/* ------------------------------------------------------------ */
@Deprecated
public void setProvider(String provider)
{
_sslContextFactory.setProvider(provider);
}
/* ------------------------------------------------------------ */
@Deprecated
public String getSecureRandomAlgorithm()
{
return _sslContextFactory.getSecureRandomAlgorithm();
}
/* ------------------------------------------------------------ */
@Deprecated
public void setSecureRandomAlgorithm(String secureRandomAlgorithm)
{
_sslContextFactory.setSecureRandomAlgorithm(secureRandomAlgorithm);
}
private static class LocalQueuedThreadPool extends QueuedThreadPool
{
}
}

View File

@ -1,734 +0,0 @@
//
// ========================================================================
// Copyright (c) 1995-2012 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
//
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
//
package org.eclipse.jetty.client;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.net.ProtocolException;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.RejectedExecutionException;
import org.eclipse.jetty.client.HttpClient.Connector;
import org.eclipse.jetty.client.security.Authentication;
import org.eclipse.jetty.client.security.SecurityListener;
import org.eclipse.jetty.http.HttpCookie;
import org.eclipse.jetty.http.HttpHeader;
import org.eclipse.jetty.http.HttpMethod;
import org.eclipse.jetty.http.HttpStatus;
import org.eclipse.jetty.http.PathMap;
import org.eclipse.jetty.io.ByteArrayBuffer;
import org.eclipse.jetty.io.Connection;
import org.eclipse.jetty.io.EndPoint;
import org.eclipse.jetty.util.component.AggregateLifeCycle;
import org.eclipse.jetty.util.component.Dumpable;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
/**
* @version $Revision: 879 $ $Date: 2009-09-11 16:13:28 +0200 (Fri, 11 Sep 2009) $
*/
public class HttpDestination implements Dumpable
{
private static final Logger LOG = Log.getLogger(HttpDestination.class);
private final List<HttpExchange> _queue = new LinkedList<HttpExchange>();
private final List<AbstractHttpConnection> _connections = new LinkedList<AbstractHttpConnection>();
private final BlockingQueue<Object> _newQueue = new ArrayBlockingQueue<Object>(10, true);
private final List<AbstractHttpConnection> _idle = new ArrayList<AbstractHttpConnection>();
private final HttpClient _client;
private final Address _address;
private final boolean _ssl;
private final ByteArrayBuffer _hostHeader;
private volatile int _maxConnections;
private volatile int _maxQueueSize;
private int _pendingConnections = 0;
private int _newConnection = 0;
private volatile Address _proxy;
private Authentication _proxyAuthentication;
private PathMap _authorizations;
private List<HttpCookie> _cookies;
HttpDestination(HttpClient client, Address address, boolean ssl)
{
_client = client;
_address = address;
_ssl = ssl;
_maxConnections = _client.getMaxConnectionsPerAddress();
_maxQueueSize = _client.getMaxQueueSizePerAddress();
String addressString = address.getHost();
if (address.getPort() != (_ssl ? 443 : 80))
addressString += ":" + address.getPort();
_hostHeader = new ByteArrayBuffer(addressString);
}
public HttpClient getHttpClient()
{
return _client;
}
public Address getAddress()
{
return _address;
}
public boolean isSecure()
{
return _ssl;
}
public ByteBuffer getHostHeader()
{
return _hostHeader;
}
public int getMaxConnections()
{
return _maxConnections;
}
public void setMaxConnections(int maxConnections)
{
this._maxConnections = maxConnections;
}
public int getMaxQueueSize()
{
return _maxQueueSize;
}
public void setMaxQueueSize(int maxQueueSize)
{
this._maxQueueSize = maxQueueSize;
}
public int getConnections()
{
synchronized (this)
{
return _connections.size();
}
}
public int getIdleConnections()
{
synchronized (this)
{
return _idle.size();
}
}
public void addAuthorization(String pathSpec, Authentication authorization)
{
synchronized (this)
{
if (_authorizations == null)
_authorizations = new PathMap();
_authorizations.put(pathSpec, authorization);
}
// TODO query and remove methods
}
public void addCookie(HttpCookie cookie)
{
synchronized (this)
{
if (_cookies == null)
_cookies = new ArrayList<HttpCookie>();
_cookies.add(cookie);
}
// TODO query, remove and age methods
}
/**
* Get a connection. We either get an idle connection if one is available, or
* we make a new connection, if we have not yet reached maxConnections. If we
* have reached maxConnections, we wait until the number reduces.
*
* @param timeout max time prepared to block waiting to be able to get a connection
* @return a HttpConnection for this destination
* @throws IOException if an I/O error occurs
*/
private AbstractHttpConnection getConnection(long timeout) throws IOException
{
AbstractHttpConnection connection = null;
while ((connection == null) && (connection = getIdleConnection()) == null && timeout > 0)
{
boolean startConnection = false;
synchronized (this)
{
int totalConnections = _connections.size() + _pendingConnections;
if (totalConnections < _maxConnections)
{
_newConnection++;
startConnection = true;
}
}
if (startConnection)
{
startNewConnection();
try
{
Object o = _newQueue.take();
if (o instanceof AbstractHttpConnection)
{
connection = (AbstractHttpConnection)o;
}
else
throw (IOException)o;
}
catch (InterruptedException e)
{
LOG.ignore(e);
}
}
else
{
try
{
Thread.currentThread();
Thread.sleep(200);
timeout -= 200;
}
catch (InterruptedException e)
{
LOG.ignore(e);
}
}
}
return connection;
}
public AbstractHttpConnection reserveConnection(long timeout) throws IOException
{
AbstractHttpConnection connection = getConnection(timeout);
if (connection != null)
connection.setReserved(true);
return connection;
}
public AbstractHttpConnection getIdleConnection() throws IOException
{
AbstractHttpConnection connection = null;
while (true)
{
synchronized (this)
{
if (connection != null)
{
_connections.remove(connection);
connection.close();
connection = null;
}
if (_idle.size() > 0)
connection = _idle.remove(_idle.size() - 1);
}
if (connection == null)
{
return null;
}
// Check if the connection was idle,
// but it expired just a moment ago
if (connection.cancelIdleTimeout())
{
return connection;
}
}
}
protected void startNewConnection()
{
try
{
synchronized (this)
{
_pendingConnections++;
}
final Connector connector = _client._connector;
if (connector != null)
connector.startConnection(this);
}
catch (Exception e)
{
LOG.debug(e);
onConnectionFailed(e);
}
}
public void onConnectionFailed(Throwable throwable)
{
Throwable connect_failure = null;
boolean startConnection = false;
synchronized (this)
{
_pendingConnections--;
if (_newConnection > 0)
{
connect_failure = throwable;
_newConnection--;
}
else if (_queue.size() > 0)
{
HttpExchange ex = _queue.remove(0);
if (ex.setStatus(HttpExchange.STATUS_EXCEPTED))
ex.getEventListener().onConnectionFailed(throwable);
// Since an existing connection had failed, we need to create a
// connection if the queue is not empty and client is running.
if (!_queue.isEmpty() && _client.isStarted())
startConnection = true;
}
}
if (startConnection)
startNewConnection();
if (connect_failure != null)
{
try
{
_newQueue.put(connect_failure);
}
catch (InterruptedException e)
{
LOG.ignore(e);
}
}
}
public void onException(Throwable throwable)
{
synchronized (this)
{
_pendingConnections--;
if (_queue.size() > 0)
{
HttpExchange ex = _queue.remove(0);
if(ex.setStatus(HttpExchange.STATUS_EXCEPTED))
ex.getEventListener().onException(throwable);
}
}
}
public void onNewConnection(final AbstractHttpConnection connection) throws IOException
{
Connection q_connection = null;
synchronized (this)
{
_pendingConnections--;
_connections.add(connection);
if (_newConnection > 0)
{
q_connection = connection;
_newConnection--;
}
else if (_queue.size() == 0)
{
connection.setIdleTimeout();
_idle.add(connection);
}
else
{
EndPoint endPoint = connection.getEndPoint();
if (isProxied() && endPoint instanceof SelectConnector.UpgradableEndPoint)
{
SelectConnector.UpgradableEndPoint proxyEndPoint = (SelectConnector.UpgradableEndPoint)endPoint;
HttpExchange exchange = _queue.get(0);
ConnectExchange connect = new ConnectExchange(getAddress(), proxyEndPoint, exchange);
connect.setAddress(getProxy());
send(connection, connect);
}
else
{
HttpExchange exchange = _queue.remove(0);
send(connection, exchange);
}
}
}
if (q_connection != null)
{
try
{
_newQueue.put(q_connection);
}
catch (InterruptedException e)
{
LOG.ignore(e);
}
}
}
public void returnConnection(AbstractHttpConnection connection, boolean close) throws IOException
{
if (connection.isReserved())
connection.setReserved(false);
if (close)
{
try
{
connection.close();
}
catch (IOException e)
{
LOG.ignore(e);
}
}
if (!_client.isStarted())
return;
if (!close && connection.getEndPoint().isOpen())
{
synchronized (this)
{
if (_queue.size() == 0)
{
connection.setIdleTimeout();
_idle.add(connection);
}
else
{
HttpExchange ex = _queue.remove(0);
send(connection, ex);
}
this.notifyAll();
}
}
else
{
boolean startConnection = false;
synchronized (this)
{
_connections.remove(connection);
if (!_queue.isEmpty())
startConnection = true;
}
if (startConnection)
startNewConnection();
}
}
public void returnIdleConnection(AbstractHttpConnection connection)
{
// TODO work out the real idle time;
long idleForMs=connection!=null&&connection.getEndPoint()!=null?connection.getEndPoint().getMaxIdleTime():-1;
connection.onIdleExpired(idleForMs);
boolean startConnection = false;
synchronized (this)
{
_idle.remove(connection);
_connections.remove(connection);
if (!_queue.isEmpty() && _client.isStarted())
startConnection = true;
}
if (startConnection)
startNewConnection();
}
public void send(HttpExchange ex) throws IOException
{
LinkedList<String> listeners = _client.getRegisteredListeners();
if (listeners != null)
{
// Add registered listeners, fail if we can't load them
for (int i = listeners.size(); i > 0; --i)
{
String listenerClass = listeners.get(i - 1);
try
{
Class listener = Class.forName(listenerClass);
Constructor constructor = listener.getDeclaredConstructor(HttpDestination.class, HttpExchange.class);
HttpEventListener elistener = (HttpEventListener)constructor.newInstance(this, ex);
ex.setEventListener(elistener);
}
catch (final Exception e)
{
throw new IOException("Unable to instantiate registered listener for destination: " + listenerClass)
{
{initCause(e);}
};
}
}
}
// Security is supported by default and should be the first consulted
if (_client.hasRealms())
{
ex.setEventListener(new SecurityListener(this, ex));
}
doSend(ex);
}
public void resend(HttpExchange ex) throws IOException
{
ex.getEventListener().onRetry();
ex.reset();
doSend(ex);
}
protected void doSend(HttpExchange ex) throws IOException
{
// add cookies
// TODO handle max-age etc.
if (_cookies != null)
{
StringBuilder buf = null;
for (HttpCookie cookie : _cookies)
{
if (buf == null)
buf = new StringBuilder();
else
buf.append("; ");
buf.append(cookie.getName()); // TODO quotes
buf.append("=");
buf.append(cookie.getValue()); // TODO quotes
}
if (buf != null)
ex.addRequestHeader(HttpHeader.COOKIE, buf.toString());
}
// Add any known authorizations
if (_authorizations != null)
{
Authentication auth = (Authentication)_authorizations.match(ex.getRequestURI());
if (auth != null)
(auth).setCredentials(ex);
}
// Schedule the timeout here, before we queue the exchange
// so that we count also the queue time in the timeout
ex.scheduleTimeout(this);
AbstractHttpConnection connection = getIdleConnection();
if (connection != null)
{
send(connection, ex);
}
else
{
boolean startConnection = false;
synchronized (this)
{
if (_queue.size() == _maxQueueSize)
throw new RejectedExecutionException("Queue full for address " + _address);
_queue.add(ex);
if (_connections.size() + _pendingConnections < _maxConnections)
startConnection = true;
}
if (startConnection)
startNewConnection();
}
}
protected void exchangeExpired(HttpExchange exchange)
{
// The exchange may expire while waiting in the
// destination queue, make sure it is removed
synchronized (this)
{
_queue.remove(exchange);
}
}
protected void send(AbstractHttpConnection connection, HttpExchange exchange) throws IOException
{
synchronized (this)
{
// If server closes the connection, put the exchange back
// to the exchange queue and recycle the connection
if (!connection.send(exchange))
{
if (exchange.getStatus() <= HttpExchange.STATUS_WAITING_FOR_CONNECTION)
_queue.add(0, exchange);
returnIdleConnection(connection);
}
}
}
@Override
public synchronized String toString()
{
return String.format("HttpDestination@%x//%s:%d(%d/%d,%d,%d/%d)%n",hashCode(),_address.getHost(),_address.getPort(),_connections.size(),_maxConnections,_idle.size(),_queue.size(),_maxQueueSize);
}
public synchronized String toDetailString()
{
StringBuilder b = new StringBuilder();
b.append(toString());
b.append('\n');
synchronized (this)
{
for (AbstractHttpConnection connection : _connections)
{
b.append(connection.toDetailString());
if (_idle.contains(connection))
b.append(" IDLE");
b.append('\n');
}
}
b.append("--");
b.append('\n');
return b.toString();
}
public void setProxy(Address proxy)
{
_proxy = proxy;
}
public Address getProxy()
{
return _proxy;
}
public Authentication getProxyAuthentication()
{
return _proxyAuthentication;
}
public void setProxyAuthentication(Authentication authentication)
{
_proxyAuthentication = authentication;
}
public boolean isProxied()
{
return _proxy != null;
}
public void close() throws IOException
{
synchronized (this)
{
for (AbstractHttpConnection connection : _connections)
{
connection.close();
}
}
}
/* ------------------------------------------------------------ */
/**
* @see org.eclipse.jetty.util.component.Dumpable#dump()
*/
public String dump()
{
return AggregateLifeCycle.dump(this);
}
/* ------------------------------------------------------------ */
/**
* @see org.eclipse.jetty.util.component.Dumpable#dump(java.lang.Appendable, java.lang.String)
*/
public void dump(Appendable out, String indent) throws IOException
{
synchronized (this)
{
out.append(String.valueOf(this)+"idle="+_idle.size()+" pending="+_pendingConnections).append("\n");
AggregateLifeCycle.dump(out,indent,_connections);
}
}
private class ConnectExchange extends ContentExchange
{
private final SelectConnector.UpgradableEndPoint proxyEndPoint;
private final HttpExchange exchange;
public ConnectExchange(Address serverAddress, SelectConnector.UpgradableEndPoint proxyEndPoint, HttpExchange exchange)
{
this.proxyEndPoint = proxyEndPoint;
this.exchange = exchange;
setMethod(HttpMethod.CONNECT);
setVersion(exchange.getVersion());
String serverHostAndPort = serverAddress.toString();
setRequestURI(serverHostAndPort);
addRequestHeader(HttpHeader.HOST, serverHostAndPort);
addRequestHeader(HttpHeader.PROXY_CONNECTION, "keep-alive");
addRequestHeader(HttpHeader.USER_AGENT, "Jetty-Client");
}
@Override
protected void onResponseComplete() throws IOException
{
int responseStatus = getResponseStatus();
if (responseStatus == HttpStatus.OK_200)
{
proxyEndPoint.upgrade();
}
else if(responseStatus == HttpStatus.GATEWAY_TIMEOUT_504)
{
onExpire();
}
else
{
onException(new ProtocolException("Proxy: " + proxyEndPoint.getRemoteAddr() +":" + proxyEndPoint.getRemotePort() + " didn't return http return code 200, but " + responseStatus + " while trying to request: " + exchange.getAddress().toString()));
}
}
@Override
protected void onConnectionFailed(Throwable x)
{
HttpDestination.this.onConnectionFailed(x);
}
@Override
protected void onException(Throwable x)
{
_queue.remove(exchange);
if (exchange.setStatus(STATUS_EXCEPTED))
exchange.getEventListener().onException(x);
}
@Override
protected void onExpire()
{
_queue.remove(exchange);
if (exchange.setStatus(STATUS_EXPIRED))
exchange.getEventListener().onExpire();
}
}
}

View File

@ -1,68 +0,0 @@
//
// ========================================================================
// Copyright (c) 1995-2012 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
//
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
//
package org.eclipse.jetty.client;
import java.io.IOException;
/**
*
*
*
*/
public interface HttpEventListener
{
// TODO review the methods here, we can probably trim these down on what to expose
public void onRequestCommitted() throws IOException;
public void onRequestComplete() throws IOException;
public void onResponseStatus(ByteBuffer version, int status, ByteBuffer reason) throws IOException;
public void onResponseHeader(ByteBuffer name, ByteBuffer value) throws IOException;
public void onResponseHeaderComplete() throws IOException;
public void onResponseContent(ByteBuffer content) throws IOException;
public void onResponseComplete() throws IOException;
public void onConnectionFailed(Throwable ex);
public void onException(Throwable ex);
public void onExpire();
public void onRetry();
}

View File

@ -1,167 +0,0 @@
//
// ========================================================================
// Copyright (c) 1995-2012 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
//
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
//
package org.eclipse.jetty.client;
import java.io.IOException;
public class HttpEventListenerWrapper implements HttpEventListener
{
HttpEventListener _listener;
boolean _delegatingRequests;
boolean _delegatingResponses;
boolean _delegationResult = true;
private ByteBuffer _version;
private int _status;
private ByteBuffer _reason;
public HttpEventListenerWrapper()
{
_listener=null;
_delegatingRequests=false;
_delegatingResponses=false;
}
public HttpEventListenerWrapper(HttpEventListener eventListener,boolean delegating)
{
_listener=eventListener;
_delegatingRequests=delegating;
_delegatingResponses=delegating;
}
public HttpEventListener getEventListener()
{
return _listener;
}
public void setEventListener(HttpEventListener listener)
{
_listener = listener;
}
public boolean isDelegatingRequests()
{
return _delegatingRequests;
}
public boolean isDelegatingResponses()
{
return _delegatingResponses;
}
public void setDelegatingRequests(boolean delegating)
{
_delegatingRequests = delegating;
}
public void setDelegatingResponses(boolean delegating)
{
_delegatingResponses = delegating;
}
public void setDelegationResult( boolean result )
{
_delegationResult = result;
}
public void onConnectionFailed(Throwable ex)
{
if (_delegatingRequests)
_listener.onConnectionFailed(ex);
}
public void onException(Throwable ex)
{
if (_delegatingRequests||_delegatingResponses)
_listener.onException(ex);
}
public void onExpire()
{
if (_delegatingRequests||_delegatingResponses)
_listener.onExpire();
}
public void onRequestCommitted() throws IOException
{
if (_delegatingRequests)
_listener.onRequestCommitted();
}
public void onRequestComplete() throws IOException
{
if (_delegatingRequests)
_listener.onRequestComplete();
}
public void onResponseComplete() throws IOException
{
if (_delegatingResponses)
{
if (_delegationResult == false)
{
_listener.onResponseStatus(_version,_status,_reason);
}
_listener.onResponseComplete();
}
}
public void onResponseContent(ByteBuffer content) throws IOException
{
if (_delegatingResponses)
_listener.onResponseContent(content);
}
public void onResponseHeader(ByteBuffer name, ByteBuffer value) throws IOException
{
if (_delegatingResponses)
_listener.onResponseHeader(name,value);
}
public void onResponseHeaderComplete() throws IOException
{
if (_delegatingResponses)
_listener.onResponseHeaderComplete();
}
public void onResponseStatus(ByteBuffer version, int status, ByteBuffer reason) throws IOException
{
if (_delegatingResponses)
{
_listener.onResponseStatus(version,status,reason);
}
else
{
_version = version;
_status = status;
_reason = reason;
}
}
public void onRetry()
{
if (_delegatingRequests)
_listener.onRetry();
}
}

View File

@ -1,212 +0,0 @@
//
// ========================================================================
// Copyright (c) 1995-2012 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
//
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
//
package org.eclipse.jetty.client;
import java.io.IOException;
import org.eclipse.jetty.http.HttpHeader;
import org.eclipse.jetty.http.HttpScheme;
import org.eclipse.jetty.http.HttpStatus;
/**
* RedirectListener
*
* Detect and handle the redirect responses
*/
public class RedirectListener extends HttpEventListenerWrapper
{
private final HttpExchange _exchange;
private HttpDestination _destination;
private String _location;
private int _attempts;
private boolean _requestComplete;
private boolean _responseComplete;
private boolean _redirected;
public RedirectListener(HttpDestination destination, HttpExchange ex)
{
// Start of sending events through to the wrapped listener
// Next decision point is the onResponseStatus
super(ex.getEventListener(),true);
_destination = destination;
_exchange = ex;
}
@Override
public void onResponseStatus( ByteBuffer version, int status, ByteBuffer reason )
throws IOException
{
_redirected = ((status == HttpStatus.MOVED_PERMANENTLY_301 ||
status == HttpStatus.MOVED_TEMPORARILY_302) &&
_attempts < _destination.getHttpClient().maxRedirects());
if (_redirected)
{
setDelegatingRequests(false);
setDelegatingResponses(false);
}
super.onResponseStatus(version,status,reason);
}
@Override
public void onResponseHeader( ByteBuffer name, ByteBuffer value )
throws IOException
{
if (_redirected)
{
int header = HttpHeader.CACHE.getOrdinal(name);
switch (header)
{
case HttpHeader.LOCATION_ORDINAL:
_location = value.toString();
break;
}
}
super.onResponseHeader(name,value);
}
@Override
public void onRequestComplete() throws IOException
{
_requestComplete = true;
if (checkExchangeComplete())
{
super.onRequestComplete();
}
}
@Override
public void onResponseComplete() throws IOException
{
_responseComplete = true;
if (checkExchangeComplete())
{
super.onResponseComplete();
}
}
public boolean checkExchangeComplete()
throws IOException
{
if (_redirected && _requestComplete && _responseComplete)
{
if (_location != null)
{
if (_location.indexOf("://")>0)
{
_exchange.setURL(_location);
}
else
{
_exchange.setRequestURI(_location);
}
// destination may have changed
boolean isHttps = HttpScheme.HTTPS.equals(String.valueOf(_exchange.getScheme()));
HttpDestination destination=_destination.getHttpClient().getDestination(_exchange.getAddress(),isHttps);
if (_destination==destination)
{
_destination.resend(_exchange);
}
else
{
// unwrap to find ultimate listener.
HttpEventListener listener=this;
while(listener instanceof HttpEventListenerWrapper)
{
listener=((HttpEventListenerWrapper)listener).getEventListener();
}
//reset the listener
_exchange.getEventListener().onRetry();
_exchange.reset();
_exchange.setEventListener(listener);
// Set the new Host header
Address address = _exchange.getAddress();
int port = address.getPort();
StringBuilder hostHeader = new StringBuilder( 64 );
hostHeader.append( address.getHost() );
if( !( ( port == 80 && !isHttps ) || ( port == 443 && isHttps ) ) )
{
hostHeader.append( ':' );
hostHeader.append( port );
}
_exchange.setRequestHeader( HttpHeader.HOST, hostHeader.toString() );
destination.send(_exchange);
}
return false;
}
else
{
setDelegationResult(false);
}
}
return true;
}
public void onRetry()
{
_redirected=false;
_attempts++;
setDelegatingRequests(true);
setDelegatingResponses(true);
_requestComplete=false;
_responseComplete=false;
super.onRetry();
}
/**
* Delegate failed connection
*/
@Override
public void onConnectionFailed( Throwable ex )
{
setDelegatingRequests(true);
setDelegatingResponses(true);
super.onConnectionFailed( ex );
}
/**
* Delegate onException
*/
@Override
public void onException( Throwable ex )
{
setDelegatingRequests(true);
setDelegatingResponses(true);
super.onException( ex );
}
}

View File

@ -1,444 +0,0 @@
//
// ========================================================================
// Copyright (c) 1995-2012 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
//
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
//
package org.eclipse.jetty.client;
import java.io.IOException;
import java.net.SocketTimeoutException;
import java.nio.channels.SelectionKey;
import java.nio.channels.SocketChannel;
import java.nio.channels.UnresolvedAddressException;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import javax.net.ssl.SSLEngine;
import org.eclipse.jetty.io.AsyncEndPoint;
import org.eclipse.jetty.io.ConnectedEndPoint;
import org.eclipse.jetty.io.Connection;
import org.eclipse.jetty.io.nio.AsyncConnection;
import org.eclipse.jetty.io.nio.SelectChannelEndPoint;
import org.eclipse.jetty.io.nio.SelectorManager;
import org.eclipse.jetty.io.nio.SslConnection;
import org.eclipse.jetty.util.component.AggregateLifeCycle;
import org.eclipse.jetty.util.component.Dumpable;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.util.ssl.SslContextFactory;
import org.eclipse.jetty.util.thread.Timeout;
import org.eclipse.jetty.util.thread.Timeout.Task;
class SelectConnector extends AggregateLifeCycle implements HttpClient.Connector, Dumpable
{
private static final Logger LOG = Log.getLogger(SelectConnector.class);
private final HttpClient _httpClient;
private final Manager _selectorManager=new Manager();
private final Map<SocketChannel, Timeout.Task> _connectingChannels = new ConcurrentHashMap<SocketChannel, Timeout.Task>();
/* ------------------------------------------------------------ */
/**
* @param httpClient the HttpClient this connector is associated to. It is
* added via the {@link #addBean(Object, boolean)} as an unmanaged bean.
*/
SelectConnector(HttpClient httpClient)
{
_httpClient = httpClient;
addBean(_httpClient,false);
addBean(_selectorManager,true);
}
/* ------------------------------------------------------------ */
public void startConnection( HttpDestination destination )
throws IOException
{
SocketChannel channel = null;
try
{
channel = SocketChannel.open();
Address address = destination.isProxied() ? destination.getProxy() : destination.getAddress();
channel.socket().setTcpNoDelay(true);
if (_httpClient.isConnectBlocking())
{
channel.socket().connect(address.toSocketAddress(), _httpClient.getConnectTimeout());
channel.configureBlocking(false);
_selectorManager.register( channel, destination );
}
else
{
channel.configureBlocking(false);
channel.connect(address.toSocketAddress());
_selectorManager.register(channel,destination);
ConnectTimeout connectTimeout = new ConnectTimeout(channel,destination);
_httpClient.schedule(connectTimeout,_httpClient.getConnectTimeout());
_connectingChannels.put(channel,connectTimeout);
}
}
catch (UnresolvedAddressException ex)
{
if (channel != null)
channel.close();
destination.onConnectionFailed(ex);
}
catch(IOException ex)
{
if (channel != null)
channel.close();
destination.onConnectionFailed(ex);
}
}
/* ------------------------------------------------------------ */
class Manager extends SelectorManager
{
Logger LOG = SelectConnector.LOG;
@Override
public boolean dispatch(Runnable task)
{
return _httpClient._threadPool.dispatch(task);
}
@Override
protected void endPointOpened(SelectChannelEndPoint endpoint)
{
}
@Override
protected void endPointClosed(SelectChannelEndPoint endpoint)
{
}
@Override
protected void endPointUpgraded(ConnectedEndPoint endpoint, Connection oldConnection)
{
}
@Override
public AsyncConnection newConnection(SocketChannel channel, AsyncEndPoint endpoint, Object attachment)
{
return new AsyncHttpConnection(_httpClient.getRequestBuffers(),_httpClient.getResponseBuffers(),endpoint);
}
@Override
protected SelectChannelEndPoint newEndPoint(SocketChannel channel, SelectSet selectSet, SelectionKey key) throws IOException
{
// We're connected, cancel the connect timeout
Timeout.Task connectTimeout = _connectingChannels.remove(channel);
if (connectTimeout != null)
connectTimeout.cancel();
if (LOG.isDebugEnabled())
LOG.debug("Channels with connection pending: {}", _connectingChannels.size());
// key should have destination at this point (will be replaced by endpoint after this call)
HttpDestination dest=(HttpDestination)key.attachment();
SelectChannelEndPoint scep = new SelectChannelEndPoint(channel, selectSet, key, (int)_httpClient.getIdleTimeout());
AsyncEndPoint ep = scep;
if (dest.isSecure())
{
LOG.debug("secure to {}, proxied={}",channel,dest.isProxied());
ep = new UpgradableEndPoint(ep,newSslEngine(channel));
}
AsyncConnection connection = selectSet.getManager().newConnection(channel,ep, key.attachment());
ep.setConnection(connection);
AbstractHttpConnection httpConnection=(AbstractHttpConnection)connection;
httpConnection.setDestination(dest);
if (dest.isSecure() && !dest.isProxied())
((UpgradableEndPoint)ep).upgrade();
dest.onNewConnection(httpConnection);
return scep;
}
private synchronized SSLEngine newSslEngine(SocketChannel channel) throws IOException
{
SslContextFactory sslContextFactory = _httpClient.getSslContextFactory();
SSLEngine sslEngine;
if (channel != null)
{
String peerHost = channel.socket().getInetAddress().getHostAddress();
int peerPort = channel.socket().getPort();
sslEngine = sslContextFactory.newSslEngine(peerHost, peerPort);
}
else
{
sslEngine = sslContextFactory.newSslEngine();
}
sslEngine.setUseClientMode(true);
sslEngine.beginHandshake();
return sslEngine;
}
/* ------------------------------------------------------------ */
/* (non-Javadoc)
* @see org.eclipse.io.nio.SelectorManager#connectionFailed(java.nio.channels.SocketChannel, java.lang.Throwable, java.lang.Object)
*/
@Override
protected void connectionFailed(SocketChannel channel, Throwable ex, Object attachment)
{
Timeout.Task connectTimeout = _connectingChannels.remove(channel);
if (connectTimeout != null)
connectTimeout.cancel();
if (attachment instanceof HttpDestination)
((HttpDestination)attachment).onConnectionFailed(ex);
else
super.connectionFailed(channel,ex,attachment);
}
}
private class ConnectTimeout extends Timeout.Task
{
private final SocketChannel channel;
private final HttpDestination destination;
public ConnectTimeout(SocketChannel channel, HttpDestination destination)
{
this.channel = channel;
this.destination = destination;
}
@Override
public void expired()
{
if (channel.isConnectionPending())
{
LOG.debug("Channel {} timed out while connecting, closing it", channel);
try
{
// This will unregister the channel from the selector
channel.close();
}
catch (IOException x)
{
LOG.ignore(x);
}
destination.onConnectionFailed(new SocketTimeoutException());
}
}
}
public static class UpgradableEndPoint implements AsyncEndPoint
{
AsyncEndPoint _endp;
SSLEngine _engine;
public UpgradableEndPoint(AsyncEndPoint endp, SSLEngine engine) throws IOException
{
_engine=engine;
_endp=endp;
}
public void upgrade()
{
AsyncHttpConnection connection = (AsyncHttpConnection)_endp.getConnection();
SslConnection sslConnection = new SslConnection(_engine,_endp);
_endp.setConnection(sslConnection);
_endp=sslConnection.getSslEndPoint();
sslConnection.getSslEndPoint().setConnection(connection);
LOG.debug("upgrade {} to {} for {}",this,sslConnection,connection);
}
public Connection getConnection()
{
return _endp.getConnection();
}
public void setConnection(Connection connection)
{
_endp.setConnection(connection);
}
public void shutdownOutput() throws IOException
{
_endp.shutdownOutput();
}
public void dispatch()
{
_endp.asyncDispatch();
}
public void asyncDispatch()
{
_endp.asyncDispatch();
}
public boolean isOutputShutdown()
{
return _endp.isOutputShutdown();
}
public void shutdownInput() throws IOException
{
_endp.shutdownInput();
}
public void scheduleWrite()
{
_endp.scheduleWrite();
}
public boolean isInputShutdown()
{
return _endp.isInputShutdown();
}
public void close() throws IOException
{
_endp.close();
}
public int fill(ByteBuffer buffer) throws IOException
{
return _endp.fill(buffer);
}
public boolean isWritable()
{
return _endp.isWritable();
}
public boolean hasProgressed()
{
return _endp.hasProgressed();
}
public int flush(ByteBuffer buffer) throws IOException
{
return _endp.flush(buffer);
}
public void scheduleTimeout(Task task, long timeoutMs)
{
_endp.scheduleTimeout(task,timeoutMs);
}
public void cancelTimeout(Task task)
{
_endp.cancelTimeout(task);
}
public int flush(ByteBuffer header, ByteBuffer buffer, ByteBuffer trailer) throws IOException
{
return _endp.flush(header,buffer,trailer);
}
public String getLocalAddr()
{
return _endp.getLocalAddr();
}
public String getLocalHost()
{
return _endp.getLocalHost();
}
public int getLocalPort()
{
return _endp.getLocalPort();
}
public String getRemoteAddr()
{
return _endp.getRemoteAddr();
}
public String getRemoteHost()
{
return _endp.getRemoteHost();
}
public int getRemotePort()
{
return _endp.getRemotePort();
}
public boolean isBlocking()
{
return _endp.isBlocking();
}
public boolean blockReadable(long millisecs) throws IOException
{
return _endp.blockReadable(millisecs);
}
public boolean blockWritable(long millisecs) throws IOException
{
return _endp.blockWritable(millisecs);
}
public boolean isOpen()
{
return _endp.isOpen();
}
public Object getTransport()
{
return _endp.getTransport();
}
public void flush() throws IOException
{
_endp.flush();
}
public int getMaxIdleTime()
{
return _endp.getMaxIdleTime();
}
public void setMaxIdleTime(int timeMs) throws IOException
{
_endp.setMaxIdleTime(timeMs);
}
public void onIdleExpired(long idleForMs)
{
_endp.onIdleExpired(idleForMs);
}
public void setCheckForIdle(boolean check)
{
_endp.setCheckForIdle(check);
}
public boolean isCheckForIdle()
{
return _endp.isCheckForIdle();
}
public String toString()
{
return "Upgradable:"+_endp.toString();
}
}
}

View File

@ -1,111 +0,0 @@
//
// ========================================================================
// Copyright (c) 1995-2012 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
//
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
//
package org.eclipse.jetty.client;
import java.io.IOException;
import java.io.InterruptedIOException;
import java.net.Socket;
import javax.net.SocketFactory;
import org.eclipse.jetty.io.Connection;
import org.eclipse.jetty.io.EndPoint;
import org.eclipse.jetty.io.bio.SocketEndPoint;
import org.eclipse.jetty.util.component.AbstractLifeCycle;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
class SocketConnector extends AbstractLifeCycle implements HttpClient.Connector
{
private static final Logger LOG = Log.getLogger(SocketConnector.class);
/**
*
*/
private final HttpClient _httpClient;
/**
* @param httpClient
*/
SocketConnector(HttpClient httpClient)
{
_httpClient = httpClient;
}
public void startConnection(final HttpDestination destination) throws IOException
{
Socket socket= destination.isSecure()
?_httpClient.getSslContextFactory().newSslSocket()
:SocketFactory.getDefault().createSocket();
socket.setSoTimeout(0);
socket.setTcpNoDelay(true);
Address address = destination.isProxied() ? destination.getProxy() : destination.getAddress();
socket.connect(address.toSocketAddress(), _httpClient.getConnectTimeout());
final EndPoint endpoint=new SocketEndPoint(socket);
final AbstractHttpConnection connection=new BlockingHttpConnection(_httpClient.getRequestBuffers(),_httpClient.getResponseBuffers(),endpoint);
connection.setDestination(destination);
destination.onNewConnection(connection);
_httpClient.getThreadPool().dispatch(new Runnable()
{
public void run()
{
try
{
Connection con = connection;
while(true)
{
final Connection next = con.handle();
if (next!=con)
{
con=next;
continue;
}
break;
}
}
catch (IOException e)
{
if (e instanceof InterruptedIOException)
LOG.ignore(e);
else
{
LOG.debug(e);
destination.onException(e);
}
}
finally
{
try
{
destination.returnConnection(connection,true);
}
catch (IOException e)
{
LOG.debug(e);
}
}
}
});
}
}

View File

@ -1,57 +0,0 @@
//
// ========================================================================
// Copyright (c) 1995-2012 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
//
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
//
package org.eclipse.jetty.client.security;
import java.io.IOException;
import org.eclipse.jetty.client.HttpExchange;
import org.eclipse.jetty.http.HttpHeader;
import org.eclipse.jetty.io.ByteArrayBuffer;
import org.eclipse.jetty.util.B64Code;
import org.eclipse.jetty.util.StringUtil;
/**
* Sets authentication headers for BASIC authentication challenges
*
*
*/
public class BasicAuthentication implements Authentication
{
private ByteBuffer _authorization;
public BasicAuthentication(Realm realm) throws IOException
{
String authenticationString = "Basic " + B64Code.encode( realm.getPrincipal() + ":" + realm.getCredentials(), StringUtil.__ISO_8859_1);
_authorization= new ByteArrayBuffer(authenticationString);
}
/**
* BASIC authentication is of the form
*
* encoded credentials are of the form: username:password
*
*
*/
public void setCredentials( HttpExchange exchange ) throws IOException
{
exchange.setRequestHeader( HttpHeader.AUTHORIZATION_BUFFER, _authorization);
}
}

View File

@ -1,141 +0,0 @@
//
// ========================================================================
// Copyright (c) 1995-2012 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
//
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
//
package org.eclipse.jetty.client.security;
import java.io.IOException;
import java.security.MessageDigest;
import java.util.Map;
import org.eclipse.jetty.client.HttpExchange;
import org.eclipse.jetty.http.HttpHeader;
import org.eclipse.jetty.util.StringUtil;
import org.eclipse.jetty.util.TypeUtil;
public class DigestAuthentication implements Authentication
{
private static final String NC = "00000001";
Realm securityRealm;
Map details;
public DigestAuthentication(Realm realm, Map details)
{
this.securityRealm=realm;
this.details=details;
}
public void setCredentials( HttpExchange exchange )
throws IOException
{
StringBuilder buffer = new StringBuilder().append("Digest");
buffer.append(" ").append("username").append('=').append('"').append(securityRealm.getPrincipal()).append('"');
buffer.append(", ").append("realm").append('=').append('"').append(String.valueOf(details.get("realm"))).append('"');
buffer.append(", ").append("nonce").append('=').append('"').append(String.valueOf(details.get("nonce"))).append('"');
buffer.append(", ").append("uri").append('=').append('"').append(exchange.getURI()).append('"');
buffer.append(", ").append("algorithm").append('=').append(String.valueOf(details.get("algorithm")));
String cnonce = newCnonce(exchange, securityRealm, details);
buffer.append(", ").append("response").append('=').append('"').append(newResponse(cnonce,
exchange, securityRealm, details)).append('"');
buffer.append(", ").append("qop").append('=').append(String.valueOf(details.get("qop")));
buffer.append(", ").append("nc").append('=').append(NC);
buffer.append(", ").append("cnonce").append('=').append('"').append(cnonce).append('"');
exchange.setRequestHeader( HttpHeader.AUTHORIZATION,
new String(buffer.toString().getBytes(StringUtil.__ISO_8859_1)));
}
protected String newResponse(String cnonce, HttpExchange exchange, Realm securityRealm, Map details)
{
try{
MessageDigest md = MessageDigest.getInstance("MD5");
// calc A1 digest
md.update(securityRealm.getPrincipal().getBytes(StringUtil.__ISO_8859_1));
md.update((byte)':');
md.update(String.valueOf(details.get("realm")).getBytes(StringUtil.__ISO_8859_1));
md.update((byte)':');
md.update(securityRealm.getCredentials().getBytes(StringUtil.__ISO_8859_1));
byte[] ha1 = md.digest();
// calc A2 digest
md.reset();
md.update(exchange.getMethod().getBytes(StringUtil.__ISO_8859_1));
md.update((byte)':');
md.update(exchange.getURI().getBytes(StringUtil.__ISO_8859_1));
byte[] ha2=md.digest();
md.update(TypeUtil.toString(ha1,16).getBytes(StringUtil.__ISO_8859_1));
md.update((byte)':');
md.update(String.valueOf(details.get("nonce")).getBytes(StringUtil.__ISO_8859_1));
md.update((byte)':');
md.update(NC.getBytes(StringUtil.__ISO_8859_1));
md.update((byte)':');
md.update(cnonce.getBytes(StringUtil.__ISO_8859_1));
md.update((byte)':');
md.update(String.valueOf(details.get("qop")).getBytes(StringUtil.__ISO_8859_1));
md.update((byte)':');
md.update(TypeUtil.toString(ha2,16).getBytes(StringUtil.__ISO_8859_1));
byte[] digest=md.digest();
// check digest
return encode(digest);
}
catch(Exception e)
{
throw new RuntimeException(e);
}
}
protected String newCnonce(HttpExchange exchange, Realm securityRealm, Map details)
{
try
{
MessageDigest md = MessageDigest.getInstance("MD5");
byte[] b= md.digest(String.valueOf(System.currentTimeMillis()).getBytes(StringUtil.__ISO_8859_1));
return encode(b);
}
catch(Exception e)
{
throw new RuntimeException(e);
}
}
private static String encode(byte[] data)
{
StringBuilder buffer = new StringBuilder();
for (int i=0; i<data.length; i++)
{
buffer.append(Integer.toHexString((data[i] & 0xf0) >>> 4));
buffer.append(Integer.toHexString(data[i] & 0x0f));
}
return buffer.toString();
}
}

View File

@ -1,57 +0,0 @@
//
// ========================================================================
// Copyright (c) 1995-2012 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
//
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
//
package org.eclipse.jetty.client.security;
import java.io.IOException;
import org.eclipse.jetty.client.HttpExchange;
import org.eclipse.jetty.http.HttpHeader;
import org.eclipse.jetty.io.ByteArrayBuffer;
import org.eclipse.jetty.util.B64Code;
import org.eclipse.jetty.util.StringUtil;
/**
* Sets proxy authentication headers for BASIC authentication challenges
*
*
*/
public class ProxyAuthorization implements Authentication
{
private ByteBuffer _authorization;
public ProxyAuthorization(String username,String password) throws IOException
{
String authenticationString = "Basic " + B64Code.encode( username + ":" + password, StringUtil.__ISO_8859_1);
_authorization= new ByteArrayBuffer(authenticationString);
}
/**
* BASIC proxy authentication is of the form
*
* encoded credentials are of the form: username:password
*
*
*/
public void setCredentials( HttpExchange exchange ) throws IOException
{
exchange.setRequestHeader( HttpHeader.PROXY_AUTHORIZATION_BUFFER, _authorization);
}
}

View File

@ -1,276 +0,0 @@
//
// ========================================================================
// Copyright (c) 1995-2012 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
//
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
//
package org.eclipse.jetty.client.security;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.StringTokenizer;
import org.eclipse.jetty.client.HttpDestination;
import org.eclipse.jetty.client.HttpEventListenerWrapper;
import org.eclipse.jetty.client.HttpExchange;
import org.eclipse.jetty.http.HttpHeader;
import org.eclipse.jetty.http.HttpStatus;
import org.eclipse.jetty.util.StringUtil;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
/**
* SecurityListener
*
* Allow for insertion of security dialog when performing an
* HttpExchange.
*/
public class SecurityListener extends HttpEventListenerWrapper
{
private static final Logger LOG = Log.getLogger(SecurityListener.class);
private HttpDestination _destination;
private HttpExchange _exchange;
private boolean _requestComplete;
private boolean _responseComplete;
private boolean _needIntercept;
private int _attempts = 0; // TODO remember to settle on winning solution
public SecurityListener(HttpDestination destination, HttpExchange ex)
{
// Start of sending events through to the wrapped listener
// Next decision point is the onResponseStatus
super(ex.getEventListener(),true);
_destination=destination;
_exchange=ex;
}
/**
* scrapes an authentication type from the authString
*
* @param authString
* @return the authentication type
*/
protected String scrapeAuthenticationType( String authString )
{
String authType;
if ( authString.indexOf( " " ) == -1 )
{
authType = authString.toString().trim();
}
else
{
String authResponse = authString.toString();
authType = authResponse.substring( 0, authResponse.indexOf( " " ) ).trim();
}
return authType;
}
/**
* scrapes a set of authentication details from the authString
*
* @param authString
* @return the authentication details
*/
protected Map<String, String> scrapeAuthenticationDetails( String authString )
{
Map<String, String> authenticationDetails = new HashMap<String, String>();
authString = authString.substring( authString.indexOf( " " ) + 1, authString.length() );
StringTokenizer strtok = new StringTokenizer( authString, ",");
while ( strtok.hasMoreTokens() )
{
String token = strtok.nextToken();
String[] pair = token.split( "=" );
// authentication details ought to come in two parts, if not then just skip
if ( pair.length == 2 )
{
String itemName = pair[0].trim();
String itemValue = pair[1].trim();
itemValue = StringUtil.unquote( itemValue );
authenticationDetails.put( itemName, itemValue );
}
else
{
LOG.debug("SecurityListener: missed scraping authentication details - " + token );
}
}
return authenticationDetails;
}
@Override
public void onResponseStatus( ByteBuffer version, int status, ByteBuffer reason )
throws IOException
{
if (LOG.isDebugEnabled())
LOG.debug("SecurityListener:Response Status: " + status );
if ( status == HttpStatus.UNAUTHORIZED_401 && _attempts<_destination.getHttpClient().maxRetries())
{
// Let's absorb events until we have done some retries
setDelegatingResponses(false);
_needIntercept = true;
}
else
{
setDelegatingResponses(true);
setDelegatingRequests(true);
_needIntercept = false;
}
super.onResponseStatus(version,status,reason);
}
@Override
public void onResponseHeader( ByteBuffer name, ByteBuffer value )
throws IOException
{
if (LOG.isDebugEnabled())
LOG.debug( "SecurityListener:Header: " + name.toString() + " / " + value.toString() );
if (!isDelegatingResponses())
{
int header = HttpHeader.CACHE.getOrdinal(name);
switch (header)
{
case HttpHeader.WWW_AUTHENTICATE_ORDINAL:
// TODO don't hard code this bit.
String authString = value.toString();
String type = scrapeAuthenticationType( authString );
// TODO maybe avoid this map creation
Map<String,String> details = scrapeAuthenticationDetails( authString );
String pathSpec="/"; // TODO work out the real path spec
RealmResolver realmResolver = _destination.getHttpClient().getRealmResolver();
if ( realmResolver == null )
{
break;
}
Realm realm = realmResolver.getRealm( details.get("realm"), _destination, pathSpec ); // TODO work our realm correctly
if ( realm == null )
{
LOG.warn( "Unknown Security Realm: " + details.get("realm") );
}
else if ("digest".equalsIgnoreCase(type))
{
_destination.addAuthorization("/",new DigestAuthentication(realm,details));
}
else if ("basic".equalsIgnoreCase(type))
{
_destination.addAuthorization(pathSpec,new BasicAuthentication(realm));
}
break;
}
}
super.onResponseHeader(name,value);
}
@Override
public void onRequestComplete() throws IOException
{
_requestComplete = true;
if (_needIntercept)
{
if (_requestComplete && _responseComplete)
{
if (LOG.isDebugEnabled())
LOG.debug("onRequestComplete, Both complete: Resending from onResponseComplete "+_exchange);
_responseComplete = false;
_requestComplete = false;
setDelegatingRequests(true);
setDelegatingResponses(true);
_destination.resend(_exchange);
}
else
{
if (LOG.isDebugEnabled())
LOG.debug("onRequestComplete, Response not yet complete onRequestComplete, calling super for "+_exchange);
super.onRequestComplete();
}
}
else
{
if (LOG.isDebugEnabled())
LOG.debug("onRequestComplete, delegating to super with Request complete="+_requestComplete+", response complete="+_responseComplete+" "+_exchange);
super.onRequestComplete();
}
}
@Override
public void onResponseComplete() throws IOException
{
_responseComplete = true;
if (_needIntercept)
{
if (_requestComplete && _responseComplete)
{
if (LOG.isDebugEnabled())
LOG.debug("onResponseComplete, Both complete: Resending from onResponseComplete"+_exchange);
_responseComplete = false;
_requestComplete = false;
setDelegatingResponses(true);
setDelegatingRequests(true);
_destination.resend(_exchange);
}
else
{
if (LOG.isDebugEnabled())
LOG.debug("onResponseComplete, Request not yet complete from onResponseComplete, calling super "+_exchange);
super.onResponseComplete();
}
}
else
{
if (LOG.isDebugEnabled())
LOG.debug("OnResponseComplete, delegating to super with Request complete="+_requestComplete+", response complete="+_responseComplete+" "+_exchange);
super.onResponseComplete();
}
}
@Override
public void onRetry()
{
_attempts++;
setDelegatingRequests(true);
setDelegatingResponses(true);
_requestComplete=false;
_responseComplete=false;
_needIntercept=false;
super.onRetry();
}
}

View File

@ -1,64 +0,0 @@
//
// ========================================================================
// Copyright (c) 1995-2012 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
//
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
//
package org.eclipse.jetty.client.webdav;
import java.io.IOException;
import org.eclipse.jetty.client.CachedExchange;
import org.eclipse.jetty.http.HttpStatus;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
public class MkcolExchange extends CachedExchange
{
private static final Logger LOG = Log.getLogger(MkcolExchange.class);
boolean exists = false;
public MkcolExchange()
{
super(true);
}
/* ------------------------------------------------------------ */
@Override
protected void onResponseStatus(ByteBuffer version, int status, ByteBuffer reason) throws IOException
{
if ( status == HttpStatus.CREATED_201 )
{
LOG.debug( "MkcolExchange:Status: Successfully created resource" );
exists = true;
}
if ( status == HttpStatus.METHOD_NOT_ALLOWED_405 ) // returned when resource exists
{
LOG.debug( "MkcolExchange:Status: Resource must exist" );
exists = true;
}
super.onResponseStatus(version, status, reason);
}
public boolean exists()
{
return exists;
}
}

View File

@ -1,57 +0,0 @@
//
// ========================================================================
// Copyright (c) 1995-2012 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
//
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
//
package org.eclipse.jetty.client.webdav;
import java.io.IOException;
import org.eclipse.jetty.client.HttpExchange;
import org.eclipse.jetty.http.HttpStatus;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
public class PropfindExchange extends HttpExchange
{
private static final Logger LOG = Log.getLogger(PropfindExchange.class);
boolean _propertyExists = false;
/* ------------------------------------------------------------ */
@Override
protected void onResponseStatus(ByteBuffer version, int status, ByteBuffer reason) throws IOException
{
if ( status == HttpStatus.OK_200 )
{
LOG.debug( "PropfindExchange:Status: Exists" );
_propertyExists = true;
}
else
{
LOG.debug( "PropfindExchange:Status: Not Exists" );
}
super.onResponseStatus(version, status, reason);
}
public boolean exists()
{
return _propertyExists;
}
}

View File

@ -1,332 +0,0 @@
//
// ========================================================================
// Copyright (c) 1995-2012 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
//
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
//
package org.eclipse.jetty.client.webdav;
import java.io.IOException;
import org.eclipse.jetty.client.HttpDestination;
import org.eclipse.jetty.client.HttpEventListenerWrapper;
import org.eclipse.jetty.client.HttpExchange;
import org.eclipse.jetty.client.security.SecurityListener;
import org.eclipse.jetty.http.HttpMethod;
import org.eclipse.jetty.http.HttpStatus;
import org.eclipse.jetty.util.URIUtil;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
/**
* WebdavListener
*
*
*
*
*/
public class WebdavListener extends HttpEventListenerWrapper
{
private static final Logger LOG = Log.getLogger(WebdavListener.class);
private HttpDestination _destination;
private HttpExchange _exchange;
private boolean _requestComplete;
private boolean _responseComplete;
private boolean _webdavEnabled;
private boolean _needIntercept;
public WebdavListener(HttpDestination destination, HttpExchange ex)
{
// Start of sending events through to the wrapped listener
// Next decision point is the onResponseStatus
super(ex.getEventListener(),true);
_destination=destination;
_exchange=ex;
// We'll only enable webdav if this is a PUT request
if ( HttpMethod.PUT.asString().equalsIgnoreCase( _exchange.getMethod() ) )
{
_webdavEnabled = true;
}
}
@Override
public void onResponseStatus(ByteBuffer version, int status, ByteBuffer reason) throws IOException
{
if ( !_webdavEnabled )
{
_needIntercept = false;
super.onResponseStatus(version, status, reason);
return;
}
if (LOG.isDebugEnabled())
LOG.debug("WebdavListener:Response Status: " + status );
// The dav spec says that CONFLICT should be returned when the parent collection doesn't exist but I am seeing
// FORBIDDEN returned instead so running with that.
if ( status == HttpStatus.FORBIDDEN_403 || status == HttpStatus.CONFLICT_409 )
{
if ( _webdavEnabled )
{
if (LOG.isDebugEnabled())
LOG.debug("WebdavListener:Response Status: dav enabled, taking a stab at resolving put issue" );
setDelegatingResponses( false ); // stop delegating, we can try and fix this request
_needIntercept = true;
}
else
{
if (LOG.isDebugEnabled())
LOG.debug("WebdavListener:Response Status: Webdav Disabled" );
setDelegatingResponses( true ); // just make sure we delegate
setDelegatingRequests( true );
_needIntercept = false;
}
}
else
{
_needIntercept = false;
setDelegatingResponses( true );
setDelegatingRequests( true );
}
super.onResponseStatus(version, status, reason);
}
@Override
public void onResponseComplete() throws IOException
{
_responseComplete = true;
if (_needIntercept)
{
if ( _requestComplete && _responseComplete)
{
try
{
// we have some work to do before retrying this
if ( resolveCollectionIssues() )
{
setDelegatingRequests( true );
setDelegatingResponses(true);
_requestComplete = false;
_responseComplete = false;
_destination.resend(_exchange);
}
else
{
// admit defeat but retry because someone else might have
setDelegationResult(false);
setDelegatingRequests( true );
setDelegatingResponses(true);
super.onResponseComplete();
}
}
catch ( IOException ioe )
{
LOG.debug("WebdavListener:Complete:IOException: might not be dealing with dav server, delegate");
super.onResponseComplete();
}
}
else
{
if (LOG.isDebugEnabled())
LOG.debug("WebdavListener:Not ready, calling super");
super.onResponseComplete();
}
}
else
{
super.onResponseComplete();
}
}
@Override
public void onRequestComplete () throws IOException
{
_requestComplete = true;
if (_needIntercept)
{
if ( _requestComplete && _responseComplete)
{
try
{
// we have some work to do before retrying this
if ( resolveCollectionIssues() )
{
setDelegatingRequests( true );
setDelegatingResponses(true);
_requestComplete = false;
_responseComplete = false;
_destination.resend(_exchange);
}
else
{
// admit defeat but retry because someone else might have
setDelegatingRequests( true );
setDelegatingResponses(true);
super.onRequestComplete();
}
}
catch ( IOException ioe )
{
LOG.debug("WebdavListener:Complete:IOException: might not be dealing with dav server, delegate");
super.onRequestComplete();
}
}
else
{
if (LOG.isDebugEnabled())
LOG.debug("WebdavListener:Not ready, calling super");
super.onRequestComplete();
}
}
else
{
super.onRequestComplete();
}
}
/**
* walk through the steps to try and resolve missing parent collection issues via webdav
*
* TODO this really ought to use URI itself for this resolution
*
* @return
* @throws IOException
*/
private boolean resolveCollectionIssues() throws IOException
{
String uri = _exchange.getURI();
String[] uriCollection = _exchange.getURI().split("/");
int checkNum = uriCollection.length;
int rewind = 0;
String parentUri = URIUtil.parentPath( uri );
while ( parentUri != null && !checkExists(parentUri) )
{
++rewind;
parentUri = URIUtil.parentPath( parentUri );
}
// confirm webdav is supported for this collection
if ( checkWebdavSupported() )
{
for (int i = 0; i < rewind;)
{
makeCollection(parentUri + "/" + uriCollection[checkNum - rewind - 1]);
parentUri = parentUri + "/" + uriCollection[checkNum - rewind - 1];
--rewind;
}
}
else
{
return false;
}
return true;
}
private boolean checkExists( String uri ) throws IOException
{
if (uri == null)
{
System.out.println("have failed miserably");
return false;
}
PropfindExchange propfindExchange = new PropfindExchange();
propfindExchange.setAddress( _exchange.getAddress() );
propfindExchange.setMethod( HttpMethod.GET ); // PROPFIND acts wonky, just use get
propfindExchange.setScheme( _exchange.getScheme() );
propfindExchange.setEventListener( new SecurityListener( _destination, propfindExchange ) );
propfindExchange.setConfigureListeners( false );
propfindExchange.setRequestURI( uri );
_destination.send( propfindExchange );
try
{
propfindExchange.waitForDone();
return propfindExchange.exists();
}
catch ( InterruptedException ie )
{
LOG.ignore( ie );
return false;
}
}
private boolean makeCollection( String uri ) throws IOException
{
MkcolExchange mkcolExchange = new MkcolExchange();
mkcolExchange.setAddress( _exchange.getAddress() );
mkcolExchange.setMethod( "MKCOL " + uri + " HTTP/1.1" );
mkcolExchange.setScheme( _exchange.getScheme() );
mkcolExchange.setEventListener( new SecurityListener( _destination, mkcolExchange ) );
mkcolExchange.setConfigureListeners( false );
mkcolExchange.setRequestURI( uri );
_destination.send( mkcolExchange );
try
{
mkcolExchange.waitForDone();
return mkcolExchange.exists();
}
catch ( InterruptedException ie )
{
LOG.ignore( ie );
return false;
}
}
private boolean checkWebdavSupported() throws IOException
{
WebdavSupportedExchange supportedExchange = new WebdavSupportedExchange();
supportedExchange.setAddress( _exchange.getAddress() );
supportedExchange.setMethod( HttpMethod.OPTIONS );
supportedExchange.setScheme( _exchange.getScheme() );
supportedExchange.setEventListener( new SecurityListener( _destination, supportedExchange ) );
supportedExchange.setConfigureListeners( false );
supportedExchange.setRequestURI( _exchange.getURI() );
_destination.send( supportedExchange );
try
{
supportedExchange.waitTilCompletion();
return supportedExchange.isWebdavSupported();
}
catch (InterruptedException ie )
{
LOG.ignore( ie );
return false;
}
}
}

View File

@ -1,75 +0,0 @@
//
// ========================================================================
// Copyright (c) 1995-2012 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
//
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
//
package org.eclipse.jetty.client.webdav;
import java.io.IOException;
import org.eclipse.jetty.client.HttpExchange;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
public class WebdavSupportedExchange extends HttpExchange
{
private static final Logger LOG = Log.getLogger(WebdavSupportedExchange.class);
private boolean _webdavSupported = false;
private boolean _isComplete = false;
@Override
protected void onResponseHeader(ByteBuffer name, ByteBuffer value) throws IOException
{
if (LOG.isDebugEnabled())
LOG.debug("WebdavSupportedExchange:Header:" + name.toString() + " / " + value.toString() );
if ( "DAV".equals( name.toString() ) )
{
if ( value.toString().indexOf( "1" ) >= 0 || value.toString().indexOf( "2" ) >= 0 )
{
_webdavSupported = true;
}
}
super.onResponseHeader(name, value);
}
public void waitTilCompletion() throws InterruptedException
{
synchronized (this)
{
while ( !_isComplete)
{
this.wait();
}
}
}
@Override
protected void onResponseComplete() throws IOException
{
_isComplete = true;
super.onResponseComplete();
}
public boolean isWebdavSupported()
{
return _webdavSupported;
}
}

View File

@ -1,443 +0,0 @@
//
// ========================================================================
// Copyright (c) 1995-2012 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
//
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
//
package org.eclipse.jetty.client;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import org.junit.Test;
/**
* @version $Revision$ $Date$
*/
public abstract class AbstractConnectionTest
{
protected HttpClient newHttpClient()
{
HttpClient httpClient = new HttpClient();
// httpClient.setConnectorType(HttpClient.CONNECTOR_SOCKET);
return httpClient;
}
protected ServerSocket newServerSocket() throws IOException
{
ServerSocket serverSocket=new ServerSocket();
serverSocket.bind(null);
return serverSocket;
}
@Test
public void testServerClosedConnection() throws Exception
{
ServerSocket serverSocket = new ServerSocket();
serverSocket.bind(null);
int port=serverSocket.getLocalPort();
HttpClient httpClient = newHttpClient();
httpClient.setMaxConnectionsPerAddress(1);
httpClient.start();
try
{
CountDownLatch latch = new CountDownLatch(1);
HttpExchange exchange = new ConnectionExchange(latch);
exchange.setAddress(new Address("localhost", port));
exchange.setRequestURI("/");
httpClient.send(exchange);
Socket remote = serverSocket.accept();
// HttpClient.send() above is async, so if we write the response immediately
// there is a chance that it arrives before the request is being sent, so we
// read the request before sending the response to avoid the race
InputStream input = remote.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(input, "UTF-8"));
String line;
while ((line = reader.readLine()) != null)
{
if (line.length() == 0)
break;
}
OutputStream output = remote.getOutputStream();
output.write("HTTP/1.1 200 OK\r\n".getBytes("UTF-8"));
output.write("Content-Length: 0\r\n".getBytes("UTF-8"));
output.write("\r\n".getBytes("UTF-8"));
output.flush();
assertEquals(HttpExchange.STATUS_COMPLETED, exchange.waitForDone());
remote.close();
// Need to wait a bit to allow the client to detect
// that the server has closed the connection
Thread.sleep(500);
// The server has closed the connection and another attempt to send
// with the same connection would fail because the connection has been
// closed by the client as well.
// The client must open a new connection in this case, and we check
// that the new request completes correctly
exchange.reset();
httpClient.send(exchange);
remote = serverSocket.accept();
input = remote.getInputStream();
reader = new BufferedReader(new InputStreamReader(input, "UTF-8"));
while ((line = reader.readLine()) != null)
{
if (line.length() == 0)
break;
}
output = remote.getOutputStream();
output.write("HTTP/1.1 200 OK\r\n".getBytes("UTF-8"));
output.write("Content-Length: 0\r\n".getBytes("UTF-8"));
output.write("\r\n".getBytes("UTF-8"));
output.flush();
assertEquals(HttpExchange.STATUS_COMPLETED, exchange.waitForDone());
}
finally
{
httpClient.stop();
}
}
protected String getScheme()
{
return "http";
}
@Test
public void testServerClosedIncomplete() throws Exception
{
ServerSocket serverSocket = newServerSocket();
int port=serverSocket.getLocalPort();
HttpClient httpClient = newHttpClient();
httpClient.setMaxConnectionsPerAddress(1);
httpClient.start();
try
{
CountDownLatch latch = new CountDownLatch(1);
HttpExchange exchange = new ConnectionExchange(latch);
exchange.setScheme(getScheme());
exchange.setAddress(new Address("localhost", port));
exchange.setRequestURI("/");
httpClient.send(exchange);
Socket remote = serverSocket.accept();
// HttpClient.send() above is async, so if we write the response immediately
// there is a chance that it arrives before the request is being sent, so we
// read the request before sending the response to avoid the race
InputStream input = remote.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(input, "UTF-8"));
String line;
while ((line = reader.readLine()) != null)
{
if (line.length() == 0)
break;
}
OutputStream output = remote.getOutputStream();
output.write("HTTP/1.1 200 OK\r\n".getBytes("UTF-8"));
output.write("Content-Length: 10\r\n".getBytes("UTF-8"));
output.write("\r\n".getBytes("UTF-8"));
output.flush();
remote.close();
int status = exchange.waitForDone();
assertEquals(HttpExchange.STATUS_EXCEPTED, status);
}
finally
{
httpClient.stop();
}
}
@Test
public void testServerHalfClosedIncomplete() throws Exception
{
ServerSocket serverSocket = new ServerSocket();
serverSocket.bind(null);
int port=serverSocket.getLocalPort();
HttpClient httpClient = newHttpClient();
httpClient.setIdleTimeout(10000);
httpClient.setMaxConnectionsPerAddress(1);
httpClient.start();
try
{
CountDownLatch latch = new CountDownLatch(1);
HttpExchange exchange = new ConnectionExchange(latch);
exchange.setAddress(new Address("localhost", port));
exchange.setRequestURI("/");
httpClient.send(exchange);
Socket remote = serverSocket.accept();
// HttpClient.send() above is async, so if we write the response immediately
// there is a chance that it arrives before the request is being sent, so we
// read the request before sending the response to avoid the race
InputStream input = remote.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(input, "UTF-8"));
String line;
while ((line = reader.readLine()) != null)
{
if (line.length() == 0)
break;
}
OutputStream output = remote.getOutputStream();
output.write("HTTP/1.1 200 OK\r\n".getBytes("UTF-8"));
output.write("Content-Length: 10\r\n".getBytes("UTF-8"));
output.write("\r\n".getBytes("UTF-8"));
output.flush();
remote.shutdownOutput();
assertEquals(HttpExchange.STATUS_EXCEPTED, exchange.waitForDone());
}
finally
{
httpClient.stop();
}
}
@Test
public void testConnectionFailed() throws Exception
{
ServerSocket serverSocket = new ServerSocket();
serverSocket.bind(null);
int port=serverSocket.getLocalPort();
serverSocket.close();
HttpClient httpClient = newHttpClient();
httpClient.start();
try
{
CountDownLatch latch = new CountDownLatch(1);
HttpExchange exchange = new ConnectionExchange(latch);
exchange.setAddress(new Address("localhost", port));
exchange.setRequestURI("/");
httpClient.send(exchange);
boolean passed = latch.await(4000, TimeUnit.MILLISECONDS);
assertTrue(passed);
long wait = 100;
long maxWait = 10 * wait;
long curWait = wait;
while (curWait < maxWait && !exchange.isDone())
{
Thread.sleep(wait);
curWait += wait;
}
assertEquals(HttpExchange.STATUS_EXCEPTED, exchange.getStatus());
}
finally
{
httpClient.stop();
}
}
@Test
public void testMultipleConnectionsFailed() throws Exception
{
ServerSocket serverSocket = new ServerSocket();
serverSocket.bind(null);
int port=serverSocket.getLocalPort();
serverSocket.close();
HttpClient httpClient = newHttpClient();
httpClient.setMaxConnectionsPerAddress(1);
httpClient.start();
try
{
HttpExchange[] exchanges = new HttpExchange[20];
final CountDownLatch latch = new CountDownLatch(exchanges.length);
for (int i = 0; i < exchanges.length; ++i)
{
HttpExchange exchange = new HttpExchange()
{
@Override
protected void onConnectionFailed(Throwable x)
{
latch.countDown();
}
};
exchange.setAddress(new Address("localhost", port));
exchange.setRequestURI("/");
exchanges[i] = exchange;
}
for (HttpExchange exchange : exchanges)
httpClient.send(exchange);
for (HttpExchange exchange : exchanges)
assertEquals(HttpExchange.STATUS_EXCEPTED, exchange.waitForDone());
assertTrue(latch.await(1000, TimeUnit.MILLISECONDS));
}
finally
{
httpClient.stop();
}
}
@Test
public void testConnectionTimeout() throws Exception
{
HttpClient httpClient = newHttpClient();
int connectTimeout = 5000;
httpClient.setConnectTimeout(connectTimeout);
httpClient.start();
try
{
CountDownLatch latch = new CountDownLatch(1);
HttpExchange exchange = new ConnectionExchange(latch);
// Using a IP address has a different behavior than using a host name
exchange.setAddress(new Address("127.0.0.1", 1));
exchange.setRequestURI("/");
httpClient.send(exchange);
boolean passed = latch.await(connectTimeout * 2L, TimeUnit.MILLISECONDS);
assertTrue(passed);
int status = exchange.waitForDone();
assertEquals(HttpExchange.STATUS_EXCEPTED, status);
}
finally
{
httpClient.stop();
}
}
@Test
public void testIdleConnection() throws Exception
{
ServerSocket serverSocket = new ServerSocket();
serverSocket.bind(null);
int port=serverSocket.getLocalPort();
HttpClient httpClient = newHttpClient();
httpClient.setIdleTimeout(700);
httpClient.start();
try
{
HttpExchange exchange = new ConnectionExchange();
exchange.setAddress(new Address("localhost", port));
exchange.setRequestURI("/");
HttpDestination dest = httpClient.getDestination(new Address("localhost", port),false);
httpClient.send(exchange);
Socket server = serverSocket.accept();
server.setSoTimeout(5000);
byte[] buf = new byte[4096];
int len=server.getInputStream().read(buf);
assertEquals(1,dest.getConnections());
assertEquals(0,dest.getIdleConnections());
server.getOutputStream().write("HTTP/1.1 200 OK\r\nContent-Length: 0\r\n\r\n".getBytes());
assertEquals(HttpExchange.STATUS_COMPLETED,exchange.waitForDone());
Thread.sleep(200); // TODO get rid of this
assertEquals(1,dest.getConnections());
assertEquals(1,dest.getIdleConnections());
exchange = new ConnectionExchange();
exchange.setAddress(new Address("localhost", port));
exchange.setRequestURI("/");
httpClient.send(exchange);
assertEquals(1,dest.getConnections());
assertEquals(0,dest.getIdleConnections());
len=server.getInputStream().read(buf);
assertEquals(1,dest.getConnections());
assertEquals(0,dest.getIdleConnections());
server.getOutputStream().write("HTTP/1.1 200 OK\r\nContent-Length: 0\r\n\r\n".getBytes());
Thread.sleep(500);
assertEquals(1,dest.getConnections());
assertEquals(1,dest.getIdleConnections());
Thread.sleep(500);
assertEquals(0,dest.getConnections());
assertEquals(0,dest.getIdleConnections());
serverSocket.close();
}
finally
{
httpClient.stop();
}
}
protected class ConnectionExchange extends HttpExchange
{
private final CountDownLatch latch;
protected ConnectionExchange()
{
this.latch = null;
}
protected ConnectionExchange(CountDownLatch latch)
{
this.latch = latch;
}
@Override
protected void onConnectionFailed(Throwable ex)
{
if (latch!=null)
latch.countDown();
}
@Override
protected void onException(Throwable x)
{
if (latch!=null)
latch.countDown();
}
}
}

View File

@ -1,500 +0,0 @@
//
// ========================================================================
// Copyright (c) 1995-2012 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
//
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
//
package org.eclipse.jetty.client;
import java.io.IOException;
import java.net.SocketTimeoutException;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.server.AbstractHttpConnection;
import org.eclipse.jetty.server.Connector;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.handler.AbstractHandler;
import org.eclipse.jetty.server.nio.SelectChannelConnector;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.StdErrLog;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
/**
*/
public abstract class AbstractHttpExchangeCancelTest
{
private Server server;
private Connector connector;
@Before
public void setUp() throws Exception
{
server = new Server();
connector = new SelectChannelConnector();
server.addConnector(connector);
server.setHandler(new EmptyHandler());
server.start();
}
@After
public void tearDown() throws Exception
{
server.stop();
server.join();
}
/* ------------------------------------------------------------ */
@Test
public void testHttpExchangeCancelOnSend1() throws Exception
{
// One of the first things that HttpClient.send() does
// is to change the status of the exchange
// We exploit that to be sure the exchange is canceled
// without race conditions
TestHttpExchange exchange = new TestHttpExchange()
{
@Override
boolean setStatus(int status)
{
// Cancel before setting the new status
if (getStatus() == HttpExchange.STATUS_START &&
status == STATUS_WAITING_FOR_CONNECTION)
cancel();
return super.setStatus(status);
}
};
exchange.setAddress(newAddress());
exchange.setRequestURI("/");
getHttpClient().send(exchange);
// Cancelling here is wrong and makes the test fail spuriously
// due to a race condition with send(): the send() can complete
// before the exchange is canceled so it will be in STATUS_COMPLETE
// which will fail the test.
// exchange.cancel();
int status = exchange.waitForDone();
assertEquals(HttpExchange.STATUS_CANCELLED, status);
assertFalse(exchange.isResponseCompleted());
assertFalse(exchange.isFailed());
assertFalse(exchange.isAssociated());
}
/* ------------------------------------------------------------ */
@Test
public void testHttpExchangeCancelOnSend2() throws Exception
{
// One of the first things that HttpClient.send() does
// is to change the status of the exchange
// We exploit that to be sure the exchange is canceled
// without race conditions
TestHttpExchange exchange = new TestHttpExchange()
{
@Override
boolean setStatus(int status)
{
// Cancel after setting the new status
int oldStatus = getStatus();
boolean set = super.setStatus(status);
if (oldStatus == STATUS_START &&
getStatus() == HttpExchange.STATUS_WAITING_FOR_CONNECTION)
cancel();
return set;
}
};
exchange.setAddress(newAddress());
exchange.setRequestURI("/");
getHttpClient().send(exchange);
// Cancelling here is wrong and makes the test fail spuriously
// due to a race condition with send(): the send() can complete
// before the exchange is canceled so it will be in STATUS_COMPLETE
// which will fail the test.
// exchange.cancel();
int status = exchange.waitForDone();
assertEquals(HttpExchange.STATUS_CANCELLED, status);
assertFalse(exchange.isResponseCompleted());
assertFalse(exchange.isFailed());
assertFalse(exchange.isAssociated());
}
/* ------------------------------------------------------------ */
@Test
public void testHttpExchangeCancelOnRequestCommitted() throws Exception
{
TestHttpExchange exchange = new TestHttpExchange()
{
@Override
protected void onRequestCommitted() throws IOException
{
super.onRequestCommitted();
cancel();
}
};
exchange.setAddress(newAddress());
exchange.setRequestURI("/");
getHttpClient().send(exchange);
int status = exchange.waitForDone();
assertEquals(HttpExchange.STATUS_CANCELLED, status);
assertFalse(exchange.isResponseCompleted());
assertFalse(exchange.isFailed());
assertFalse(exchange.isAssociated());
}
/* ------------------------------------------------------------ */
@Test
public void testHttpExchangeCancelOnRequestComplete() throws Exception
{
TestHttpExchange exchange = new TestHttpExchange()
{
@Override
protected void onRequestComplete() throws IOException
{
super.onRequestComplete();
cancel();
}
};
exchange.setAddress(newAddress());
exchange.setRequestURI("/");
getHttpClient().send(exchange);
int status = exchange.waitForDone();
assertThat("Exchange Status", status, is(HttpExchange.STATUS_CANCELLED));
assertThat("Exchange.isResponseCompleted", exchange.isResponseCompleted(), is(false));
assertThat("Exchange.isFailed", exchange.isFailed(), is(false));
assertThat("Exchange.isAssociated", exchange.isAssociated(), is(false));
}
/* ------------------------------------------------------------ */
@Test
public void testHttpExchangeCancelOnResponseStatus() throws Exception
{
TestHttpExchange exchange = new TestHttpExchange()
{
@Override
protected void onResponseStatus(ByteBuffer version, int status, ByteBuffer reason) throws IOException
{
super.onResponseStatus(version, status, reason);
cancel();
}
};
exchange.setAddress(newAddress());
exchange.setRequestURI("/");
getHttpClient().send(exchange);
int status = exchange.waitForDone();
assertEquals(HttpExchange.STATUS_CANCELLED, status);
assertFalse(exchange.isResponseCompleted());
assertFalse(exchange.isFailed());
assertFalse(exchange.isAssociated());
}
/* ------------------------------------------------------------ */
@Test
public void testHttpExchangeCancelOnResponseHeader() throws Exception
{
TestHttpExchange exchange = new TestHttpExchange()
{
@Override
protected void onResponseHeader(ByteBuffer name, ByteBuffer value) throws IOException
{
super.onResponseHeader(name, value);
cancel();
}
};
exchange.setAddress(newAddress());
exchange.setRequestURI("/");
getHttpClient().send(exchange);
int status = exchange.waitForDone();
assertEquals(HttpExchange.STATUS_CANCELLED, status);
assertFalse(exchange.isResponseCompleted());
assertFalse(exchange.isFailed());
assertFalse(exchange.isAssociated());
}
/* ------------------------------------------------------------ */
@Test
public void testHttpExchangeCancelOnResponseHeadersComplete() throws Exception
{
TestHttpExchange exchange = new TestHttpExchange()
{
@Override
protected void onResponseHeaderComplete() throws IOException
{
super.onResponseHeaderComplete();
cancel();
}
};
exchange.setAddress(newAddress());
exchange.setRequestURI("/");
getHttpClient().send(exchange);
int status = exchange.waitForDone();
assertEquals(HttpExchange.STATUS_CANCELLED, status);
assertFalse(exchange.isResponseCompleted());
assertFalse(exchange.isFailed());
assertFalse(exchange.isAssociated());
}
/* ------------------------------------------------------------ */
@Test
public void testHttpExchangeCancelOnResponseContent() throws Exception
{
TestHttpExchange exchange = new TestHttpExchange()
{
@Override
protected void onResponseContent(ByteBuffer content) throws IOException
{
super.onResponseContent(content);
cancel();
}
};
exchange.setAddress(newAddress());
exchange.setRequestURI("/?action=body");
getHttpClient().send(exchange);
int status = exchange.waitForDone();
assertEquals(HttpExchange.STATUS_CANCELLED, status);
assertFalse(exchange.isResponseCompleted());
assertFalse(exchange.isFailed());
assertFalse(exchange.isAssociated());
}
/* ------------------------------------------------------------ */
@Test
public void testHttpExchangeCancelOnResponseComplete() throws Exception
{
TestHttpExchange exchange = new TestHttpExchange()
{
@Override
protected void onResponseComplete() throws IOException
{
super.onResponseComplete();
cancel();
}
};
exchange.setAddress(newAddress());
exchange.setRequestURI("/");
getHttpClient().send(exchange);
int status = exchange.waitForDone();
assertTrue(exchange.isResponseCompleted());
assertFalse(exchange.isFailed());
assertFalse(exchange.isAssociated());
assertEquals(HttpExchange.STATUS_COMPLETED, status);
}
/* ------------------------------------------------------------ */
@Test
public void testHttpExchangeOnServerException() throws Exception
{
try
{
((StdErrLog)Log.getLogger(AbstractHttpConnection.class)).setHideStacks(true);
TestHttpExchange exchange = new TestHttpExchange();
exchange.setAddress(newAddress());
exchange.setRequestURI("/?action=throw");
getHttpClient().send(exchange);
int status = exchange.waitForDone();
assertEquals(HttpExchange.STATUS_COMPLETED, status);
assertTrue(exchange.isResponseCompleted());
assertFalse(exchange.isFailed());
assertFalse(exchange.isAssociated());
}
finally
{
((StdErrLog)Log.getLogger(AbstractHttpConnection.class)).setHideStacks(false);
}
}
/* ------------------------------------------------------------ */
@Test
public void testHttpExchangeOnExpire() throws Exception
{
HttpClient httpClient = getHttpClient();
httpClient.stop();
httpClient.setTimeout(1000);
httpClient.start();
TestHttpExchange exchange = new TestHttpExchange();
exchange.setAddress(newAddress());
exchange.setRequestURI("/?action=wait5000");
long start = System.currentTimeMillis();
httpClient.send(exchange);
int status = exchange.waitForDone();
long end = System.currentTimeMillis();
assertTrue(HttpExchange.STATUS_EXPIRED==status||HttpExchange.STATUS_EXCEPTED==status);
assertFalse(exchange.isResponseCompleted());
assertTrue(end-start<4000);
assertTrue(exchange.isExpired());
assertFalse(exchange.isFailed());
assertFalse(exchange.isAssociated());
}
@Test
public void testHttpExchangeCancelReturnsConnection() throws Exception
{
TestHttpExchange exchange = new TestHttpExchange();
Address address = newAddress();
exchange.setAddress(address);
long delay = 5000;
exchange.setRequestURI("/?action=wait" + delay);
HttpClient httpClient = getHttpClient();
HttpDestination destination = httpClient.getDestination(address, false);
int connections = destination.getConnections();
httpClient.send(exchange);
Thread.sleep(delay / 2);
Assert.assertEquals(connections + 1, destination.getConnections());
exchange.cancel();
Assert.assertEquals(connections, destination.getConnections());
}
/* ------------------------------------------------------------ */
protected abstract HttpClient getHttpClient();
/* ------------------------------------------------------------ */
protected Address newAddress()
{
return new Address("localhost", connector.getLocalPort());
}
/* ------------------------------------------------------------ */
private static class EmptyHandler extends AbstractHandler
{
/* ------------------------------------------------------------ */
public void handle(String path, Request request, HttpServletRequest httpRequest, HttpServletResponse httpResponse) throws IOException, ServletException
{
request.setHandled(true);
String action = httpRequest.getParameter("action");
if (action != null)
{
if ("body".equals(action))
{
ServletOutputStream output = httpResponse.getOutputStream();
output.write("body".getBytes("UTF-8"));
// output.flush();
}
else if ("throw".equals(action))
{
throw new ServletException();
}
else if (action.startsWith("wait"))
{
long sleep = Long.valueOf(action.substring("wait".length()));
long start=System.currentTimeMillis();
try
{
Thread.sleep(sleep);
long end=System.currentTimeMillis();
assertTrue("Duration "+(end-start)+" >~ "+sleep,(end-start)>sleep-100);
}
catch (InterruptedException x)
{
Thread.currentThread().interrupt();
}
}
}
}
}
/* ------------------------------------------------------------ */
protected static class TestHttpExchange extends ContentExchange
{
private boolean responseCompleted;
private boolean failed = false;
private boolean expired = false;
/* ------------------------------------------------------------ */
protected TestHttpExchange()
{
super(true);
}
/* ------------------------------------------------------------ */
@Override
protected synchronized void onResponseComplete() throws IOException
{
this.responseCompleted = true;
}
/* ------------------------------------------------------------ */
public synchronized boolean isResponseCompleted()
{
return responseCompleted;
}
/* ------------------------------------------------------------ */
@Override
protected synchronized void onException(Throwable ex)
{
LOG.debug(ex);
if (ex instanceof SocketTimeoutException ||
ex.getCause() instanceof SocketTimeoutException)
expired=true;
else
failed = true;
}
/* ------------------------------------------------------------ */
public synchronized boolean isFailed()
{
return failed;
}
/* ------------------------------------------------------------ */
@Override
protected synchronized void onExpire()
{
this.expired = true;
}
/* ------------------------------------------------------------ */
public synchronized boolean isExpired()
{
return expired;
}
}
}

View File

@ -1,110 +0,0 @@
//
// ========================================================================
// Copyright (c) 1995-2012 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
//
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
//
package org.eclipse.jetty.client;
import static org.junit.Assert.assertNull;
import java.io.IOException;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;
import org.junit.Test;
/* ------------------------------------------------------------ */
/**
* @version $Revision$ $Date$
*/
public class AsyncCallbackHttpExchangeTest
{
/* ------------------------------------------------------------ */
/**
* If the HttpExchange callbacks are called holding the lock on HttpExchange,
* it will be impossible for the callback to perform some work asynchronously
* and contemporarly accessing the HttpExchange instance synchronized state.
* This test verifies that this situation does not happen.
*
* @throws Exception if the test fails
*/
@Test
public void testAsyncCallback() throws Exception
{
ExecutorService executor = Executors.newCachedThreadPool();
try
{
AtomicReference<Exception> failure = new AtomicReference<Exception>();
TestHttpExchange exchange = new TestHttpExchange(executor, failure);
exchange.setStatus(HttpExchange.STATUS_WAITING_FOR_COMMIT);
exchange.setStatus(HttpExchange.STATUS_SENDING_REQUEST);
// This status change triggers onRequestCommitted()
exchange.setStatus(HttpExchange.STATUS_WAITING_FOR_RESPONSE);
assertNull(failure.get());
}
finally
{
executor.shutdown();
}
}
/* ------------------------------------------------------------ */
private class TestHttpExchange extends HttpExchange
{
private final ExecutorService executor;
private final AtomicReference<Exception> failure;
/* ------------------------------------------------------------ */
private TestHttpExchange(ExecutorService executor, AtomicReference<Exception> failure)
{
this.executor = executor;
this.failure = failure;
}
/* ------------------------------------------------------------ */
@Override
protected void onRequestCommitted() throws IOException
{
Future<Integer> future = executor.submit(new Callable<Integer>()
{
/* ------------------------------------------------------------ */
public Integer call() throws Exception
{
// Method getStatus() reads synchronized state
return TestHttpExchange.this.getStatus();
}
});
// We're waiting for the future to complete, thus never exiting
// this method; if this method is called with the lock held,
// this method never completes
try
{
future.get(1000, TimeUnit.MILLISECONDS);
// Test green here
}
catch (Exception x)
{
// Timed out, the test did not pass
failure.set(x);
}
}
}
}

View File

@ -1,73 +0,0 @@
//
// ========================================================================
// Copyright (c) 1995-2012 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
//
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
//
package org.eclipse.jetty.client;
import java.io.IOException;
import java.net.ServerSocket;
import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
import org.eclipse.jetty.util.ssl.SslContextFactory;
import org.junit.BeforeClass;
public class AsyncSelectConnectionTest extends AbstractConnectionTest
{
protected HttpClient newHttpClient()
{
HttpClient httpClient = new HttpClient();
httpClient.setConnectorType(HttpClient.CONNECTOR_SELECT_CHANNEL);
httpClient.setConnectBlocking(false);
return httpClient;
}
static SslContextFactory ctx = new SslContextFactory(MavenTestingUtils.getTestResourceFile("keystore").getAbsolutePath());
@BeforeClass
public static void initKS() throws Exception
{
ctx.setKeyStorePassword("storepwd");
ctx.setKeyManagerPassword("keypwd");
ctx.start();
}
@Override
protected String getScheme()
{
return "https";
}
@Override
protected ServerSocket newServerSocket() throws IOException
{
return ctx.newSslServerSocket(null,0,100);
}
@Override
public void testServerHalfClosedIncomplete() throws Exception
{
// SSL doesn't do half closes
}
@Override
public void testServerClosedIncomplete() throws Exception
{
super.testServerClosedIncomplete();
}
}

View File

@ -1,53 +0,0 @@
//
// ========================================================================
// Copyright (c) 1995-2012 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
//
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
//
package org.eclipse.jetty.client;
import org.eclipse.jetty.client.helperClasses.AsyncSslServerAndClientCreator;
import org.eclipse.jetty.client.helperClasses.ServerAndClientCreator;
import org.junit.Before;
import org.junit.Test;
public class AsyncSslHttpExchangeTest extends SslHttpExchangeTest
{
private static ServerAndClientCreator serverAndClientCreator = new AsyncSslServerAndClientCreator();
@Before
public void setUpOnce() throws Exception
{
_scheme="https";
_server = serverAndClientCreator.createServer();
_httpClient = serverAndClientCreator.createClient(3000L,3500L,2000);
_port = _server.getConnectors()[0].getLocalPort();
}
@Test
public void testPerf1() throws Exception
{
sender(1,true);
}
@Override
public void testBigPostWithContentExchange() throws Exception
{
super.testBigPostWithContentExchange();
}
}

View File

@ -1,60 +0,0 @@
//
// ========================================================================
// Copyright (c) 1995-2012 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
//
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
//
package org.eclipse.jetty.client;
import org.junit.After;
import org.junit.Before;
/* ------------------------------------------------------------ */
/**
* @version $Revision$ $Date$
*/
public class BlockingHttpExchangeCancelTest extends AbstractHttpExchangeCancelTest
{
private HttpClient httpClient;
/* ------------------------------------------------------------ */
@Before
@Override
public void setUp() throws Exception
{
super.setUp();
httpClient = new HttpClient();
httpClient.setConnectorType(HttpClient.CONNECTOR_SOCKET);
httpClient.start();
}
/* ------------------------------------------------------------ */
@After
@Override
public void tearDown() throws Exception
{
httpClient.stop();
super.tearDown();
}
/* ------------------------------------------------------------ */
@Override
protected HttpClient getHttpClient()
{
return httpClient;
}
}

View File

@ -1,140 +0,0 @@
//
// ========================================================================
// Copyright (c) 1995-2012 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
//
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
//
package org.eclipse.jetty.client;
import static org.junit.Assert.assertEquals;
import java.io.IOException;
import java.util.Enumeration;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.http.HttpStatus;
import org.eclipse.jetty.server.Connector;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.handler.AbstractHandler;
import org.eclipse.jetty.server.nio.SelectChannelConnector;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
/* ------------------------------------------------------------ */
public class CachedHeadersIsolationTest
{
Server server;
HttpClient client;
int port;
@Before
public void setUp() throws Exception
{
server = new Server();
Connector connector = new SelectChannelConnector();
server.addConnector(connector);
server.setHandler(new AbstractHandler()
{
/* ------------------------------------------------------------ */
public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException,
ServletException
{
response.setStatus(HttpStatus.OK_200);
response.addHeader("For",request.getQueryString());
response.addHeader("Name","Value");
response.getOutputStream().print("blah");
response.flushBuffer();
}
});
server.start();
port = server.getConnectors()[0].getLocalPort();
client = new HttpClient();
client.setConnectorType(HttpClient.CONNECTOR_SELECT_CHANNEL);
client.setConnectTimeout(5);
client.start();
}
/* ------------------------------------------------------------ */
@After
public void tearDown() throws Exception
{
server.stop();
client.stop();
}
/* ------------------------------------------------------------ */
@Test
public void testHeaderWhenReadEarly() throws Exception
{
CachedExchange e1 = new CachedExchange(true);
CachedExchange e2 = new CachedExchange(true);
e1.setURL("http://localhost:" + port + "/?a=short");
e2.setURL("http://localhost:" + port + "/?a=something_longer");
client.send(e1);
while (!e1.isDone())
Thread.sleep(100);
assertEquals("Read buffer","Value",e1.getResponseFields().getStringField("Name"));
client.send(e2);
while (!e2.isDone())
Thread.sleep(100);
assertEquals("Overwritten buffer","Value",e1.getResponseFields().getStringField("Name"));
}
/* ------------------------------------------------------------ */
@Test
public void testHeaderWhenReadLate() throws Exception
{
CachedExchange e1 = new CachedExchange(true);
CachedExchange e2 = new CachedExchange(true);
e1.setURL("http://localhost:" + port + "/?a=short");
e2.setURL("http://localhost:" + port + "/?a=something_longer");
client.send(e1);
while (!e1.isDone())
Thread.sleep(100);
client.send(e2);
while (!e2.isDone())
Thread.sleep(100);
for ( Enumeration<String> e = e1.getResponseFields().getValues("Name"); e.hasMoreElements();)
{
System.out.println(e.nextElement());
}
assertEquals("Overwritten buffer","Value",e1.getResponseFields().getStringField("Name"));
}
}

View File

@ -1,389 +0,0 @@
//
// ========================================================================
// Copyright (c) 1995-2012 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
//
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
//
package org.eclipse.jetty.client;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URLDecoder;
import javax.servlet.ServletException;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.client.security.Realm;
import org.eclipse.jetty.client.security.SimpleRealmResolver;
import org.eclipse.jetty.http.HttpMethod;
import org.eclipse.jetty.http.HttpStatus;
import org.eclipse.jetty.io.ByteArrayBuffer;
import org.eclipse.jetty.io.EofException;
import org.eclipse.jetty.server.Handler;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.handler.AbstractHandler;
import org.eclipse.jetty.server.handler.HandlerCollection;
import org.eclipse.jetty.server.nio.SelectChannelConnector;
import org.eclipse.jetty.servlet.DefaultServlet;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;
import org.eclipse.jetty.util.IO;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
public class ContentExchangeTest
{
private static String _content =
"Lorem ipsum dolor sit amet, consectetur adipiscing elit. In quis felis nunc. "+
"Quisque suscipit mauris et ante auctor ornare rhoncus lacus aliquet. Pellentesque "+
"habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. "+
"Vestibulum sit amet felis augue, vel convallis dolor. Cras accumsan vehicula diam "+
"at faucibus. Etiam in urna turpis, sed congue mi. Morbi et lorem eros. Donec vulputate "+
"velit in risus suscipit lobortis. Aliquam id urna orci, nec sollicitudin ipsum. "+
"Cras a orci turpis. Donec suscipit vulputate cursus. Mauris nunc tellus, fermentum "+
"eu auctor ut, mollis at diam. Quisque porttitor ultrices metus, vitae tincidunt massa "+
"sollicitudin a. Vivamus porttitor libero eget purus hendrerit cursus. Integer aliquam "+
"consequat mauris quis luctus. Cras enim nibh, dignissim eu faucibus ac, mollis nec neque. "+
"Aliquam purus mauris, consectetur nec convallis lacinia, porta sed ante. Suspendisse "+
"et cursus magna. Donec orci enim, molestie a lobortis eu, imperdiet vitae neque.";
private File _docRoot;
private Server _server;
private HttpClient _client;
private Realm _realm;
private String _protocol;
private String _baseUrl;
private String _requestContent;
/* ------------------------------------------------------------ */
@Before
public void setUp()
throws Exception
{
_docRoot = new File("target/test-output/docroot/");
_docRoot.mkdirs();
_docRoot.deleteOnExit();
File content = new File(_docRoot,"input.txt");
FileOutputStream out = new FileOutputStream(content);
out.write(_content.getBytes("utf-8"));
out.close();
_server = new Server();
configureServer(_server);
_server.start();
int port = _server.getConnectors()[0].getLocalPort();
_baseUrl = _protocol+"://localhost:"+port+ "/";
}
/* ------------------------------------------------------------ */
@After
public void tearDown()
throws Exception
{
if (_server != null)
{
_server.stop();
_server = null;
}
}
/* ------------------------------------------------------------ */
@Test
public void testPut() throws Exception
{
startClient(_realm);
ContentExchange putExchange = new ContentExchange();
putExchange.setURL(getBaseUrl() + "output.txt");
putExchange.setMethod(HttpMethod.PUT);
putExchange.setRequestContent(new ByteArrayBuffer(_content.getBytes()));
_client.send(putExchange);
int state = putExchange.waitForDone();
int responseStatus = putExchange.getResponseStatus();
stopClient();
boolean statusOk = (responseStatus == 200 || responseStatus == 201);
assertTrue(statusOk);
String content = IO.toString(new FileInputStream(new File(_docRoot,"output.txt")));
assertEquals(_content,content);
}
/* ------------------------------------------------------------ */
@Test
public void testGet() throws Exception
{
startClient(_realm);
ContentExchange getExchange = new ContentExchange();
getExchange.setURL(getBaseUrl() + "input.txt");
getExchange.setMethod(HttpMethod.GET);
_client.send(getExchange);
int state = getExchange.waitForDone();
String content = "";
int responseStatus = getExchange.getResponseStatus();
if (responseStatus == HttpStatus.OK_200)
{
content = getExchange.getResponseContent();
}
stopClient();
assertEquals(HttpStatus.OK_200,responseStatus);
assertEquals(_content,content);
}
/* ------------------------------------------------------------ */
@Test
public void testHead() throws Exception
{
startClient(_realm);
ContentExchange getExchange = new ContentExchange();
getExchange.setURL(getBaseUrl() + "input.txt");
getExchange.setMethod(HttpMethod.HEAD);
_client.send(getExchange);
getExchange.waitForDone();
int responseStatus = getExchange.getResponseStatus();
stopClient();
assertEquals(HttpStatus.OK_200,responseStatus);
}
/* ------------------------------------------------------------ */
@Test
public void testPost() throws Exception
{
startClient(_realm);
ContentExchange postExchange = new ContentExchange();
postExchange.setURL(getBaseUrl() + "test");
postExchange.setMethod(HttpMethod.POST);
postExchange.setRequestContent(new ByteArrayBuffer(_content.getBytes()));
_client.send(postExchange);
int state = postExchange.waitForDone();
int responseStatus = postExchange.getResponseStatus();
stopClient();
assertEquals(HttpStatus.OK_200,responseStatus);
assertEquals(_content,_requestContent);
}
/* ------------------------------------------------------------ */
protected void configureServer(Server server)
throws Exception
{
setProtocol("http");
SelectChannelConnector connector = new SelectChannelConnector();
server.addConnector(connector);
Handler handler = new TestHandler(getBasePath());
ServletContextHandler root = new ServletContextHandler();
root.setContextPath("/");
root.setResourceBase(_docRoot.getAbsolutePath());
ServletHolder servletHolder = new ServletHolder( new DefaultServlet() );
servletHolder.setInitParameter( "gzip", "true" );
root.addServlet( servletHolder, "/*" );
HandlerCollection handlers = new HandlerCollection();
handlers.setHandlers(new Handler[]{handler, root});
server.setHandler( handlers );
}
/* ------------------------------------------------------------ */
protected void startClient(Realm realm)
throws Exception
{
_client = new HttpClient();
configureClient(_client);
if (realm != null)
_client.setRealmResolver(new SimpleRealmResolver(realm));
_client.start();
}
/* ------------------------------------------------------------ */
protected void configureClient(HttpClient client)
throws Exception
{
client.setConnectorType(HttpClient.CONNECTOR_SELECT_CHANNEL);
}
/* ------------------------------------------------------------ */
protected void stopClient()
throws Exception
{
if (_client != null)
{
_client.stop();
_client = null;
}
}
/* ------------------------------------------------------------ */
protected String getBasePath()
{
return _docRoot.getAbsolutePath();
}
/* ------------------------------------------------------------ */
protected String getBaseUrl()
{
return _baseUrl;
}
/* ------------------------------------------------------------ */
protected HttpClient getClient()
{
return _client;
}
/* ------------------------------------------------------------ */
protected Realm getRealm()
{
return _realm;
}
/* ------------------------------------------------------------ */
protected String getContent()
{
return _content;
}
/* ------------------------------------------------------------ */
protected void setProtocol(String protocol)
{
_protocol = protocol;
}
/* ------------------------------------------------------------ */
protected void setRealm(Realm realm)
{
_realm = realm;
}
/* ------------------------------------------------------------ */
public static void copyStream(InputStream in, OutputStream out)
{
try
{
byte[] buffer=new byte[1024];
int len;
while ((len=in.read(buffer))>=0)
{
out.write(buffer,0,len);
}
}
catch (EofException e)
{
System.err.println(e);
}
catch (IOException e)
{
e.printStackTrace();
}
}
/* ------------------------------------------------------------ */
protected class TestHandler extends AbstractHandler {
private final String resourcePath;
/* ------------------------------------------------------------ */
public TestHandler(String repositoryPath) {
this.resourcePath = repositoryPath;
}
/* ------------------------------------------------------------ */
public void handle(String target, Request baseRequest,
HttpServletRequest request, HttpServletResponse response)
throws IOException, ServletException
{
if (baseRequest.isHandled())
{
return;
}
OutputStream out = null;
if (baseRequest.getMethod().equals("PUT"))
{
baseRequest.setHandled(true);
File file = new File(resourcePath, URLDecoder.decode(request.getPathInfo()));
file.getParentFile().mkdirs();
file.deleteOnExit();
out = new FileOutputStream(file);
response.setStatus(HttpServletResponse.SC_CREATED);
}
if (baseRequest.getMethod().equals("POST"))
{
baseRequest.setHandled(true);
out = new ByteArrayOutputStream();
response.setStatus(HttpServletResponse.SC_OK);
}
if (out != null)
{
ServletInputStream in = request.getInputStream();
try
{
copyStream( in, out );
}
finally
{
in.close();
out.close();
}
if (!(out instanceof FileOutputStream))
_requestContent = out.toString();
}
}
}
}

View File

@ -1,200 +0,0 @@
//
// ========================================================================
// Copyright (c) 1995-2012 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
//
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
//
package org.eclipse.jetty.client;
import java.io.IOException;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicBoolean;
import org.eclipse.jetty.http.HttpMethod;
/* ------------------------------------------------------------ */
/** A simple test http client like curl.
* <p>
* Usage is java -cp $CLASSPATH org.eclipse.jetty.client.Curl [ option | URL ] ...
* Options supported are: <ul>
* <li>--async : The following URLs are fetched in parallel (default)
* <li>--sync : The following URLs are fetched in sequence
* <li>--dump : The content is dumped to stdout
* <li>--nodump : The content is suppressed (default)
* </ul>
*/
public class Curl
{
public static void main(String[] args)
throws Exception
{
if (args.length==0)
args=new String[]
{ "--sync", "http://www.sun.com/robots.txt", "http://www.sun.com/favicon.ico" , "--dump", "http://www.sun.com/robots.txt"};
HttpClient client = new HttpClient();
client.setIdleTimeout(2000);
client.start();
boolean async=true;
boolean dump= false;
boolean verbose= false;
int urls=0;
for (String arg : args)
{
if (!arg.startsWith("-"))
urls++;
}
final CountDownLatch latch = new CountDownLatch(urls);
for (String arg : args)
{
if ("--verbose".equals(arg))
{
verbose=true;
continue;
}
if ("--sync".equals(arg))
{
async=false;
continue;
}
if ("--async".equals(arg))
{
async=true;
continue;
}
if ("--dump".equals(arg))
{
dump=true;
continue;
}
if ("--nodump".equals(arg))
{
dump=false;
continue;
}
final boolean d = dump;
final boolean v = verbose;
HttpExchange ex = new HttpExchange()
{
AtomicBoolean counted=new AtomicBoolean(false);
@Override
protected void onConnectionFailed(Throwable ex)
{
if (!counted.getAndSet(true))
latch.countDown();
super.onConnectionFailed(ex);
}
@Override
protected void onException(Throwable ex)
{
if (!counted.getAndSet(true))
latch.countDown();
super.onException(ex);
}
@Override
protected void onExpire()
{
if (!counted.getAndSet(true))
latch.countDown();
super.onExpire();
}
@Override
protected void onResponseComplete() throws IOException
{
if (!counted.getAndSet(true))
latch.countDown();
super.onResponseComplete();
}
@Override
protected void onResponseContent(ByteBuffer content) throws IOException
{
super.onResponseContent(content);
if (d)
System.out.print(content.toString());
if (v)
System.err.println("got "+content.length());
}
/* ------------------------------------------------------------ */
/**
* @see org.eclipse.jetty.client.HttpExchange#onResponseHeader(org.eclipse.jetty.io.ByteBuffer, org.eclipse.jetty.io.ByteBuffer)
*/
@Override
protected void onResponseHeader(ByteBuffer name, ByteBuffer value) throws IOException
{
super.onResponseHeader(name,value);
if (v)
System.err.println(name+": "+value);
}
/* ------------------------------------------------------------ */
/**
* @see org.eclipse.jetty.client.HttpExchange#onResponseHeaderComplete()
*/
@Override
protected void onResponseHeaderComplete() throws IOException
{
super.onResponseHeaderComplete();
if (v)
System.err.println();
}
/* ------------------------------------------------------------ */
/**
* @see org.eclipse.jetty.client.HttpExchange#onResponseStatus(org.eclipse.jetty.io.ByteBuffer, int, org.eclipse.jetty.io.ByteBuffer)
*/
@Override
protected void onResponseStatus(ByteBuffer version, int status, ByteBuffer reason) throws IOException
{
super.onResponseStatus(version,status,reason);
if (v)
System.err.println(version+" "+status+" "+reason);
}
};
ex.setMethod(HttpMethod.GET);
ex.setURL(arg);
System.err.println("\nSending "+ex);
client.send(ex);
if (!async)
{
System.err.println("waiting...");
ex.waitForDone();
System.err.println("Done");
}
}
latch.await();
}
}

View File

@ -1,276 +0,0 @@
//
// ========================================================================
// Copyright (c) 1995-2012 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
//
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
//
package org.eclipse.jetty.client;
import static org.junit.Assert.assertEquals;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.http.HttpMethod;
import org.eclipse.jetty.http.HttpStatus;
import org.eclipse.jetty.io.ByteArrayBuffer;
import org.eclipse.jetty.server.Handler;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.handler.AbstractHandler;
import org.eclipse.jetty.server.handler.HandlerCollection;
import org.eclipse.jetty.server.nio.SelectChannelConnector;
import org.eclipse.jetty.servlet.DefaultServlet;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;
import org.junit.Test;
/* ------------------------------------------------------------ */
public class ErrorStatusTest
extends ContentExchangeTest
{
/* ------------------------------------------------------------ */
@Test
public void testPutBadRequest()
throws Exception
{
doPutFail(HttpStatus.BAD_REQUEST_400);
}
/* ------------------------------------------------------------ */
@Test
public void testPutUnauthorized()
throws Exception
{
doPutFail(HttpStatus.UNAUTHORIZED_401);
}
/* ------------------------------------------------------------ */
@Test
public void testPutForbidden()
throws Exception
{
doPutFail(HttpStatus.FORBIDDEN_403);
}
/* ------------------------------------------------------------ */
@Test
public void testPutNotFound()
throws Exception
{
doPutFail(HttpStatus.NOT_FOUND_404);
}
/* ------------------------------------------------------------ */
@Test
public void testPutServerError()
throws Exception
{
doPutFail(HttpStatus.INTERNAL_SERVER_ERROR_500);
}
/* ------------------------------------------------------------ */
@Test
public void testGetBadRequest()
throws Exception
{
doGetFail(HttpStatus.BAD_REQUEST_400);
}
/* ------------------------------------------------------------ */
@Test
public void testGetUnauthorized()
throws Exception
{
doGetFail(HttpStatus.UNAUTHORIZED_401);
}
/* ------------------------------------------------------------ */
@Test
public void testGetNotFound()
throws Exception
{
doGetFail(HttpStatus.NOT_FOUND_404);
}
/* ------------------------------------------------------------ */
@Test
public void testGetServerError()
throws Exception
{
doGetFail(HttpStatus.INTERNAL_SERVER_ERROR_500);
}
/* ------------------------------------------------------------ */
@Test
public void testPostBadRequest()
throws Exception
{
doPostFail(HttpStatus.BAD_REQUEST_400);
}
/* ------------------------------------------------------------ */
@Test
public void testPostUnauthorized()
throws Exception
{
doPostFail(HttpStatus.UNAUTHORIZED_401);
}
/* ------------------------------------------------------------ */
@Test
public void testPostForbidden()
throws Exception
{
doPostFail(HttpStatus.FORBIDDEN_403);
}
/* ------------------------------------------------------------ */
@Test
public void testPostNotFound()
throws Exception
{
doPostFail(HttpStatus.NOT_FOUND_404);
}
/* ------------------------------------------------------------ */
@Test
public void testPostServerError()
throws Exception
{
doPostFail(HttpStatus.INTERNAL_SERVER_ERROR_500);
}
/* ------------------------------------------------------------ */
protected void doPutFail(int status)
throws Exception
{
startClient(getRealm());
ContentExchange putExchange = new ContentExchange();
putExchange.setURL(getBaseUrl() + "output.txt");
putExchange.setMethod(HttpMethod.PUT);
putExchange.setRequestHeader("X-Response-Status",Integer.toString(status));
putExchange.setRequestContent(new ByteArrayBuffer(getContent().getBytes()));
getClient().send(putExchange);
int state = putExchange.waitForDone();
int responseStatus = putExchange.getResponseStatus();
stopClient();
assertEquals(status, responseStatus);
}
/* ------------------------------------------------------------ */
protected void doGetFail(int status)
throws Exception
{
startClient(getRealm());
ContentExchange getExchange = new ContentExchange();
getExchange.setURL(getBaseUrl() + "input.txt");
getExchange.setMethod(HttpMethod.GET);
getExchange.setRequestHeader("X-Response-Status",Integer.toString(status));
getClient().send(getExchange);
int state = getExchange.waitForDone();
String content;
int responseStatus = getExchange.getResponseStatus();
if (responseStatus == HttpStatus.OK_200) {
content = getExchange.getResponseContent();
}
stopClient();
assertEquals(status, responseStatus);
}
/* ------------------------------------------------------------ */
protected void doPostFail(int status)
throws Exception
{
startClient(getRealm());
ContentExchange postExchange = new ContentExchange();
postExchange.setURL(getBaseUrl() + "test");
postExchange.setMethod(HttpMethod.POST);
postExchange.setRequestHeader("X-Response-Status",Integer.toString(status));
postExchange.setRequestContent(new ByteArrayBuffer(getContent().getBytes()));
getClient().send(postExchange);
int state = postExchange.waitForDone();
int responseStatus = postExchange.getResponseStatus();
stopClient();
assertEquals(status, responseStatus);
}
/* ------------------------------------------------------------ */
protected void configureServer(Server server)
throws Exception
{
setProtocol("http");
SelectChannelConnector connector = new SelectChannelConnector();
server.addConnector(connector);
ServletContextHandler root = new ServletContextHandler();
root.setContextPath("/");
root.setResourceBase(getBasePath());
ServletHolder servletHolder = new ServletHolder( new DefaultServlet() );
servletHolder.setInitParameter( "gzip", "true" );
root.addServlet( servletHolder, "/*" );
Handler status = new StatusHandler();
Handler test = new TestHandler(getBasePath());
HandlerCollection handlers = new HandlerCollection();
handlers.setHandlers(new Handler[]{status, test, root});
server.setHandler( handlers );
}
/* ------------------------------------------------------------ */
protected static class StatusHandler extends AbstractHandler {
/* ------------------------------------------------------------ */
public void handle(String target, Request baseRequest,
HttpServletRequest request, HttpServletResponse response)
throws IOException, ServletException
{
if (baseRequest.isHandled())
return;
int statusValue = 0;
String statusHeader = request.getHeader("X-Response-Status");
if (statusHeader != null)
{
statusValue = Integer.parseInt(statusHeader);
}
if (statusValue != 0)
{
response.setStatus(statusValue);
baseRequest.setHandled(true);
}
}
}
}

View File

@ -1,197 +0,0 @@
//
// ========================================================================
// Copyright (c) 1995-2012 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
//
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
//
package org.eclipse.jetty.client;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicLong;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.junit.Assert;
import org.junit.Test;
import org.junit.Ignore;
public class ExpirationWithLimitedConnectionsTest
{
@Ignore
public void testExpirationWithMaxConnectionPerAddressReached() throws Exception
{
final Logger logger = Log.getLogger("org.eclipse.jetty.client");
logger.setDebugEnabled(true);
HttpClient client = new HttpClient();
int maxConnectionsPerAddress = 10;
client.setMaxConnectionsPerAddress(maxConnectionsPerAddress);
long timeout = 1000;
client.setTimeout(timeout);
client.start();
final List<Socket> sockets = new CopyOnWriteArrayList<Socket>();
final List<Exception> failures = new CopyOnWriteArrayList<Exception>();
final AtomicLong processingDelay = new AtomicLong(200);
final ExecutorService threadPool = Executors.newCachedThreadPool();
final ServerSocket server = new ServerSocket(0);
threadPool.submit(new Runnable()
{
public void run()
{
while (true)
{
try
{
final Socket socket = server.accept();
sockets.add(socket);
logger.debug("CONNECTION {}", socket.getRemoteSocketAddress());
threadPool.submit(new Runnable()
{
public void run()
{
while (true)
{
try
{
BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream(), "UTF-8"));
String firstLine = reader.readLine();
String line = firstLine;
while (line != null)
{
if (line.length() == 0)
break;
line = reader.readLine();
}
if (line == null)
break;
long sleep = processingDelay.get();
logger.debug("{} {} {} ms", firstLine, socket.getRemoteSocketAddress(), sleep);
TimeUnit.MILLISECONDS.sleep(sleep);
String response = "" +
"HTTP/1.1 200 OK\r\n" +
"Content-Length: 0\r\n" +
"\r\n";
OutputStream output = socket.getOutputStream();
output.write(response.getBytes("UTF-8"));
output.flush();
}
catch (Exception x)
{
failures.add(x);
break;
}
}
}
});
}
catch (Exception x)
{
failures.add(x);
break;
}
}
}
});
List<ContentExchange> exchanges = new ArrayList<ContentExchange>();
final AtomicBoolean firstExpired = new AtomicBoolean();
int count = 0;
int maxAdditionalRequest = 100;
int additionalRequests = 0;
while (true)
{
TimeUnit.MILLISECONDS.sleep(1); // Just avoid being too fast
ContentExchange exchange = new ContentExchange(true)
{
@Override
protected void onResponseComplete() throws IOException
{
logger.debug("{} {} OK", getMethod(), getRequestURI());
}
@Override
protected void onExpire()
{
logger.debug("{} {} EXPIRED {}", getMethod(), getRequestURI(), this);
firstExpired.compareAndSet(false, true);
}
};
exchanges.add(exchange);
Address address = new Address("localhost", server.getLocalPort());
exchange.setAddress(address);
exchange.setMethod("GET");
exchange.setRequestURI("/" + count);
exchange.setVersion("HTTP/1.1");
exchange.setRequestHeader("Host", address.toString());
logger.debug("{} {} SENT", exchange.getMethod(), exchange.getRequestURI());
client.send(exchange);
++count;
if (processingDelay.get() > 0)
{
if (client.getDestination(address, false).getConnections() == maxConnectionsPerAddress)
{
if (firstExpired.get())
{
++additionalRequests;
if (additionalRequests == maxAdditionalRequest)
processingDelay.set(0);
}
}
}
else
{
++additionalRequests;
if (additionalRequests == 2 * maxAdditionalRequest)
break;
}
}
for (ContentExchange exchange : exchanges)
{
int status = exchange.waitForDone();
Assert.assertTrue(status == HttpExchange.STATUS_COMPLETED || status == HttpExchange.STATUS_EXPIRED);
}
client.stop();
Assert.assertTrue(failures.isEmpty());
for (Socket socket : sockets)
socket.close();
server.close();
threadPool.shutdown();
threadPool.awaitTermination(5, TimeUnit.SECONDS);
}
}

View File

@ -1,117 +0,0 @@
//
// ========================================================================
// Copyright (c) 1995-2012 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
//
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
//
package org.eclipse.jetty.client;
import static org.junit.Assert.assertTrue;
import java.io.IOException;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.handler.AbstractHandler;
import org.eclipse.jetty.server.nio.SelectChannelConnector;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
/**
* Test contributed by: Michiel Thuys for JETTY-806
*/
public class ExpireTest
{
private Server server;
private HttpClient client;
private int port;
@Before
public void init() throws Exception
{
server = new Server();
SelectChannelConnector connector = new SelectChannelConnector();
connector.setHost("localhost");
connector.setPort(0);
server.addConnector(connector);
server.setHandler(new AbstractHandler()
{
public void handle(String target, Request request, HttpServletRequest httpRequest, HttpServletResponse httpResponse)
throws IOException, ServletException
{
request.setHandled(true);
try
{
Thread.sleep(2000);
}
catch (InterruptedException x)
{
}
}
});
server.start();
port = connector.getLocalPort();
client = new HttpClient();
client.setConnectorType(HttpClient.CONNECTOR_SELECT_CHANNEL);
client.setTimeout(200);
client.setMaxRetries(0);
client.setMaxConnectionsPerAddress(100);
client.start();
}
@After
public void destroy() throws Exception
{
client.stop();
server.stop();
server.join();
}
@Test
public void testExpire() throws Exception
{
String baseUrl = "http://" + "localhost" + ":" + port + "/";
int count = 200;
final CountDownLatch expires = new CountDownLatch(count);
for (int i=0;i<count;i++)
{
final ContentExchange exchange = new ContentExchange()
{
@Override
protected void onExpire()
{
expires.countDown();
}
};
exchange.setMethod("GET");
exchange.setURL(baseUrl);
client.send(exchange);
}
// Wait to be sure that all exchanges have expired
assertTrue(expires.await(5, TimeUnit.SECONDS));
}
}

View File

@ -1,37 +0,0 @@
//
// ========================================================================
// Copyright (c) 1995-2012 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
//
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
//
package org.eclipse.jetty.client;
import org.eclipse.jetty.client.helperClasses.ExternalKeyStoreAsyncSslServerAndClientCreator;
import org.eclipse.jetty.client.helperClasses.ServerAndClientCreator;
import org.junit.Before;
public class ExternalKeyStoreAsyncSslHttpExchangeTest extends SslHttpExchangeTest
{
private static ServerAndClientCreator serverAndClientCreator = new ExternalKeyStoreAsyncSslServerAndClientCreator();
@Before
public void setUpOnce() throws Exception
{
_scheme="https";
_server = serverAndClientCreator.createServer();
_httpClient = serverAndClientCreator.createClient(3000L,3500L,2000);
_port = _server.getConnectors()[0].getLocalPort();
}
}

View File

@ -1,245 +0,0 @@
//
// ========================================================================
// Copyright (c) 1995-2012 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
//
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
//
package org.eclipse.jetty.client;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import java.io.File;
import java.io.IOException;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.http.HttpMethod;
import org.eclipse.jetty.http.HttpStatus;
import org.eclipse.jetty.server.Connector;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.handler.AbstractHandler;
import org.eclipse.jetty.server.nio.SelectChannelConnector;
import org.eclipse.jetty.util.log.Log;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
/* ------------------------------------------------------------ */
public class Http100ContinueTest
{
private static final int TIMEOUT = 500;
private static final String CONTENT = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. In quis felis nunc. "
+ "Quisque suscipit mauris et ante auctor ornare rhoncus lacus aliquet. Pellentesque "
+ "habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. "
+ "Vestibulum sit amet felis augue, vel convallis dolor. Cras accumsan vehicula diam "
+ "at faucibus. Etiam in urna turpis, sed congue mi. Morbi et lorem eros. Donec vulputate "
+ "velit in risus suscipit lobortis. Aliquam id urna orci, nec sollicitudin ipsum. "
+ "Cras a orci turpis. Donec suscipit vulputate cursus. Mauris nunc tellus, fermentum "
+ "eu auctor ut, mollis at diam. Quisque porttitor ultrices metus, vitae tincidunt massa "
+ "sollicitudin a. Vivamus porttitor libero eget purus hendrerit cursus. Integer aliquam "
+ "consequat mauris quis luctus. Cras enim nibh, dignissim eu faucibus ac, mollis nec neque. "
+ "Aliquam purus mauris, consectetur nec convallis lacinia, porta sed ante. Suspendisse "
+ "et cursus magna. Donec orci enim, molestie a lobortis eu, imperdiet vitae neque.";
private static TestFeature _feature;
private static Server _server;
private static TestHandler _handler;
private static HttpClient _client;
private static String _requestUrl;
@BeforeClass
public static void init() throws Exception
{
File docRoot = new File("target/test-output/docroot/");
if (!docRoot.exists())
assertTrue(docRoot.mkdirs());
docRoot.deleteOnExit();
_server = new Server();
Connector connector = new SelectChannelConnector();
_server.addConnector(connector);
_handler = new TestHandler();
_server.setHandler(_handler);
_server.start();
_client = new HttpClient();
_client.setConnectorType(HttpClient.CONNECTOR_SELECT_CHANNEL);
_client.setTimeout(TIMEOUT);
_client.setMaxRetries(0);
_client.start();
_requestUrl = "http://localhost:" + connector.getLocalPort() + "/";
}
@AfterClass
public static void destroy() throws Exception
{
_client.stop();
_server.stop();
_server.join();
}
@Test
public void testSuccess() throws Exception
{
// Handler to send CONTINUE 100
_feature = TestFeature.CONTINUE;
ContentExchange exchange = sendExchange();
int state = exchange.waitForDone();
assertEquals(HttpExchange.STATUS_COMPLETED, state);
int responseStatus = exchange.getResponseStatus();
assertEquals(HttpStatus.OK_200,responseStatus);
String content = exchange.getResponseContent();
assertEquals(Http100ContinueTest.CONTENT,content);
}
@Test
public void testMissingContinue() throws Exception
{
// Handler does not send CONTINUE 100
_feature = TestFeature.NORMAL;
ContentExchange exchange = sendExchange();
int state = exchange.waitForDone();
assertEquals(HttpExchange.STATUS_COMPLETED, state);
int responseStatus = exchange.getResponseStatus();
assertEquals(HttpStatus.OK_200,responseStatus);
String content = exchange.getResponseContent();
assertEquals(Http100ContinueTest.CONTENT,content);
}
@Test
public void testError() throws Exception
{
// Handler sends NOT FOUND 404 response
_feature = TestFeature.NOTFOUND;
ContentExchange exchange = sendExchange();
int state = exchange.waitForDone();
assertEquals(HttpExchange.STATUS_COMPLETED, state);
int responseStatus = exchange.getResponseStatus();
assertEquals(HttpStatus.NOT_FOUND_404,responseStatus);
}
@Test
public void testTimeout() throws Exception
{
// Handler delays response till client times out
_feature = TestFeature.TIMEOUT;
final CountDownLatch expires = new CountDownLatch(1);
ContentExchange exchange = new ContentExchange()
{
@Override
protected void onExpire()
{
expires.countDown();
}
};
configureExchange(exchange);
_client.send(exchange);
assertTrue(expires.await(TIMEOUT*10,TimeUnit.MILLISECONDS));
}
public ContentExchange sendExchange() throws Exception
{
ContentExchange exchange = new ContentExchange();
configureExchange(exchange);
_client.send(exchange);
return exchange;
}
public void configureExchange(ContentExchange exchange)
{
exchange.setURL(_requestUrl);
exchange.setMethod(HttpMethod.GET);
exchange.addRequestHeader("User-Agent","Jetty-Client/7.0");
exchange.addRequestHeader("Expect","100-continue"); //server to send CONTINUE 100
}
private static class TestHandler extends AbstractHandler
{
public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
{
if (baseRequest.isHandled())
return;
baseRequest.setHandled(true);
switch (_feature)
{
case CONTINUE:
// force 100 Continue response to be sent
request.getInputStream();
// next send data
case NORMAL:
response.setContentType("text/plain");
response.setStatus(HttpServletResponse.SC_OK);
response.getWriter().print(CONTENT);
break;
case NOTFOUND:
response.setStatus(HttpServletResponse.SC_NOT_FOUND);
break;
case TIMEOUT:
try
{
Thread.sleep(TIMEOUT*4);
}
catch (InterruptedException ex)
{
Log.ignore(ex);
}
break;
}
}
}
enum TestFeature {
CONTINUE,
NORMAL,
NOTFOUND,
TIMEOUT
}
}

View File

@ -1,47 +0,0 @@
//
// ========================================================================
// Copyright (c) 1995-2012 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
//
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
//
package org.eclipse.jetty.client;
import java.util.Collections;
import java.util.List;
import org.eclipse.jetty.http.HttpFields;
import org.junit.Assert;
public final class HttpAsserts
{
public static void assertContainsHeaderKey(String expectedKey, HttpFields headers)
{
if (headers.containsKey(expectedKey))
{
return;
}
List<String> names = Collections.list(headers.getFieldNames());
StringBuilder err = new StringBuilder();
err.append("Missing expected header key [").append(expectedKey);
err.append("] (of ").append(names.size()).append(" header fields)");
for (int i = 0; i < names.size(); i++)
{
String value = headers.getStringField(names.get(i));
err.append("\n").append(i).append("] ").append(names.get(i));
err.append(": ").append(value);
}
Assert.fail(err.toString());
}
}

View File

@ -1,225 +0,0 @@
//
// ========================================================================
// Copyright (c) 1995-2012 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
//
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
//
package org.eclipse.jetty.client;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.RejectedExecutionException;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;
public class HttpDestinationQueueTest
{
private static HttpClient _httpClient;
private static long _timeout = 200;
@BeforeClass
public static void beforeOnce() throws Exception
{
_httpClient = new HttpClient();
_httpClient.setMaxConnectionsPerAddress(1);
_httpClient.setMaxQueueSizePerAddress(1);
_httpClient.setTimeout(_timeout);
_httpClient.start();
}
@Test
public void testDestinationMaxQueueSize() throws Exception
{
ServerSocket server = new ServerSocket(0);
// This will keep the connection busy
HttpExchange exchange1 = new HttpExchange();
exchange1.setMethod("GET");
exchange1.setURL("http://localhost:" + server.getLocalPort() + "/exchange1");
_httpClient.send(exchange1);
// Read request so we are sure that this exchange is out of the queue
Socket socket = server.accept();
byte[] buffer = new byte[1024];
StringBuilder request = new StringBuilder();
while (true)
{
int read = socket.getInputStream().read(buffer);
request.append(new String(buffer,0,read,"UTF-8"));
if (request.toString().endsWith("\r\n\r\n"))
break;
}
Assert.assertTrue(request.toString().contains("exchange1"));
// This will be queued
HttpExchange exchange2 = new HttpExchange();
exchange2.setMethod("GET");
exchange2.setURL("http://localhost:" + server.getLocalPort() + "/exchange2");
_httpClient.send(exchange2);
// This will be rejected, since the connection is busy and the queue is full
HttpExchange exchange3 = new HttpExchange();
exchange3.setMethod("GET");
exchange3.setURL("http://localhost:" + server.getLocalPort() + "/exchange3");
try
{
_httpClient.send(exchange3);
Assert.fail();
}
catch (RejectedExecutionException x)
{
// Expected
}
// Send the response to avoid exceptions in the console
socket.getOutputStream().write("HTTP/1.1 200 OK\r\nContent-Length: 0\r\n\r\n".getBytes("UTF-8"));
Assert.assertEquals(HttpExchange.STATUS_COMPLETED,exchange1.waitForDone());
// Be sure that the second exchange can be sent
request.setLength(0);
while (true)
{
int read = socket.getInputStream().read(buffer);
request.append(new String(buffer,0,read,"UTF-8"));
if (request.toString().endsWith("\r\n\r\n"))
break;
}
Assert.assertTrue(request.toString().contains("exchange2"));
socket.getOutputStream().write("HTTP/1.1 200 OK\r\nConnection: close\r\n\r\n".getBytes("UTF-8"));
socket.close();
Assert.assertEquals(HttpExchange.STATUS_COMPLETED,exchange2.waitForDone());
server.close();
}
@Test
public void testDefaultTimeoutIncludesQueuingExchangeExpiresInQueue() throws Exception
{
ServerSocket server = new ServerSocket(0);
// This will keep the connection busy
HttpExchange exchange1 = new HttpExchange();
exchange1.setTimeout(_timeout * 3); // Be sure it does not expire
exchange1.setMethod("GET");
exchange1.setURL("http://localhost:" + server.getLocalPort() + "/exchange1");
_httpClient.send(exchange1);
// Read request so we are sure that this exchange is out of the queue
Socket socket = server.accept();
byte[] buffer = new byte[1024];
StringBuilder request = new StringBuilder();
while (true)
{
int read = socket.getInputStream().read(buffer);
request.append(new String(buffer,0,read,"UTF-8"));
if (request.toString().endsWith("\r\n\r\n"))
break;
}
Assert.assertTrue(request.toString().contains("exchange1"));
// This will be queued
HttpExchange exchange2 = new HttpExchange();
exchange2.setMethod("GET");
exchange2.setURL("http://localhost:" + server.getLocalPort() + "/exchange2");
_httpClient.send(exchange2);
// Wait until the queued exchange times out in the queue
Thread.sleep(_timeout * 2);
Assert.assertEquals(HttpExchange.STATUS_EXPIRED,exchange2.getStatus());
// Send the response to the first exchange to avoid exceptions in the console
socket.getOutputStream().write("HTTP/1.1 200 OK\r\nContent-Length: 0\r\n\r\n".getBytes("UTF-8"));
Assert.assertEquals(HttpExchange.STATUS_COMPLETED,exchange1.waitForDone());
socket.close();
server.close();
}
@Test
public void testDefaultTimeoutIncludesQueuingExchangeExpiresDuringRequest() throws Exception
{
ServerSocket server = new ServerSocket(0);
HttpExchange exchange1 = new HttpExchange();
exchange1.setMethod("GET");
exchange1.setURL("http://localhost:" + server.getLocalPort() + "/exchange1");
_httpClient.send(exchange1);
// Read request so we are sure that this exchange is out of the queue
Socket socket = server.accept();
byte[] buffer = new byte[1024];
StringBuilder request = new StringBuilder();
while (true)
{
int read = socket.getInputStream().read(buffer);
request.append(new String(buffer,0,read,"UTF-8"));
if (request.toString().endsWith("\r\n\r\n"))
break;
}
Assert.assertTrue(request.toString().contains("exchange1"));
// Wait until the exchange times out during the request
Thread.sleep(_timeout * 2);
Assert.assertEquals(HttpExchange.STATUS_EXPIRED,exchange1.getStatus());
socket.close();
server.close();
}
@Test
public void testExchangeTimeoutIncludesQueuingExchangeExpiresDuringResponse() throws Exception
{
ServerSocket server = new ServerSocket(0);
long timeout = 1000;
HttpExchange exchange1 = new HttpExchange();
exchange1.setTimeout(timeout);
exchange1.setMethod("GET");
exchange1.setURL("http://localhost:" + server.getLocalPort() + "/exchange1");
_httpClient.send(exchange1);
// Read request so we are sure that this exchange is out of the queue
Socket socket = server.accept();
byte[] buffer = new byte[1024];
StringBuilder request = new StringBuilder();
while (true)
{
int read = socket.getInputStream().read(buffer);
request.append(new String(buffer,0,read,"UTF-8"));
if (request.toString().endsWith("\r\n\r\n"))
break;
}
Assert.assertTrue(request.toString().contains("exchange1"));
// Write part of the response
socket.getOutputStream().write("HTTP/1.1 200 OK\r\nContent-Type: application/octet-stream\r\nContent-Length: 1\r\n\r\n".getBytes("UTF-8"));
// Wait until the exchange times out during the response
Thread.sleep(timeout * 2);
Assert.assertEquals(HttpExchange.STATUS_EXPIRED,exchange1.getStatus());
socket.close();
server.close();
}
}

View File

@ -1,699 +0,0 @@
//
// ========================================================================
// Copyright (c) 1995-2012 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
//
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
//
package org.eclipse.jetty.client;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import static org.junit.matchers.JUnitMatchers.containsString;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URI;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
import org.eclipse.jetty.client.helperClasses.HttpServerAndClientCreator;
import org.eclipse.jetty.client.helperClasses.ServerAndClientCreator;
import org.eclipse.jetty.client.security.ProxyAuthorization;
import org.eclipse.jetty.http.HttpFields;
import org.eclipse.jetty.http.HttpMethod;
import org.eclipse.jetty.http.HttpStatus;
import org.eclipse.jetty.io.ByteArrayBuffer;
import org.eclipse.jetty.io.Connection;
import org.eclipse.jetty.io.EofException;
import org.eclipse.jetty.io.nio.DirectNIOBuffer;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.toolchain.test.Stress;
import org.eclipse.jetty.util.component.AbstractLifeCycle;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
/* ------------------------------------------------------------ */
/**
* Functional testing for HttpExchange.
*/
public class HttpExchangeTest
{
final static boolean verbose=HttpExchange.LOG.isDebugEnabled();
protected static int _maxConnectionsPerAddress = 2;
protected static String _scheme = "http";
protected static Server _server;
protected static int _port;
protected static HttpClient _httpClient;
protected static AtomicInteger _count = new AtomicInteger();
protected static ServerAndClientCreator serverAndClientCreator = new HttpServerAndClientCreator();
protected static URI getBaseURI()
{
return URI.create(_scheme + "://localhost:" + _port + "/");
}
/* ------------------------------------------------------------ */
// TODO work out why BeforeClass does not work here?
@Before
public void setUpOnce() throws Exception
{
_scheme = "http";
_server = serverAndClientCreator.createServer();
_httpClient = serverAndClientCreator.createClient(3000L,3500L,2000);
_port = _server.getConnectors()[0].getLocalPort();
}
/* ------------------------------------------------------------ */
@After
public void tearDownOnce() throws Exception
{
_httpClient.stop();
long startTime = System.currentTimeMillis();
while (!_httpClient.getState().equals(AbstractLifeCycle.STOPPED))
{
if (System.currentTimeMillis() - startTime > 1000)
break;
Thread.sleep(5);
}
_server.stop();
}
/* ------------------------------------------------------------ */
@Test
public void testResetNewExchange() throws Exception
{
HttpExchange exchange = new HttpExchange();
exchange.reset();
}
/* ------------------------------------------------------------ */
@Test
public void testPerf() throws Exception
{
sender(1,false);
sender(1,true);
sender(10,false);
sender(10,true);
if (Stress.isEnabled())
{
sender(100,false);
sender(100,true);
sender(10000,false);
sender(10000,true);
}
}
/* ------------------------------------------------------------ */
/**
* Test sending data through the exchange.
*
* @throws IOException
*/
public void sender(final int nb, final boolean close) throws Exception
{
// System.err.printf("%nSENDER %d %s%n",nb,close);
_count.set(0);
final CountDownLatch complete = new CountDownLatch(nb);
final AtomicInteger allcontent = new AtomicInteger(nb);
HttpExchange[] httpExchange = new HttpExchange[nb];
long start = System.currentTimeMillis();
for (int i = 0; i < nb; i++)
{
final int n = i;
httpExchange[n] = new HttpExchange()
{
String result = "pending";
int len = 0;
/* ------------------------------------------------------------ */
@Override
protected void onRequestCommitted()
{
if (verbose)
System.err.println(n+" [ "+this);
result = "committed";
}
/* ------------------------------------------------------------ */
@Override
protected void onRequestComplete() throws IOException
{
if (verbose)
System.err.println(n+" [ ==");
result = "sent";
}
@Override
/* ------------------------------------------------------------ */
protected void onResponseStatus(ByteBuffer version, int status, ByteBuffer reason)
{
if (verbose)
System.err.println(n+" ] "+version+" "+status+" "+reason);
result = "status";
}
/* ------------------------------------------------------------ */
@Override
protected void onResponseHeader(ByteBuffer name, ByteBuffer value)
{
if (verbose)
System.err.println(n+" ] "+name+": "+value);
}
/* ------------------------------------------------------------ */
@Override
protected void onResponseHeaderComplete() throws IOException
{
if (verbose)
System.err.println(n+" ] -");
result = "content";
super.onResponseHeaderComplete();
}
/* ------------------------------------------------------------ */
@Override
protected void onResponseContent(ByteBuffer content)
{
len += content.length();
if (verbose)
System.err.println(n+" ] "+content.length()+" -> "+len);
}
/* ------------------------------------------------------------ */
@Override
protected void onResponseComplete()
{
if (verbose)
System.err.println(n+" ] == "+len+" "+complete.getCount()+"/"+nb);
result = "complete";
if (len == 2009)
allcontent.decrementAndGet();
else
System.err.println(n+ " ONLY " + len+ "/2009");
complete.countDown();
}
/* ------------------------------------------------------------ */
@Override
protected void onConnectionFailed(Throwable ex)
{
if (verbose)
System.err.println(n+" ] "+ex);
complete.countDown();
result = "failed";
System.err.println(n+ " FAILED " + ex);
super.onConnectionFailed(ex);
}
/* ------------------------------------------------------------ */
@Override
protected void onException(Throwable ex)
{
if (verbose)
System.err.println(n+" ] "+ex);
complete.countDown();
result = "excepted";
System.err.println(n+ " EXCEPTED " + ex);
super.onException(ex);
}
/* ------------------------------------------------------------ */
@Override
protected void onExpire()
{
if (verbose)
System.err.println(n+" ] expired");
complete.countDown();
result = "expired";
System.err.println(n + " EXPIRED " + len);
super.onExpire();
}
/* ------------------------------------------------------------ */
@Override
public String toString()
{
return n+"/"+result+"/"+len+"/"+super.toString();
}
};
httpExchange[n].setURI(getBaseURI().resolve("/" + n));
httpExchange[n].addRequestHeader("arbitrary","value");
if (close)
httpExchange[n].setRequestHeader("Connection","close");
_httpClient.send(httpExchange[n]);
}
if (!complete.await(2,TimeUnit.SECONDS))
System.err.println(_httpClient.dump());
assertTrue(complete.await(20,TimeUnit.SECONDS));
assertEquals("nb="+nb+" close="+close,0,allcontent.get());
}
/* ------------------------------------------------------------ */
@Test
public void testPostWithContentExchange() throws Exception
{
for (int i=0;i<20;i++)
{
ContentExchange httpExchange=new ContentExchange();
httpExchange.setURI(getBaseURI());
httpExchange.setMethod(HttpMethod.POST);
httpExchange.setRequestContent(new ByteArrayBuffer("<hello />"));
_httpClient.send(httpExchange);
int status = httpExchange.waitForDone();
//httpExchange.waitForStatus(HttpExchange.STATUS_COMPLETED);
String result=httpExchange.getResponseContent();
assertEquals(HttpExchange.STATUS_COMPLETED, status);
assertEquals("i="+i,"<hello />",result);
}
}
/* ------------------------------------------------------------ */
@Test
public void testGetWithContentExchange() throws Exception
{
for (int i=0;i<10;i++)
{
ContentExchange httpExchange=new ContentExchange();
URI uri = getBaseURI().resolve("?i=" + i);
httpExchange.setURI(uri);
httpExchange.setMethod(HttpMethod.GET);
_httpClient.send(httpExchange);
int status = httpExchange.waitForDone();
//httpExchange.waitForStatus(HttpExchange.STATUS_COMPLETED);
String result=httpExchange.getResponseContent();
assertNotNull("Should have received response content", result);
assertEquals("i="+i,0,result.indexOf("<hello>"));
assertEquals("i="+i,result.length()-10,result.indexOf("</hello>"));
assertEquals(HttpExchange.STATUS_COMPLETED, status);
Thread.sleep(5);
}
}
/* ------------------------------------------------------------ */
@Test
public void testLocalAddressAvailabilityWithContentExchange() throws Exception
{
for (int i=0;i<10;i++)
{
ContentExchange httpExchange=new ContentExchange();
URI uri = getBaseURI().resolve("?i=" + i);
httpExchange.setURI(uri);
httpExchange.setMethod(HttpMethod.GET);
_httpClient.send(httpExchange);
int status = httpExchange.waitForDone();
assertNotNull(httpExchange.getLocalAddress());
String result=httpExchange.getResponseContent();
assertNotNull("Should have received response content", result);
assertEquals("i="+i,0,result.indexOf("<hello>"));
assertEquals("i="+i,result.length()-10,result.indexOf("</hello>"));
assertEquals(HttpExchange.STATUS_COMPLETED, status);
Thread.sleep(5);
}
}
/* ------------------------------------------------------------ */
@Test
public void testShutdownWithExchange() throws Exception
{
final AtomicReference<Throwable> throwable=new AtomicReference<Throwable>();
HttpExchange httpExchange=new HttpExchange()
{
/* ------------------------------------------------------------ */
/**
* @see org.eclipse.jetty.client.HttpExchange#onException(java.lang.Throwable)
*/
@Override
protected void onException(Throwable x)
{
throwable.set(x);
}
/* ------------------------------------------------------------ */
/**
* @see org.eclipse.jetty.client.HttpExchange#onConnectionFailed(java.lang.Throwable)
*/
@Override
protected void onConnectionFailed(Throwable x)
{
throwable.set(x);
}
};
httpExchange.setURI(getBaseURI());
httpExchange.setMethod("SLEEP");
_httpClient.send(httpExchange);
new Thread()
{
@Override
public void run()
{
try {
Thread.sleep(500);
_httpClient.stop();
} catch(Exception e) {e.printStackTrace();}
}
}.start();
int status = httpExchange.waitForDone();
System.err.println(throwable.get());
assertTrue(throwable.get().toString().indexOf("close")>=0);
assertEquals(HttpExchange.STATUS_EXCEPTED, status);
_httpClient.start();
}
/* ------------------------------------------------------------ */
@Test
public void testBigPostWithContentExchange() throws Exception
{
int size =32;
ContentExchange httpExchange=new ContentExchange()
{
int total;
@Override
protected synchronized void onResponseStatus(ByteBuffer version, int status, ByteBuffer reason) throws IOException
{
if (verbose)
System.err.println("] "+version+" "+status+" "+reason);
super.onResponseStatus(version,status,reason);
}
@Override
protected synchronized void onResponseHeader(ByteBuffer name, ByteBuffer value) throws IOException
{
if (verbose)
System.err.println("] "+name+": "+value);
super.onResponseHeader(name,value);
}
@Override
protected synchronized void onResponseContent(ByteBuffer content) throws IOException
{
if (verbose)
{
total+=content.length();
System.err.println("] "+content.length()+" -> "+total);
}
super.onResponseContent(content);
}
@Override
protected void onRequestComplete() throws IOException
{
if (verbose)
System.err.println("] ==");
super.onRequestComplete();
}
@Override
protected void onResponseHeaderComplete() throws IOException
{
if (verbose)
System.err.println("] --");
super.onResponseHeaderComplete();
}
};
ByteBuffer babuf = new ByteArrayBuffer(size*36*1024);
ByteBuffer niobuf = new DirectNIOBuffer(size*36*1024);
byte[] bytes="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ".getBytes();
for (int i=0;i<size*1024;i++)
{
babuf.put(bytes);
niobuf.put(bytes);
}
httpExchange.setURI(getBaseURI());
httpExchange.setMethod(HttpMethod.POST);
httpExchange.setRequestContentType("application/data");
httpExchange.setRequestContent(babuf);
_httpClient.send(httpExchange);
long start=System.currentTimeMillis();
while(!httpExchange.isDone())
{
long now=System.currentTimeMillis();
if ((now-start)>=10000)
{
System.err.println("TEST IS TAKING TOOOOO LONG!!!!!!!!!!!!!!!!!!!!");
System.err.println("CLIENT:");
System.err.println(_httpClient.dump());
System.err.println("SERVER:");
_server.dumpStdErr();
break;
}
Thread.sleep(100);
}
int status = httpExchange.waitForDone();
assertEquals(HttpExchange.STATUS_COMPLETED,status);
String result=httpExchange.getResponseContent();
assertEquals(babuf.length(),result.length());
httpExchange.reset();
httpExchange.setURI(getBaseURI());
httpExchange.setMethod(HttpMethod.POST);
httpExchange.setRequestContentType("application/data");
httpExchange.setRequestContent(niobuf);
_httpClient.send(httpExchange);
start=System.currentTimeMillis();
while(!httpExchange.isDone())
{
long now=System.currentTimeMillis();
if ((now-start)>=10000)
{
System.err.println("TEST IS TAKING TOOOOO LONG!!!!!!!!!!!!!!!!!!!!");
System.err.println("CLIENT:");
System.err.println(_httpClient.dump());
System.err.println("SERVER:");
_server.dumpStdErr();
break;
}
Thread.sleep(100);
}
status = httpExchange.waitForDone();
assertEquals(HttpExchange.STATUS_COMPLETED, status);
result=httpExchange.getResponseContent();
assertEquals(niobuf.length(),result.length());
}
/* ------------------------------------------------------------ */
@Test
public void testSlowPost() throws Exception
{
ContentExchange httpExchange=new ContentExchange();
httpExchange.setURI(getBaseURI());
httpExchange.setMethod(HttpMethod.POST);
final String data="012345678901234567890123456789012345678901234567890123456789";
InputStream content = new InputStream()
{
int _index=0;
@Override
public int read() throws IOException
{
// System.err.printf("reading 1 of %d/%d%n",_index,data.length());
if (_index>=data.length())
return -1;
try
{
Thread.sleep(5);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
// System.err.printf("read 1%n");
return data.charAt(_index++);
}
@Override
public int read(byte[] b, int off, int len) throws IOException
{
// System.err.printf("reading %d of %d/%d%n",len,_index,data.length());
if (_index >= data.length())
return -1;
try
{
Thread.sleep(25);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
int l = 0;
while (l < 5 && _index < data.length() && l < len)
b[off + l++] = (byte)data.charAt(_index++);
// System.err.printf("read %d%n",l);
return l;
}
};
httpExchange.setRequestContentSource(content);
_httpClient.send(httpExchange);
int status = httpExchange.waitForDone();
String result = httpExchange.getResponseContent();
assertEquals(HttpExchange.STATUS_COMPLETED,status);
assertEquals(data,result);
}
/* ------------------------------------------------------------ */
@Test
public void testProxy() throws Exception
{
if (_scheme.equals("https"))
return;
try
{
_httpClient.setProxy(new Address("127.0.0.1",_port));
_httpClient.setProxyAuthentication(new ProxyAuthorization("user","password"));
ContentExchange httpExchange=new ContentExchange();
httpExchange.setAddress(new Address("jetty.eclipse.org",8080));
httpExchange.setMethod(HttpMethod.GET);
httpExchange.setRequestURI("/jetty-6");
_httpClient.send(httpExchange);
int status = httpExchange.waitForDone();
//httpExchange.waitForStatus(HttpExchange.STATUS_COMPLETED);
String result=httpExchange.getResponseContent();
assertNotNull("Should have received response content", result);
result=result.trim();
assertEquals(HttpExchange.STATUS_COMPLETED, status);
assertTrue(result.startsWith("Proxy request: http://jetty.eclipse.org:8080/jetty-6"));
assertTrue(result.endsWith("Basic dXNlcjpwYXNzd29yZA=="));
}
finally
{
_httpClient.setProxy(null);
}
}
/* ------------------------------------------------------------ */
@Test
public void testReserveConnections () throws Exception
{
_httpClient = serverAndClientCreator.createClient(3000L,3500L,2000);
final HttpDestination destination = _httpClient.getDestination(new Address("localhost",_port),_scheme.equalsIgnoreCase("https"));
final org.eclipse.jetty.client.AbstractHttpConnection[] connections = new org.eclipse.jetty.client.AbstractHttpConnection[_maxConnectionsPerAddress];
for (int i = 0; i < _maxConnectionsPerAddress; i++)
{
connections[i] = destination.reserveConnection(200);
assertNotNull(connections[i]);
HttpExchange ex = new ContentExchange();
ex.setURI(getBaseURI().resolve("?i=" + i));
ex.setMethod(HttpMethod.GET);
connections[i].send(ex);
}
// try to get a connection, and only wait 500ms, as we have
// already reserved the max, should return null
Connection c = destination.reserveConnection(500);
assertNull(c);
// unreserve first connection
destination.returnConnection(connections[0],false);
// reserving one should now work
c = destination.reserveConnection(500);
assertNotNull(c);
// release connections
for (AbstractHttpConnection httpConnection : connections){
destination.returnConnection(httpConnection,false);
}
}
@Test
public void testOptionsWithExchange() throws Exception
{
ContentExchange httpExchange = new ContentExchange(true);
httpExchange.setURL(getBaseURI().toASCIIString());
httpExchange.setRequestURI("*");
httpExchange.setMethod(HttpMethod.OPTIONS);
// httpExchange.setRequestHeader("Connection","close");
_httpClient.send(httpExchange);
int state = httpExchange.waitForDone();
assertEquals(HttpExchange.STATUS_COMPLETED, state);
assertEquals(HttpStatus.OK_200,httpExchange.getResponseStatus());
HttpFields headers = httpExchange.getResponseFields();
HttpAsserts.assertContainsHeaderKey("Content-Length", headers);
assertEquals("Content-Length header value", 0, headers.getLongField("Content-Length"));
HttpAsserts.assertContainsHeaderKey("Allow",headers);
String allow = headers.getStringField("Allow");
String expectedMethods[] =
{ "GET", "HEAD", "POST", "PUT", "DELETE", "MOVE", "OPTIONS", "TRACE" };
for (String expectedMethod : expectedMethods)
{
assertThat(allow,containsString(expectedMethod));
}
}
/* ------------------------------------------------------------ */
public static void copyStream(InputStream in, OutputStream out)
{
try
{
byte[] buffer = new byte[1024];
int len;
while ((len = in.read(buffer)) >= 0)
{
out.write(buffer,0,len);
}
}
catch (EofException e)
{
System.err.println("HttpExchangeTest#copyStream: " + e);
}
catch (IOException e)
{
e.printStackTrace();
}
}
}

View File

@ -1,237 +0,0 @@
//
// ========================================================================
// Copyright (c) 1995-2012 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
//
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
//
package org.eclipse.jetty.client;
import static org.junit.Assert.assertEquals;
import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.client.security.Realm;
import org.eclipse.jetty.client.security.SimpleRealmResolver;
import org.eclipse.jetty.http.HttpMethod;
import org.eclipse.jetty.http.HttpStatus;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.handler.AbstractHandler;
import org.eclipse.jetty.server.nio.SelectChannelConnector;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
/* ------------------------------------------------------------ */
public class HttpGetRedirectTest
{
private static String _content =
"Lorem ipsum dolor sit amet, consectetur adipiscing elit. In quis felis nunc. "+
"Quisque suscipit mauris et ante auctor ornare rhoncus lacus aliquet. Pellentesque "+
"habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. "+
"Vestibulum sit amet felis augue, vel convallis dolor. Cras accumsan vehicula diam "+
"at faucibus. Etiam in urna turpis, sed congue mi. Morbi et lorem eros. Donec vulputate "+
"velit in risus suscipit lobortis. Aliquam id urna orci, nec sollicitudin ipsum. "+
"Cras a orci turpis. Donec suscipit vulputate cursus. Mauris nunc tellus, fermentum "+
"eu auctor ut, mollis at diam. Quisque porttitor ultrices metus, vitae tincidunt massa "+
"sollicitudin a. Vivamus porttitor libero eget purus hendrerit cursus. Integer aliquam "+
"consequat mauris quis luctus. Cras enim nibh, dignissim eu faucibus ac, mollis nec neque. "+
"Aliquam purus mauris, consectetur nec convallis lacinia, porta sed ante. Suspendisse "+
"et cursus magna. Donec orci enim, molestie a lobortis eu, imperdiet vitae neque.";
private File _docRoot;
private Server _server;
private HttpClient _client;
private Realm _realm;
private String _protocol;
private String _requestUrl;
private String _requestUrl2;
private RedirectHandler _handler;
/* ------------------------------------------------------------ */
@Before
public void setUp()
throws Exception
{
_docRoot = new File("target/test-output/docroot/");
_docRoot.mkdirs();
_docRoot.deleteOnExit();
_server = new Server();
configureServer(_server);
org.eclipse.jetty.server.bio.SocketConnector connector = new org.eclipse.jetty.server.bio.SocketConnector();
_server.addConnector(connector);
_server.start();
int port = _server.getConnectors()[0].getLocalPort();
_requestUrl = _protocol+"://localhost:"+port+ "/content.txt";
_handler._toURL=_protocol+"://localhost:"+connector.getLocalPort()+ "/moved.txt";
}
/* ------------------------------------------------------------ */
@After
public void tearDown()
throws Exception
{
if (_server != null)
{
_server.stop();
_server = null;
}
}
/* ------------------------------------------------------------ */
@Test
public void testGet() throws Exception
{
startClient(_realm);
ContentExchange getExchange = new ContentExchange();
getExchange.setURL(_requestUrl);
getExchange.setMethod(HttpMethod.GET);
_client.send(getExchange);
int state = getExchange.waitForDone();
String content = "";
int responseStatus = getExchange.getResponseStatus();
if (responseStatus == HttpStatus.OK_200)
{
content = getExchange.getResponseContent();
}
assertEquals(HttpStatus.OK_200,responseStatus);
assertEquals(_content,content);
stopClient();
}
/* ------------------------------------------------------------ */
protected void configureServer(Server server)
throws Exception
{
setProtocol("http");
SelectChannelConnector connector = new SelectChannelConnector();
server.addConnector(connector);
_handler = new RedirectHandler(HttpStatus.MOVED_PERMANENTLY_301, "/content.txt", "WAIT FOR IT", 2);
server.setHandler( _handler );
}
/* ------------------------------------------------------------ */
protected void startClient(Realm realm)
throws Exception
{
_client = new HttpClient();
_client.setConnectorType(HttpClient.CONNECTOR_SELECT_CHANNEL);
_client.registerListener("org.eclipse.jetty.client.RedirectListener");
if (realm != null)
_client.setRealmResolver(new SimpleRealmResolver(realm));
_client.start();
}
/* ------------------------------------------------------------ */
protected void stopClient()
throws Exception
{
if (_client != null)
{
_client.stop();
_client = null;
}
}
/* ------------------------------------------------------------ */
protected String getBasePath()
{
return _docRoot.getAbsolutePath();
}
/* ------------------------------------------------------------ */
protected void setProtocol(String protocol)
{
_protocol = protocol;
}
/* ------------------------------------------------------------ */
protected void setRealm(Realm realm)
{
_realm = realm;
}
/* ------------------------------------------------------------ */
private static class RedirectHandler
extends AbstractHandler
{
private final String _fromURI;
private final int _code;
private final int _maxRedirects;
private int _redirectCount = 0;
private String _toURL;
/* ------------------------------------------------------------ */
public RedirectHandler( final int code, final String fromURI, final String toURL, final int maxRedirects )
{
this._code = code;
this._fromURI = fromURI;
this._toURL = toURL;
this._maxRedirects = maxRedirects;
if (_fromURI==null || _toURL==null)
throw new IllegalArgumentException();
}
/* ------------------------------------------------------------ */
public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response)
throws IOException, ServletException
{
if ( baseRequest.isHandled() )
{
return;
}
if (request.getRequestURI().equals(_fromURI))
{
_redirectCount++;
String location = ( _redirectCount <= _maxRedirects )?_fromURI:_toURL;
response.setStatus( _code );
response.setHeader( "Location", location );
( (Request) request ).setHandled( true );
}
else
{
PrintWriter out = response.getWriter();
out.write(_content);
baseRequest.setHandled( true );
}
}
}
}

View File

@ -1,193 +0,0 @@
//
// ========================================================================
// Copyright (c) 1995-2012 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
//
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
//
package org.eclipse.jetty.client;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import java.io.File;
import java.io.IOException;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.http.HttpMethod;
import org.eclipse.jetty.http.HttpStatus;
import org.eclipse.jetty.server.Connector;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.handler.AbstractHandler;
import org.eclipse.jetty.server.nio.SelectChannelConnector;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
public class HttpHeadersTest
{
private static final Logger LOG = Log.getLogger(HttpHeadersTest.class);
private static final String CONTENT = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. In quis felis nunc. "
+ "Quisque suscipit mauris et ante auctor ornare rhoncus lacus aliquet. Pellentesque "
+ "habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. "
+ "Vestibulum sit amet felis augue, vel convallis dolor. Cras accumsan vehicula diam "
+ "at faucibus. Etiam in urna turpis, sed congue mi. Morbi et lorem eros. Donec vulputate "
+ "velit in risus suscipit lobortis. Aliquam id urna orci, nec sollicitudin ipsum. "
+ "Cras a orci turpis. Donec suscipit vulputate cursus. Mauris nunc tellus, fermentum "
+ "eu auctor ut, mollis at diam. Quisque porttitor ultrices metus, vitae tincidunt massa "
+ "sollicitudin a. Vivamus porttitor libero eget purus hendrerit cursus. Integer aliquam "
+ "consequat mauris quis luctus. Cras enim nibh, dignissim eu faucibus ac, mollis nec neque. "
+ "Aliquam purus mauris, consectetur nec convallis lacinia, porta sed ante. Suspendisse "
+ "et cursus magna. Donec orci enim, molestie a lobortis eu, imperdiet vitae neque.";
private Server _server;
private TestHeaderHandler _handler;
private int _port;
@Before
public void init() throws Exception
{
File docRoot = new File("target/test-output/docroot/");
if (!docRoot.exists())
assertTrue(docRoot.mkdirs());
docRoot.deleteOnExit();
_server = new Server();
Connector connector = new SelectChannelConnector();
_server.addConnector(connector);
_handler = new TestHeaderHandler();
_server.setHandler(_handler);
_server.start();
_port = connector.getLocalPort();
}
@After
public void destroy() throws Exception
{
_server.stop();
_server.join();
}
@Test
public void testHttpHeaders() throws Exception
{
HttpClient httpClient = new HttpClient();
httpClient.setConnectorType(HttpClient.CONNECTOR_SELECT_CHANNEL);
httpClient.start();
try
{
String requestUrl = "http://localhost:" + _port + "/header";
ContentExchange exchange = new ContentExchange();
exchange.setURL(requestUrl);
exchange.setMethod(HttpMethod.GET);
exchange.addRequestHeader("User-Agent","Jetty-Client/7.0");
httpClient.send(exchange);
int state = exchange.waitForDone();
assertEquals(HttpExchange.STATUS_COMPLETED, state);
int responseStatus = exchange.getResponseStatus();
assertEquals(HttpStatus.OK_200,responseStatus);
String content = exchange.getResponseContent();
assertEquals(HttpHeadersTest.CONTENT,content);
assertEquals("Jetty-Client/7.0",_handler.headers.get("User-Agent"));
}
finally
{
httpClient.stop();
}
}
@Test
public void testHttpHeadersSize() throws Exception
{
HttpClient httpClient = new HttpClient();
httpClient.setConnectorType(HttpClient.CONNECTOR_SELECT_CHANNEL);
httpClient.start();
try
{
String requestUrl = "http://localhost:" + _port + "/header";
ContentExchange exchange = new ContentExchange()
{
@Override
protected void onException(Throwable x)
{
// suppress exception
LOG.ignore(x);
}
};
exchange.setURL(requestUrl);
exchange.setMethod(HttpMethod.GET);
for (int i = 0; i < 4; i++)
{
for (int j = 0; j < 1024; j++)
{
exchange.addRequestHeader("header" + i + "-" + j,"v");
}
}
httpClient.send(exchange);
int state = exchange.waitForDone();
assertEquals(HttpExchange.STATUS_EXCEPTED, state);
}
finally
{
httpClient.stop();
}
}
private static class TestHeaderHandler extends AbstractHandler
{
protected Map<String, String> headers;
public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
{
if (baseRequest.isHandled())
return;
headers = new HashMap<String, String>();
for (Enumeration e = request.getHeaderNames(); e.hasMoreElements();)
{
String name = (String)e.nextElement();
headers.put(name,request.getHeader(name));
}
response.setContentType("text/plain");
response.setStatus(HttpServletResponse.SC_OK);
response.getWriter().print(CONTENT);
baseRequest.setHandled(true);
}
}
}

View File

@ -1,123 +0,0 @@
//
// ========================================================================
// Copyright (c) 1995-2012 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
//
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
//
package org.eclipse.jetty.client;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.Socket;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.client.security.Authentication;
import org.eclipse.jetty.client.security.BasicAuthentication;
import org.eclipse.jetty.client.security.Realm;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.handler.ConnectHandler;
import org.eclipse.jetty.server.nio.SelectChannelConnector;
import org.junit.After;
import org.junit.Assert;
import org.junit.Assume;
import org.junit.Before;
import org.junit.Test;
public class HttpsProxyAuthenticationTest
{
private Server _proxy = new Server();
private HttpClient _client = new HttpClient();
private boolean authHandlerSend;
@Before
public void init() throws Exception
{
SelectChannelConnector connector = new SelectChannelConnector();
_proxy.addConnector(connector);
_proxy.setHandler(new ConnectHandler()
{
@Override
protected boolean handleAuthentication(HttpServletRequest request, HttpServletResponse response, String address) throws ServletException, IOException
{
String authHeader = request.getHeader("Authorization");
if (authHeader != null && authHeader.length() > 0)
authHandlerSend = true;
return super.handleAuthentication(request,response,address);
}
});
_proxy.start();
int proxyPort = connector.getLocalPort();
Authentication authentication = new BasicAuthentication(new Realm()
{
public String getId()
{
return "MyRealm";
}
public String getPrincipal()
{
return "jetty";
}
public String getCredentials()
{
return "jetty";
}
});
_client.setProxy(new Address("localhost", proxyPort));
_client.setProxyAuthentication(authentication);
_client.start();
}
@After
public void destroy() throws Exception
{
_client.stop();
_proxy.stop();
_proxy.join();
}
@Test
public void httpsViaProxyThatReturns504ErrorTest() throws Exception
{
// Assume that we can connect to google
String host = "google.com";
int port = 443;
Socket socket = new Socket();
try
{
socket.connect(new InetSocketAddress(host, port), 1000);
}
catch (IOException x)
{
Assume.assumeNoException(x);
}
finally
{
socket.close();
}
HttpExchange exchange = new ContentExchange();
exchange.setURL("https://" + host + ":" + port);
exchange.addRequestHeader("behaviour", "google");
_client.send(exchange);
Assert.assertEquals(HttpExchange.STATUS_COMPLETED, exchange.waitForDone());
Assert.assertTrue("Authorization header not set!", authHandlerSend);
}
}

View File

@ -1,141 +0,0 @@
//
// ========================================================================
// Copyright (c) 1995-2012 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
//
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
//
package org.eclipse.jetty.client;
import static org.junit.Assert.assertEquals;
import java.io.IOException;
import java.net.ProtocolException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.http.HttpStatus;
import org.eclipse.jetty.server.AbstractHttpConnection;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.handler.ConnectHandler;
import org.eclipse.jetty.server.nio.SelectChannelConnector;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
/* ------------------------------------------------------------ */
/**
* This UnitTest class executes two tests. Both will send a http request to https://google.com through a misbehaving proxy server.
* <p/>
* The first test runs against a proxy which simply closes the connection (as nginx does) for a connect request. The second proxy server always responds with a
* 500 error.
* <p/>
* The expected result for both tests is an exception and the HttpExchange should have status HttpExchange.STATUS_EXCEPTED.
*/
public class HttpsViaBrokenHttpProxyTest
{
private Server _proxy = new Server();
private HttpClient _client = new HttpClient();
@Before
public void init() throws Exception
{
// setup proxies with different behaviour
_proxy.addConnector(new SelectChannelConnector());
_proxy.setHandler(new BadBehavingConnectHandler());
_proxy.start();
int proxyClosingConnectionPort = _proxy.getConnectors()[0].getLocalPort();
_client.setProxy(new Address("localhost", proxyClosingConnectionPort));
_client.start();
}
@After
public void destroy() throws Exception
{
_client.stop();
_proxy.stop();
}
@Test
public void httpsViaProxyThatClosesConnectionOnConnectRequestTest() throws Exception
{
sendRequestThroughProxy(new ContentExchange()
{
@Override
protected void onException(Throwable x)
{
}
}, "close", 9);
}
@Test
public void httpsViaProxyThatReturns500ErrorTest() throws Exception
{
HttpExchange exchange = new ContentExchange()
{
@Override
protected void onException(Throwable x)
{
// Suppress logging for expected exception
if (!(x instanceof ProtocolException))
super.onException(x);
}
};
sendRequestThroughProxy(exchange, "error500", 9);
}
@Test
public void httpsViaProxyThatReturns504ErrorTest() throws Exception
{
sendRequestThroughProxy(new ContentExchange(), "error504", 8);
}
private void sendRequestThroughProxy(HttpExchange exchange, String desiredBehaviour, int exptectedStatus) throws Exception
{
String url = "https://" + desiredBehaviour + ".com/";
exchange.setURL(url);
exchange.addRequestHeader("behaviour", desiredBehaviour);
_client.send(exchange);
assertEquals(HttpExchange.toState(exptectedStatus) + " status awaited", exptectedStatus, exchange.waitForDone());
}
private class BadBehavingConnectHandler extends ConnectHandler
{
@Override
protected void handleConnect(Request baseRequest, HttpServletRequest request, HttpServletResponse response, String serverAddress)
throws ServletException, IOException
{
if (serverAddress.contains("close"))
{
AbstractHttpConnection.getCurrentConnection().getEndPoint().close();
}
else if (serverAddress.contains("error500"))
{
response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR_500);
}
else if (serverAddress.contains("error504"))
{
response.setStatus(HttpStatus.GATEWAY_TIMEOUT_504);
}
baseRequest.setHandled(true);
}
}
}

Some files were not shown because too many files have changed in this diff Show More