pax_global_header00006660000000000000000000000064116655305600014521gustar00rootroot0000000000000052 comment=8a5d9170f13e25fbd6bf7666fcd7134571eaa868 async-http-client-1.6.5/000077500000000000000000000000001166553056000151005ustar00rootroot00000000000000async-http-client-1.6.5/.gitignore000066400000000000000000000002461166553056000170720ustar00rootroot00000000000000*.class *~ .*.swp .*.swo .loadpath .buildpath .classpath .project .settings .idea *.iml *.ipr *.iws nbproject .DS_Store target test-output /META-INF/MANIFEST.MF work async-http-client-1.6.5/LICENSE-2.0.txt000066400000000000000000000261361166553056000172300ustar00rootroot00000000000000 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. async-http-client-1.6.5/README000066400000000000000000000120521166553056000157600ustar00rootroot00000000000000Async Http Client Copyright 2010 Ning Inc DESCRIPTION ----------- Getting started: http://is.gd/kexrN (PDF) http://is.gd/ja6My (HTML) Async Http Client library purpose is to allow Java applications to easily execute HTTP requests and asynchronously process the HTTP responses. The Async HTTP Client library is simple to use. First, in order to add it to your Maven project, simply add this dependency: Sonatype Sonatype Release http://oss.sonatype.org/content/repositories/releases and then define the dependency as: com.ning async-http-client 1.6.2 You can also download the artifact http://oss.sonatype.org/content/repositories/releases Then in your code you can simply do: import com.ning.http.client.*; import java.util.concurrent.Future; AsyncHttpClient asyncHttpClient = new AsyncHttpClient(); Future f = asyncHttpClient.prepareGet("http://www.ning.com/ ").execute(); Response r = f.get(); You can also accomplish asynchronous operation without using a Future if you want to receive and process the response in your handler: import com.ning.http.client.*; import java.util.concurrent.Future; AsyncHttpClient asyncHttpClient = new AsyncHttpClient(); asyncHttpClient.prepareGet("http://www.ning.com/ ").execute(new AsyncCompletionHandler(){ @Override public Response onCompleted(Response response) throws Exception{ // Do something with the Response // ... return response; } @Override public void onThrowable(Throwable t){ // Something wrong happened. } }); You can also mix Future with AsyncHandler to only retrieve part of the asynchronous response import com.ning.http.client.*; import java.util.concurrent.Future; AsyncHttpClient asyncHttpClient = new AsyncHttpClient(); Future f = asyncHttpClient.prepareGet("http://www.ning.com/ ").execute(new AsyncCompletionHandler(){ @Override public Integer onCompleted(Response response) throws Exception{ // Do something with the Response return response.getStatusCode(); } @Override public void onThrowable(Throwable t){ // Something wrong happened. } }); int statuѕCode = f.get(); You have full control on the Response life cycle, so you can decide at any moment to stop processing what the server is sending back: import com.ning.http.client.*; import java.util.concurrent.Future; AsyncHttpClient c = new AsyncHttpClient(); Future f = c.prepareGet("http://www.ning.com/ ").execute(new AsyncHandler() { private StringBuilder builder = new StringBuilder(); @Override public STATE onStatusReceived(HttpResponseStatus status) throws Exception { int statusCode = status.getStatusCode(); // The Status have been read // If you don't want to read the headers,body or stop processing the response return STATE.ABORT; } @Override public STATE onHeadersReceived(HttpResponseHeaders h) throws Exception { Headers headers = h.getHeaders(); // The headers have been read // If you don't want to read the body, or stop processing the response return STATE.ABORT; } @Override public STATE onBodyPartReceived(HttpResponseBodyPart bodyPart) throws Exception { builder.append(new String(bodyPart.getBodyPartBytes())); return STATE.CONTINU } @Override public String onCompleted() throws Exception { // Will be invoked once the response has been fully read or a ResponseComplete exception // has been thrown. return builder.toString(); } @Override public void onThrowable(Throwable t) { } }); String bodyResponse = f.get(); Finally, you can also configure the AsyncHttpClient via it's AsyncHttpClientConfig object: AsyncHttpClientConfig cf = new AsyncHttpClientConfig.Builder().setProxyServer(new ProxyServer("127.0.0.1", 38080)).build(); AsyncHttpClient c = new AsyncHttpClient(cf); The library uses Java non blocking I/O for supporting asynchronous operations. The default asynchronous provider is build on top of Netty (http://www.jboss.org/netty), the Java NIO Client Server Socket Framework from JBoss, but the library exposes a configurable provider SPI which allows to easily plug in other frameworks. Keep up to date on the library development by joining the Asynchronous HTTP Client discussion group http://groups.google.com/group/asynchttpclient async-http-client-1.6.5/pom.xml000066400000000000000000000442241166553056000164230ustar00rootroot00000000000000 org.sonatype.oss oss-parent 5 4.0.0 com.ning async-http-client Asynchronous Http Client 1.6.5 jar Async Http Client library purpose is to allow Java applications to easily execute HTTP requests and asynchronously process the HTTP responses. http://github.com/sonatype/async-http-client scm:git:git@github.com:sonatype/async-http-client.git https://github.com/sonatype/async-http-client scm:git:git@github.com:sonatype/async-http-client.git jira https://issues.sonatype.org/browse/AHC 2.0.9 brianm Brian McCallister brianm@skife.org jfarcand Jeanfrancois Arcand jfarcand@apache.org thomd Thomas Dudziak tomdz@apache.org neotyk Hubert Iwaniuk Apache License 2.0 http://www.apache.org/licenses/LICENSE-2.0.html repo org.jboss.netty netty 3.2.5.Final javax.servlet servlet-api commons-logging commons-logging org.slf4j slf4j-api log4j log4j org.slf4j slf4j-api 1.6.2 ch.qos.logback logback-classic 0.9.26 test log4j log4j 1.2.13 test org.testng testng 5.8 test jdk15 org.eclipse.jetty jetty-server 7.1.4.v20100610 test org.eclipse.jetty jetty-servlet 7.1.4.v20100610 test org.eclipse.jetty jetty-servlets 7.1.4.v20100610 test org.eclipse.jetty jetty-security 7.1.4.v20100610 test org.apache.tomcat coyote 6.0.29 test org.apache.tomcat catalina 6.0.29 test servlet-api org.apache.tomcat commons-io commons-io 2.0.1 test commons-fileupload commons-fileupload 1.2.2 test commons-httpclient commons-httpclient 3.1 true commons-lang commons-lang 2.4 true commons-logging commons-logging 1.1.1 true org.apache.maven.wagon wagon-ssh-external 1.0-beta-6 install org.codehaus.mojo animal-sniffer-maven-plugin 1.6 org.codehaus.mojo.signature java15 1.0 check-java-1.5-compat process-classes check org.apache.felix maven-bundle-plugin 2.0.1 true META-INF $(replace;$(project.version);-SNAPSHOT;.$(tstamp;yyyyMMdd-HHmm)) Sonatype org.jboss.netty.*;resolution:=optional, org.apache.commons.httpclient;resolution:=optional, org.apache.commons.httpclient.*;resolution:=optional, * com.ning.http.*;version="$(replace;$(project.version);-SNAPSHOT;"")" osgi-bundle package bundle org.apache.maven.plugins maven-enforcer-plugin 1.0-beta-1 enforce-versions enforce 2.0.9 1.5 org.apache.maven.plugins maven-compiler-plugin 2.3.2 1.5 1.5 UTF-8 1024m org.apache.maven.plugins maven-resources-plugin 2.4.3 UTF-8 org.apache.maven.plugins maven-release-plugin 2.1 org.apache.maven.plugins maven-jar-plugin 2.3.1 test-jar org.apache.maven.plugins maven-source-plugin 2.1.2 attach-sources verify jar-no-fork org.apache.maven.plugins maven-javadoc-plugin 2.7 1.6 UTF-8 1g attach-javadocs verify jar org.apache.maven.plugins maven-shade-plugin 1.2.1 package shade true shaded commons-codec:commons-codec commons-lang:commons-lang commons-logging:commons-logging junit:junit log4j:log4j commons-httpclient:commons-httpclient org.codehaus.mojo clirr-maven-plugin 2.3 **/NettyAsyncHttpProvider$* **/AsyncHandler$STATE **/ProxyServer$Protocol **/Realm$AuthScheme **/SimpleAsyncHttpClient$ErrorDocumentBehaviour **/SpnegoEngine check-api-compat verify check-no-fork release-sign-artifacts performRelease true org.apache.maven.plugins maven-gpg-plugin sign-artifacts verify sign offline-testing org.apache.maven.plugins maven-surefire-plugin standalone online-testing org.apache.maven.plugins maven-surefire-plugin standalone, online sonatype-nexus-staging Sonatype Release https://oss.sonatype.org/service/local/staging/deploy/maven2 sonatype-nexus-snapshots sonatype-nexus-snapshots ${distMgmtSnapshotsUrl} https://oss.sonatype.org/content/repositories/snapshots async-http-client-1.6.5/src/000077500000000000000000000000001166553056000156675ustar00rootroot00000000000000async-http-client-1.6.5/src/main/000077500000000000000000000000001166553056000166135ustar00rootroot00000000000000async-http-client-1.6.5/src/main/java/000077500000000000000000000000001166553056000175345ustar00rootroot00000000000000async-http-client-1.6.5/src/main/java/com/000077500000000000000000000000001166553056000203125ustar00rootroot00000000000000async-http-client-1.6.5/src/main/java/com/ning/000077500000000000000000000000001166553056000212455ustar00rootroot00000000000000async-http-client-1.6.5/src/main/java/com/ning/http/000077500000000000000000000000001166553056000222245ustar00rootroot00000000000000async-http-client-1.6.5/src/main/java/com/ning/http/client/000077500000000000000000000000001166553056000235025ustar00rootroot00000000000000async-http-client-1.6.5/src/main/java/com/ning/http/client/AsyncCompletionHandler.java000066400000000000000000000077031166553056000307610ustar00rootroot00000000000000/* * Copyright 2010 Ning, Inc. * * Ning licenses this file to you 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. * */ package com.ning.http.client; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * An {@link AsyncHandler} augmented with an {@link #onCompleted(Response)} convenience method which gets called * when the {@link Response} processing is finished. This class also implement the {@link ProgressAsyncHandler} callback, * all doing nothing except returning {@link com.ning.http.client.AsyncHandler.STATE#CONTINUE} * * @param Type of the value that will be returned by the associated {@link java.util.concurrent.Future} */ public abstract class AsyncCompletionHandler implements AsyncHandler, ProgressAsyncHandler { private final Logger log = LoggerFactory.getLogger(AsyncCompletionHandlerBase.class); private final Response.ResponseBuilder builder = new Response.ResponseBuilder(); /** * {@inheritDoc} */ public STATE onBodyPartReceived(final HttpResponseBodyPart content) throws Exception { builder.accumulate(content); return STATE.CONTINUE; } /** * {@inheritDoc} */ public STATE onStatusReceived(final HttpResponseStatus status) throws Exception { builder.reset(); builder.accumulate(status); return STATE.CONTINUE; } /** * {@inheritDoc} */ public STATE onHeadersReceived(final HttpResponseHeaders headers) throws Exception { builder.accumulate(headers); return STATE.CONTINUE; } /** * {@inheritDoc} */ public final T onCompleted() throws Exception { return onCompleted(builder.build()); } /** * {@inheritDoc} */ public void onThrowable(Throwable t) { log.debug(t.getMessage(), t); } /** * Invoked once the HTTP response processing is finished. *

* * Gets always invoked as last callback method. * * @param response The {@link Response} * @return T Value that will be returned by the associated {@link java.util.concurrent.Future} * @throws Exception if something wrong happens */ abstract public T onCompleted(Response response) throws Exception; /** * Invoked when the content (a {@link java.io.File}, {@link String} or {@link java.io.FileInputStream} has been fully * written on the I/O socket. * * @return a {@link com.ning.http.client.AsyncHandler.STATE} telling to CONTINUE or ABORT the current processing. */ public STATE onHeaderWriteCompleted() { return STATE.CONTINUE; } /** * Invoked when the content (a {@link java.io.File}, {@link String} or {@link java.io.FileInputStream} has been fully * written on the I/O socket. * * @return a {@link com.ning.http.client.AsyncHandler.STATE} telling to CONTINUE or ABORT the current processing. */ public STATE onContentWriteCompleted() { return STATE.CONTINUE; } /** * Invoked when the I/O operation associated with the {@link Request} body as been progressed. * @param amount The amount of bytes to transfer. * @param current The amount of bytes transferred * @param total The total number of bytes transferred * @return a {@link com.ning.http.client.AsyncHandler.STATE} telling to CONTINUE or ABORT the current processing. */ public STATE onContentWriteProgress(long amount, long current, long total) { return STATE.CONTINUE; } } async-http-client-1.6.5/src/main/java/com/ning/http/client/AsyncCompletionHandlerBase.java000066400000000000000000000022251166553056000315460ustar00rootroot00000000000000/* * Copyright 2010 Ning, Inc. * * Ning licenses this file to you 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. * */ package com.ning.http.client; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Simple {@link AsyncHandler} of type {@link Response} */ public class AsyncCompletionHandlerBase extends AsyncCompletionHandler{ private final Logger log = LoggerFactory.getLogger(AsyncCompletionHandlerBase.class); @Override public Response onCompleted(Response response) throws Exception { return response; } /* @Override */ public void onThrowable(Throwable t) { log.debug(t.getMessage(), t); } } async-http-client-1.6.5/src/main/java/com/ning/http/client/AsyncHandler.java000066400000000000000000000076621166553056000267330ustar00rootroot00000000000000/* * Copyright 2010 Ning, Inc. * * Ning licenses this file to you 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. */ package com.ning.http.client; /** * An asynchronous handler or callback which gets invoked as soon as some data is available when * processing an asynchronous response.
* Callback methods get invoked in the following order: *

    *
  1. {@link #onStatusReceived(HttpResponseStatus)},
  2. *
  3. {@link #onHeadersReceived(HttpResponseHeaders)},
  4. *
  5. {@link #onBodyPartReceived(HttpResponseBodyPart)}, which could be invoked multiple times,
  6. *
  7. {@link #onCompleted()}, once the response has been fully read.
  8. *
* * Returning a {@link AsyncHandler.STATE#ABORT} from any of those callback methods will interrupt asynchronous response * processing, after that only {@link #onCompleted()} is going to be called. *

* * AsyncHandler aren't thread safe, hence you should avoid re-using the same instance when doing concurrent requests. * As an exmaple, the following may produce unexpected results: * {@code * AsyncHandler ah = new AsyncHandler() {....}; * AsyncHttpClient client = new AsyncHttpClient(); * client.prepareGet("http://...").execute(ah); * client.prepareGet("http://...").execute(ah); * } * It is recommended to create a new instance instead. * * @param Type of object returned by the {@link java.util.concurrent.Future#get} */ public interface AsyncHandler { public static enum STATE { /** * Stop the processing. */ ABORT, /** * Continue the processing */ CONTINUE, /** * Pause the current processing. */ PAUSE } /** * Invoked when an unexpected exception occurs during the processing of the response. The exception may have been * produced by implementation of onXXXReceived method invokation. * * @param t a {@link Throwable} */ void onThrowable(Throwable t); /** * Invoked as soon as some response body part are received. Could be invoked many times. * @param bodyPart response's body part. * @throws Exception if something wrong happens * @return a {@link STATE} telling to CONTINUE or ABORT the current processing. */ STATE onBodyPartReceived(HttpResponseBodyPart bodyPart) throws Exception; /** * Invoked as soon as the HTTP status line has been received * @param responseStatus the status code and test of the response * @throws Exception if something wrong happens * @return a {@link STATE} telling to CONTINUE or ABORT the current processing. */ STATE onStatusReceived(HttpResponseStatus responseStatus) throws Exception; /** * Invoked as soon as the HTTP headers has been received. Can potentially be invoked morethan once if a broken server * sent trailling headers. * @param headers the HTTP headers. * @throws Exception if something wrong happens * @return a {@link STATE} telling to CONTINUE or ABORT the current processing. */ STATE onHeadersReceived(HttpResponseHeaders headers) throws Exception; /** * Invoked once the HTTP response processing is finished. *

* * Gets always invoked as last callback method. * * @return T Value that will be returned by the associated {@link java.util.concurrent.Future} * @throws Exception if something wrong happens */ T onCompleted() throws Exception; } async-http-client-1.6.5/src/main/java/com/ning/http/client/AsyncHttpClient.java000077500000000000000000000505651166553056000274370ustar00rootroot00000000000000/* * Copyright 2010 Ning, Inc. * * Ning licenses this file to you 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. * */ package com.ning.http.client; import com.ning.http.client.Request.EntityWriter; import com.ning.http.client.filter.FilterContext; import com.ning.http.client.filter.FilterException; import com.ning.http.client.filter.RequestFilter; import com.ning.http.client.resumable.ResumableAsyncHandler; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.ning.http.client.providers.jdk.JDKAsyncHttpProvider; import java.io.IOException; import java.io.InputStream; import java.util.Collection; import java.util.Map; import java.util.concurrent.Future; import java.util.concurrent.atomic.AtomicBoolean; /** * This class support asynchronous and synchronous HTTP request. * * To execute synchronous HTTP request, you just need to do * {@code * AsyncHttpClient c = new AsyncHttpClient(); * Future f = c.prepareGet("http://www.ning.com/").execute(); * } * * The code above will block until the response is fully received. To execute asynchronous HTTP request, you * create an {@link AsyncHandler} or its abstract implementation, {@link com.ning.http.client.AsyncCompletionHandler} * * {@code * AsyncHttpClient c = new AsyncHttpClient(); * Future f = c.prepareGet("http://www.ning.com/").execute(new AsyncCompletionHandler() { * * @Override * public Response onCompleted(Response response) throws IOException { * // Do something * return response; * } * * @Override * public void onThrowable(Throwable t) { * } * }); * Response response = f.get(); * * // We are just interested to retrieve the status code. * Future f = c.prepareGet("http://www.ning.com/").execute(new AsyncCompletionHandler() { * * @Override * public Integer onCompleted(Response response) throws IOException { * // Do something * return response.getStatusCode(); * } * * @Override * public void onThrowable(Throwable t) { * } * }); * Integer statusCode = f.get(); * } * The {@link AsyncCompletionHandler#onCompleted(com.ning.http.client.Response)} will be invoked once the http response has been fully read, which include * the http headers and the response body. Note that the entire response will be buffered in memory. * * You can also have more control about the how the response is asynchronously processed by using a {@link AsyncHandler} * {@code * AsyncHttpClient c = new AsyncHttpClient(); * Future f = c.prepareGet("http://www.ning.com/").execute(new AsyncHandler() { * private StringBuilder builder = new StringBuilder(); * * @Override * public STATE onStatusReceived(HttpResponseStatus s) throws Exception { * // return STATE.CONTINUE or STATE.ABORT * return STATE.CONTINUE * } * * @Override * public STATE onHeadersReceived(HttpResponseHeaders bodyPart) throws Exception { * // return STATE.CONTINUE or STATE.ABORT * return STATE.CONTINUE * * } * @Override * * public STATE onBodyPartReceived(HttpResponseBodyPart bodyPart) throws Exception { * builder.append(new String(bodyPart)); * // return STATE.CONTINUE or STATE.ABORT * return STATE.CONTINUE * } * * @Override * public String onCompleted() throws Exception { * // Will be invoked once the response has been fully read or a ResponseComplete exception * // has been thrown. * return builder.toString(); * } * * @Override * public void onThrowable(Throwable t) { * } * }); * * String bodyResponse = f.get(); * } * From any {@link HttpContent} sub classes, you can asynchronously process the response status,headers and body and decide when to * stop the processing the response by throwing a new {link ResponseComplete} at any moment. * * This class can also be used without the need of {@link AsyncHandler}

* {@code * AsyncHttpClient c = new AsyncHttpClient(); * Future f = c.prepareGet(TARGET_URL).execute(); * Response r = f.get(); * } * * Finally, you can configure the AsyncHttpClient using an {@link AsyncHttpClientConfig} instance

* {@code * AsyncHttpClient c = new AsyncHttpClient(new AsyncHttpClientConfig.Builder().setRequestTimeoutInMs(...).build()); * Future f = c.prepareGet(TARGET_URL).execute(); * Response r = f.get(); * } * * An instance of this class will cache every HTTP 1.1 connections and close them when the {@link AsyncHttpClientConfig#getIdleConnectionTimeoutInMs()} * expires. This object can hold many persistent connections to different host. * */ public class AsyncHttpClient { private final static String DEFAULT_PROVIDER = "com.ning.http.client.providers.netty.NettyAsyncHttpProvider"; private final AsyncHttpProvider httpProvider; private final AsyncHttpClientConfig config; private final static Logger logger = LoggerFactory.getLogger(AsyncHttpClient.class); private final AtomicBoolean isClosed = new AtomicBoolean(false); /** * Default signature calculator to use for all requests constructed by this client instance. * * @since 1.1 */ protected SignatureCalculator signatureCalculator; /** * Create a new HTTP Asynchronous Client using the default {@link AsyncHttpClientConfig} configuration. The * default {@link AsyncHttpProvider} will be used ({@link com.ning.http.client.providers.netty.NettyAsyncHttpProvider} */ public AsyncHttpClient() { this(new AsyncHttpClientConfig.Builder().build()); } /** * Create a new HTTP Asynchronous Client using an implementation of {@link AsyncHttpProvider} and * the default {@link AsyncHttpClientConfig} configuration. * @param provider a {@link AsyncHttpProvider} */ public AsyncHttpClient(AsyncHttpProvider provider) { this(provider,new AsyncHttpClientConfig.Builder().build()); } /** * Create a new HTTP Asynchronous Client using a {@link AsyncHttpClientConfig} configuration and the * {@link #DEFAULT_PROVIDER} * @param config a {@link AsyncHttpClientConfig} */ public AsyncHttpClient(AsyncHttpClientConfig config) { this(loadDefaultProvider(DEFAULT_PROVIDER, config),config); } /** * Create a new HTTP Asynchronous Client using a {@link AsyncHttpClientConfig} configuration and * and a {@link AsyncHttpProvider}. * @param config a {@link AsyncHttpClientConfig} * @param httpProvider a {@link AsyncHttpProvider} */ public AsyncHttpClient(AsyncHttpProvider httpProvider, AsyncHttpClientConfig config) { this.config = config; this.httpProvider = httpProvider; } /** * Create a new HTTP Asynchronous Client using a {@link AsyncHttpClientConfig} configuration and * and a AsyncHttpProvider class' name. * @param config a {@link AsyncHttpClientConfig} * @param providerClass a {@link AsyncHttpProvider} */ public AsyncHttpClient(String providerClass, AsyncHttpClientConfig config) { this.config = new AsyncHttpClientConfig.Builder().build(); this.httpProvider = loadDefaultProvider(providerClass,config); } public class BoundRequestBuilder extends RequestBuilderBase { /** * Calculator used for calculating request signature for the request being * built, if any. */ protected SignatureCalculator signatureCalculator; /** * URL used as the base, not including possibly query parameters. Needed for * signature calculation */ protected String baseURL; private BoundRequestBuilder(String reqType) { super(BoundRequestBuilder.class, reqType); } private BoundRequestBuilder(Request prototype) { super(BoundRequestBuilder.class, prototype); } public ListenableFuture execute(AsyncHandler handler) throws IOException { return AsyncHttpClient.this.executeRequest(build(), handler); } public ListenableFuture execute() throws IOException { return AsyncHttpClient.this.executeRequest(build(), new AsyncCompletionHandlerBase()); } // Note: For now we keep the delegates in place even though they are not needed // since otherwise Clojure (and maybe other languages) won't be able to // access these methods - see Clojure tickets 126 and 259 @Override public BoundRequestBuilder addBodyPart(Part part) throws IllegalArgumentException { return super.addBodyPart(part); } @Override public BoundRequestBuilder addCookie(Cookie cookie) { return super.addCookie(cookie); } @Override public BoundRequestBuilder addHeader(String name, String value) { return super.addHeader(name, value); } @Override public BoundRequestBuilder addParameter(String key, String value) throws IllegalArgumentException { return super.addParameter(key, value); } @Override public BoundRequestBuilder addQueryParameter(String name, String value) { return super.addQueryParameter(name, value); } @Override public Request build() { /* Let's first calculate and inject signature, before finalizing actual build * (order does not matter with current implementation but may in future) */ if (signatureCalculator != null) { String url = baseURL; // Should not include query parameters, ensure: int i = url.indexOf('?'); if (i >= 0) { url = url.substring(0, i); } signatureCalculator.calculateAndAddSignature(baseURL, request, this); } return super.build(); } @Override public BoundRequestBuilder setBody(byte[] data) throws IllegalArgumentException { return super.setBody(data); } @Override public BoundRequestBuilder setBody(EntityWriter dataWriter, long length) throws IllegalArgumentException { return super.setBody(dataWriter, length); } @Override public BoundRequestBuilder setBody(EntityWriter dataWriter) { return super.setBody(dataWriter); } @Override public BoundRequestBuilder setBody(InputStream stream) throws IllegalArgumentException { return super.setBody(stream); } @Override public BoundRequestBuilder setBody(String data) throws IllegalArgumentException { return super.setBody(data); } @Override public BoundRequestBuilder setHeader(String name, String value) { return super.setHeader(name, value); } @Override public BoundRequestBuilder setHeaders(FluentCaseInsensitiveStringsMap headers) { return super.setHeaders(headers); } @Override public BoundRequestBuilder setHeaders(Map> headers) { return super.setHeaders(headers); } @Override public BoundRequestBuilder setParameters(Map> parameters) throws IllegalArgumentException { return super.setParameters(parameters); } @Override public BoundRequestBuilder setParameters(FluentStringsMap parameters) throws IllegalArgumentException { return super.setParameters(parameters); } @Override public BoundRequestBuilder setUrl(String url) { baseURL = url; return super.setUrl(url); } @Override public BoundRequestBuilder setVirtualHost(String virtualHost) { return super.setVirtualHost(virtualHost); } public BoundRequestBuilder setSignatureCalculator(SignatureCalculator signatureCalculator) { this.signatureCalculator = signatureCalculator; return this; } } /** * Return the asynchronous {@link com.ning.http.client.AsyncHttpProvider} * @return an {@link com.ning.http.client.AsyncHttpProvider} */ public AsyncHttpProvider getProvider() { return httpProvider; } /** * Close the underlying connections. */ public void close() { httpProvider.close(); isClosed.set(true); } @Override protected void finalize() throws Throwable { try { if (!isClosed.get()) { logger.warn("AsyncHttpClient.close() hasn't been invoked, which may produce file descriptor leaks"); } } finally { super.finalize(); } } /** * Return true if closed * @return true if closed */ public boolean isClosed(){ return isClosed.get(); } /** * Return the {@link com.ning.http.client.AsyncHttpClientConfig} * @return {@link com.ning.http.client.AsyncHttpClientConfig} */ public AsyncHttpClientConfig getConfig(){ return config; } /** * Set default signature calculator to use for requests build by this client instance */ public AsyncHttpClient setSignatureCalculator(SignatureCalculator signatureCalculator) { this.signatureCalculator = signatureCalculator; return this; } /** * Prepare an HTTP client GET request. * @param url A well formed URL. * @return {@link RequestBuilder} */ public BoundRequestBuilder prepareGet(String url) { return requestBuilder("GET", url); } /** * Prepare an HTTP client CONNECT request. * @param url A well formed URL. * @return {@link RequestBuilder} */ public BoundRequestBuilder prepareConnect(String url) { return requestBuilder("CONNECT", url); } /** * Prepare an HTTP client OPTIONS request. * @param url A well formed URL. * @return {@link RequestBuilder} */ public BoundRequestBuilder prepareOptions(String url) { return requestBuilder("OPTIONS", url); } /** * Prepare an HTTP client HEAD request. * @param url A well formed URL. * @return {@link RequestBuilder} */ public BoundRequestBuilder prepareHead(String url) { return requestBuilder("HEAD", url); } /** * Prepare an HTTP client POST request. * @param url A well formed URL. * @return {@link RequestBuilder} */ public BoundRequestBuilder preparePost(String url) { return requestBuilder("POST", url); } /** * Prepare an HTTP client PUT request. * @param url A well formed URL. * @return {@link RequestBuilder} */ public BoundRequestBuilder preparePut(String url) { return requestBuilder("PUT", url); } /** * Prepare an HTTP client DELETE request. * @param url A well formed URL. * @return {@link RequestBuilder} */ public BoundRequestBuilder prepareDelete(String url) { return requestBuilder("DELETE", url); } /** * Construct a {@link RequestBuilder} using a {@link Request} * @param request a {@link Request} * @return {@link RequestBuilder} */ public BoundRequestBuilder prepareRequest(Request request) { return requestBuilder(request); } /** * Execute an HTTP request. * @param request {@link Request} * @param handler an instance of {@link AsyncHandler} * @param Type of the value that will be returned by the associated {@link java.util.concurrent.Future} * @return a {@link Future} of type T * @throws IOException */ public ListenableFuture executeRequest(Request request, AsyncHandler handler) throws IOException { FilterContext fc = new FilterContext.FilterContextBuilder().asyncHandler(handler).request(request).build(); fc = preProcessRequest(fc); return httpProvider.execute(fc.getRequest(), fc.getAsyncHandler()); } /** * Execute an HTTP request. * @param request {@link Request} * @return a {@link Future} of type Response * @throws IOException */ public ListenableFuture executeRequest(Request request) throws IOException { FilterContext fc = new FilterContext.FilterContextBuilder().asyncHandler(new AsyncCompletionHandlerBase()).request(request).build(); fc = preProcessRequest(fc); return httpProvider.execute(fc.getRequest(), fc.getAsyncHandler()); } /** * Configure and execute the associated {@link RequestFilter}. This class may decorate the {@link Request} and {@link AsyncHandler} * * @param fc {@link FilterContext} * @return {@link FilterContext} */ private FilterContext preProcessRequest(FilterContext fc) throws IOException { for (RequestFilter asyncFilter : config.getRequestFilters()) { try { fc = asyncFilter.filter(fc); if (fc == null) { throw new NullPointerException("FilterContext is null"); } } catch (FilterException e) { IOException ex = new IOException(); ex.initCause(e); throw ex; } } Request request = fc.getRequest(); if (ResumableAsyncHandler.class.isAssignableFrom(fc.getAsyncHandler().getClass())) { request = ResumableAsyncHandler.class.cast(fc.getAsyncHandler()).adjustRequestRange(request); } if (request.getRangeOffset() != 0) { RequestBuilder builder = new RequestBuilder(request); builder.setHeader("Range", "bytes=" + request.getRangeOffset() + "-"); request = builder.build(); } fc = new FilterContext.FilterContextBuilder(fc).request(request).build(); return fc; } @SuppressWarnings("unchecked") private final static AsyncHttpProvider loadDefaultProvider(String className, AsyncHttpClientConfig config){ try { Class providerClass = (Class) Thread.currentThread() .getContextClassLoader().loadClass(className); return providerClass.getDeclaredConstructor( new Class[]{AsyncHttpClientConfig.class}).newInstance(new Object[]{config}); } catch (Throwable t){ // Let's try with another classloader try { Class providerClass = (Class) AsyncHttpClient.class.getClassLoader().loadClass(className); return providerClass.getDeclaredConstructor( new Class[]{AsyncHttpClientConfig.class}).newInstance(new Object[]{config}); } catch (Throwable t2) { } if (logger.isDebugEnabled()) { logger.debug("Default provider not found {}. Using the {}", DEFAULT_PROVIDER, JDKAsyncHttpProvider.class.getName()); } return new JDKAsyncHttpProvider(config); } } protected BoundRequestBuilder requestBuilder(String reqType, String url) { return new BoundRequestBuilder(reqType).setUrl(url).setSignatureCalculator(signatureCalculator); } protected BoundRequestBuilder requestBuilder(Request prototype) { return new BoundRequestBuilder(prototype).setSignatureCalculator(signatureCalculator); } } async-http-client-1.6.5/src/main/java/com/ning/http/client/AsyncHttpClientConfig.java000066400000000000000000001117351166553056000305570ustar00rootroot00000000000000/* * Copyright 2010 Ning, Inc. * * Ning licenses this file to you 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. */ package com.ning.http.client; import com.ning.http.client.filter.IOExceptionFilter; import com.ning.http.client.filter.RequestFilter; import com.ning.http.client.filter.ResponseFilter; import com.ning.http.util.ProxyUtils; import javax.net.ssl.HostnameVerifier; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLEngine; import javax.net.ssl.SSLSession; import java.security.GeneralSecurityException; import java.util.Collections; import java.util.LinkedList; import java.util.List; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ThreadFactory; /** * Configuration class to use with a {@link AsyncHttpClient}. System property can be also used to configure this * object default behavior by doing: *

* -Dcom.ning.http.client.AsyncHttpClientConfig.nameOfTheProperty * ex: *

* -Dcom.ning.http.client.AsyncHttpClientConfig.defaultMaxTotalConnections * -Dcom.ning.http.client.AsyncHttpClientConfig.defaultMaxTotalConnections * -Dcom.ning.http.client.AsyncHttpClientConfig.defaultMaxConnectionsPerHost * -Dcom.ning.http.client.AsyncHttpClientConfig.defaultConnectionTimeoutInMS * -Dcom.ning.http.client.AsyncHttpClientConfig.defaultIdleConnectionInPoolTimeoutInMS * -Dcom.ning.http.client.AsyncHttpClientConfig.defaultRequestTimeoutInMS * -Dcom.ning.http.client.AsyncHttpClientConfig.defaultRedirectsEnabled * -Dcom.ning.http.client.AsyncHttpClientConfig.defaultMaxRedirects */ public class AsyncHttpClientConfig { protected final static String ASYNC_CLIENT = AsyncHttpClientConfig.class.getName() + "."; protected int maxTotalConnections; protected int maxConnectionPerHost; protected int connectionTimeOutInMs; protected int idleConnectionInPoolTimeoutInMs; protected int requestTimeoutInMs; protected boolean redirectEnabled; protected int maxDefaultRedirects; protected boolean compressionEnabled; protected String userAgent; protected boolean allowPoolingConnection; protected ScheduledExecutorService reaper; protected ExecutorService applicationThreadPool; protected ProxyServer proxyServer; protected SSLContext sslContext; protected SSLEngineFactory sslEngineFactory; protected AsyncHttpProviderConfig providerConfig; protected ConnectionsPool connectionsPool; protected Realm realm; protected List requestFilters; protected List responseFilters; protected List ioExceptionFilters; protected int requestCompressionLevel; protected int maxRequestRetry; protected boolean allowSslConnectionPool; protected boolean useRawUrl; protected boolean removeQueryParamOnRedirect; protected HostnameVerifier hostnameVerifier; protected int ioThreadMultiplier; protected AsyncHttpClientConfig(){ } private AsyncHttpClientConfig(int maxTotalConnections, int maxConnectionPerHost, int connectionTimeOutInMs, int idleConnectionInPoolTimeoutInMs, int requestTimeoutInMs, boolean redirectEnabled, int maxDefaultRedirects, boolean compressionEnabled, String userAgent, boolean keepAlive, ScheduledExecutorService reaper, ExecutorService applicationThreadPool, ProxyServer proxyServer, SSLContext sslContext, SSLEngineFactory sslEngineFactory, AsyncHttpProviderConfig providerConfig, ConnectionsPool connectionsPool, Realm realm, List requestFilters, List responseFilters, List ioExceptionFilters, int requestCompressionLevel, int maxRequestRetry, boolean allowSslConnectionCaching, boolean useRawUrl, boolean removeQueryParamOnRedirect, HostnameVerifier hostnameVerifier, int ioThreadMultiplier) { this.maxTotalConnections = maxTotalConnections; this.maxConnectionPerHost = maxConnectionPerHost; this.connectionTimeOutInMs = connectionTimeOutInMs; this.idleConnectionInPoolTimeoutInMs = idleConnectionInPoolTimeoutInMs; this.requestTimeoutInMs = requestTimeoutInMs; this.redirectEnabled = redirectEnabled; this.maxDefaultRedirects = maxDefaultRedirects; this.compressionEnabled = compressionEnabled; this.userAgent = userAgent; this.allowPoolingConnection = keepAlive; this.sslContext = sslContext; this.sslEngineFactory = sslEngineFactory; this.providerConfig = providerConfig; this.connectionsPool = connectionsPool; this.realm = realm; this.requestFilters = requestFilters; this.responseFilters = responseFilters; this.ioExceptionFilters = ioExceptionFilters; this.requestCompressionLevel = requestCompressionLevel; this.maxRequestRetry = maxRequestRetry; this.reaper = reaper; this.allowSslConnectionPool = allowSslConnectionCaching; this.removeQueryParamOnRedirect = removeQueryParamOnRedirect; this.hostnameVerifier = hostnameVerifier; this.ioThreadMultiplier = ioThreadMultiplier; if (applicationThreadPool == null) { this.applicationThreadPool = Executors.newCachedThreadPool(); } else { this.applicationThreadPool = applicationThreadPool; } this.proxyServer = proxyServer; this.useRawUrl = useRawUrl; } /** * A {@link ScheduledExecutorService} used to expire idle connections. * * @return {@link ScheduledExecutorService} */ public ScheduledExecutorService reaper() { return reaper; } /** * Return the maximum number of connections an {@link com.ning.http.client.AsyncHttpClient} can handle. * * @return the maximum number of connections an {@link com.ning.http.client.AsyncHttpClient} can handle. */ public int getMaxTotalConnections() { return maxTotalConnections; } /** * Return the maximum number of connections per hosts an {@link com.ning.http.client.AsyncHttpClient} can handle. * * @return the maximum number of connections per host an {@link com.ning.http.client.AsyncHttpClient} can handle. */ public int getMaxConnectionPerHost() { return maxConnectionPerHost; } /** * Return the maximum time in millisecond an {@link com.ning.http.client.AsyncHttpClient} can wait when connecting to a remote host * * @return the maximum time in millisecond an {@link com.ning.http.client.AsyncHttpClient} can wait when connecting to a remote host */ public int getConnectionTimeoutInMs() { return connectionTimeOutInMs; } /** * Return the maximum time in millisecond an {@link com.ning.http.client.AsyncHttpClient} can stay idle. * * @return the maximum time in millisecond an {@link com.ning.http.client.AsyncHttpClient} can stay idle. * @deprecated Please use {@link com.ning.http.client.AsyncHttpClientConfig#getIdleConnectionInPoolTimeoutInMs()} */ public int getIdleConnectionTimeoutInMs() { return idleConnectionInPoolTimeoutInMs; } /** * Return the maximum time in millisecond an {@link com.ning.http.client.AsyncHttpClient} will keep connection * in pool. * * @return the maximum time in millisecond an {@link com.ning.http.client.AsyncHttpClient} will keep connection * in pool. */ public int getIdleConnectionInPoolTimeoutInMs() { return idleConnectionInPoolTimeoutInMs; } /** * Return the maximum time in millisecond an {@link com.ning.http.client.AsyncHttpClient} wait for a response * * @return the maximum time in millisecond an {@link com.ning.http.client.AsyncHttpClient} wait for a response */ public int getRequestTimeoutInMs() { return requestTimeoutInMs; } /** * Is HTTP redirect enabled * * @return true if enabled. */ public boolean isRedirectEnabled() { return redirectEnabled; } /** * Get the maximum number of HTTP redirect * * @return the maximum number of HTTP redirect */ public int getMaxRedirects() { return maxDefaultRedirects; } /** * Is the {@link ConnectionsPool} support enabled. * * @return true if keep-alive is enabled */ public boolean getAllowPoolingConnection() { return allowPoolingConnection; } /** * Is the {@link ConnectionsPool} support enabled. * * @return true if keep-alive is enabled * @deprecated - Use {@link AsyncHttpClientConfig#getAllowPoolingConnection()} */ public boolean getKeepAlive() { return allowPoolingConnection; } /** * Return the USER_AGENT header value * * @return the USER_AGENT header value */ public String getUserAgent() { return userAgent; } /** * Is HTTP compression enabled. * * @return true if compression is enabled */ public boolean isCompressionEnabled() { return compressionEnabled; } /** * Return the {@link java.util.concurrent.ExecutorService} an {@link AsyncHttpClient} use for handling * asynchronous response. * * @return the {@link java.util.concurrent.ExecutorService} an {@link AsyncHttpClient} use for handling * asynchronous response. */ public ExecutorService executorService() { return applicationThreadPool; } /** * An instance of {@link com.ning.http.client.ProxyServer} used by an {@link AsyncHttpClient} * * @return instance of {@link com.ning.http.client.ProxyServer} */ public ProxyServer getProxyServer() { return proxyServer; } /** * Return an instance of {@link SSLContext} used for SSL connection. * * @return an instance of {@link SSLContext} used for SSL connection. */ public SSLContext getSSLContext() { return sslContext; } /** * Return an instance of {@link ConnectionsPool} * * @return an instance of {@link ConnectionsPool} */ public ConnectionsPool getConnectionsPool() { return connectionsPool; } /** * Return an instance of {@link SSLEngineFactory} used for SSL connection. * * @return an instance of {@link SSLEngineFactory} used for SSL connection. */ public SSLEngineFactory getSSLEngineFactory() { if (sslEngineFactory == null) { return new SSLEngineFactory() { public SSLEngine newSSLEngine() { if (sslContext != null) { SSLEngine sslEngine = sslContext.createSSLEngine(); sslEngine.setUseClientMode(true); return sslEngine; } else { return null; } } }; } return sslEngineFactory; } /** * Return the {@link com.ning.http.client.AsyncHttpProviderConfig} * * @return the {@link com.ning.http.client.AsyncHttpProviderConfig} */ public AsyncHttpProviderConfig getAsyncHttpProviderConfig() { return providerConfig; } /** * Return the current {@link Realm}} * * @return the current {@link Realm}} */ public Realm getRealm() { return realm; } /** * Return the list of {@link RequestFilter} * * @return Unmodifiable list of {@link ResponseFilter} */ public List getRequestFilters() { return Collections.unmodifiableList(requestFilters); } /** * Return the list of {@link ResponseFilter} * * @return Unmodifiable list of {@link ResponseFilter} */ public List getResponseFilters() { return Collections.unmodifiableList(responseFilters); } /** * Return the list of {@link java.io.IOException} * * @return Unmodifiable list of {@link java.io.IOException} */ public List getIOExceptionFilters() { return Collections.unmodifiableList(ioExceptionFilters); } /** * Return the compression level, or -1 if no compression is used. * * @return the compression level, or -1 if no compression is use */ public int getRequestCompressionLevel() { return requestCompressionLevel; } /** * Return the number of time the library will retry when an {@link java.io.IOException} is throw by the remote server * * @return the number of time the library will retry when an {@link java.io.IOException} is throw by the remote server */ public int getMaxRequestRetry() { return maxRequestRetry; } /** * Return true is SSL connection polling is enabled. Default is true. * * @return true is enabled. */ public boolean isSslConnectionPoolEnabled() { return allowSslConnectionPool; } /** * @return the useRawUrl */ public boolean isUseRawUrl() { return useRawUrl; } /** * Return true if the query parameters will be stripped from the request when a redirect is requested. * @return true if the query parameters will be stripped from the request when a redirect is requested. */ public boolean isRemoveQueryParamOnRedirect() { return removeQueryParamOnRedirect; } /** * Return true if one of the {@link java.util.concurrent.ExecutorService} has been shutdown. * @return true if one of the {@link java.util.concurrent.ExecutorService} has been shutdown. */ public boolean isClosed(){ return applicationThreadPool.isShutdown() || reaper.isShutdown(); } /** * Return the {@link HostnameVerifier} * @return the {@link HostnameVerifier} */ public HostnameVerifier getHostnameVerifier() { return hostnameVerifier; } /*** * * @return number to multiply by availableProcessors() that will determine # of NioWorkers to use */ public int getIoThreadMultiplier() { return ioThreadMultiplier; } /** * Builder for an {@link AsyncHttpClient} */ public static class Builder { private int defaultMaxTotalConnections = Integer.getInteger(ASYNC_CLIENT + "defaultMaxTotalConnections", -1); private int defaultMaxConnectionPerHost = Integer.getInteger(ASYNC_CLIENT + "defaultMaxConnectionsPerHost", -1); private int defaultConnectionTimeOutInMs = Integer.getInteger(ASYNC_CLIENT + "defaultConnectionTimeoutInMS", 60 * 1000); private int defaultIdleConnectionInPoolTimeoutInMs = Integer.getInteger(ASYNC_CLIENT + "defaultIdleConnectionInPoolTimeoutInMS", 60 * 1000); private int defaultRequestTimeoutInMs = Integer.getInteger(ASYNC_CLIENT + "defaultRequestTimeoutInMS", 60 * 1000); private boolean redirectEnabled = Boolean.getBoolean(ASYNC_CLIENT + "defaultRedirectsEnabled"); private int maxDefaultRedirects = Integer.getInteger(ASYNC_CLIENT + "defaultMaxRedirects", 5); private boolean compressionEnabled = Boolean.getBoolean(ASYNC_CLIENT + "compressionEnabled"); private String userAgent = System.getProperty(ASYNC_CLIENT + "userAgent", "NING/1.0"); private boolean useProxyProperties = Boolean.getBoolean(ASYNC_CLIENT + "useProxyProperties"); private boolean allowPoolingConnection = true; private ScheduledExecutorService reaper = Executors.newScheduledThreadPool(Runtime.getRuntime().availableProcessors(), new ThreadFactory() { public Thread newThread(Runnable r) { Thread t = new Thread(r, "AsyncHttpClient-Reaper"); t.setDaemon(true); return t; } }); private ExecutorService applicationThreadPool = Executors.newCachedThreadPool(new ThreadFactory() { public Thread newThread(Runnable r) { Thread t = new Thread(r, "AsyncHttpClient-Callback"); t.setDaemon(true); return t; } }); private ProxyServer proxyServer = null; private SSLContext sslContext; private SSLEngineFactory sslEngineFactory; private AsyncHttpProviderConfig providerConfig; private ConnectionsPool connectionsPool; private Realm realm; private int requestCompressionLevel = -1; private int maxRequestRetry = 5; private final List requestFilters = new LinkedList(); private final List responseFilters = new LinkedList(); private final List ioExceptionFilters = new LinkedList(); private boolean allowSslConnectionPool = true; private boolean useRawUrl = false; private boolean removeQueryParamOnRedirect = true; private HostnameVerifier hostnameVerifier = new HostnameVerifier() { public boolean verify( String s, SSLSession sslSession ) { return true; } }; private int ioThreadMultiplier = 2; public Builder() { } /** * Set the maximum number of connections an {@link com.ning.http.client.AsyncHttpClient} can handle. * * @param defaultMaxTotalConnections the maximum number of connections an {@link com.ning.http.client.AsyncHttpClient} can handle. * @return a {@link Builder} */ public Builder setMaximumConnectionsTotal(int defaultMaxTotalConnections) { this.defaultMaxTotalConnections = defaultMaxTotalConnections; return this; } /** * Set the maximum number of connections per hosts an {@link com.ning.http.client.AsyncHttpClient} can handle. * * @param defaultMaxConnectionPerHost the maximum number of connections per host an {@link com.ning.http.client.AsyncHttpClient} can handle. * @return a {@link Builder} */ public Builder setMaximumConnectionsPerHost(int defaultMaxConnectionPerHost) { this.defaultMaxConnectionPerHost = defaultMaxConnectionPerHost; return this; } /** * Set the maximum time in millisecond an {@link com.ning.http.client.AsyncHttpClient} can wait when connecting to a remote host * * @param defaultConnectionTimeOutInMs the maximum time in millisecond an {@link com.ning.http.client.AsyncHttpClient} can wait when connecting to a remote host * @return a {@link Builder} */ public Builder setConnectionTimeoutInMs(int defaultConnectionTimeOutInMs) { this.defaultConnectionTimeOutInMs = defaultConnectionTimeOutInMs; return this; } /** * Set the maximum time in millisecond an {@link com.ning.http.client.AsyncHttpClient} can stay idle. * * @param defaultIdleConnectionTimeoutInMs * the maximum time in millisecond an {@link com.ning.http.client.AsyncHttpClient} can stay idle. * @return a {@link Builder} * @deprecated Please use {@link Builder#setIdleConnectionInPoolTimeoutInMs(int)} */ public Builder setIdleConnectionTimeoutInMs(int defaultIdleConnectionTimeoutInMs) { this.defaultIdleConnectionInPoolTimeoutInMs = defaultIdleConnectionTimeoutInMs; return this; } /** * Set the maximum time in millisecond an {@link com.ning.http.client.AsyncHttpClient} will keep connection * idle in pool. * * @param defaultIdleConnectionInPoolTimeoutInMs * the maximum time in millisecond an {@link com.ning.http.client.AsyncHttpClient} will keep connection * idle in pool. * @return a {@link Builder} */ public Builder setIdleConnectionInPoolTimeoutInMs(int defaultIdleConnectionInPoolTimeoutInMs) { this.defaultIdleConnectionInPoolTimeoutInMs = defaultIdleConnectionInPoolTimeoutInMs; return this; } /** * Set the maximum time in millisecond an {@link com.ning.http.client.AsyncHttpClient} wait for a response * * @param defaultRequestTimeoutInMs the maximum time in millisecond an {@link com.ning.http.client.AsyncHttpClient} wait for a response * @return a {@link Builder} */ public Builder setRequestTimeoutInMs(int defaultRequestTimeoutInMs) { this.defaultRequestTimeoutInMs = defaultRequestTimeoutInMs; return this; } /** * Set to true to enable HTTP redirect * * @param redirectEnabled true if enabled. * @return a {@link Builder} */ public Builder setFollowRedirects(boolean redirectEnabled) { this.redirectEnabled = redirectEnabled; return this; } /** * Set the maximum number of HTTP redirect * * @param maxDefaultRedirects the maximum number of HTTP redirect * @return a {@link Builder} */ public Builder setMaximumNumberOfRedirects(int maxDefaultRedirects) { this.maxDefaultRedirects = maxDefaultRedirects; return this; } /** * Enable HTTP compression. * * @param compressionEnabled true if compression is enabled * @return a {@link Builder} */ public Builder setCompressionEnabled(boolean compressionEnabled) { this.compressionEnabled = compressionEnabled; return this; } /** * Set the USER_AGENT header value * * @param userAgent the USER_AGENT header value * @return a {@link Builder} */ public Builder setUserAgent(String userAgent) { this.userAgent = userAgent; return this; } /** * Set true if connection can be pooled by a {@link ConnectionsPool}. Default is true. * * @param allowPoolingConnection true if connection can be pooled by a {@link ConnectionsPool} * @return a {@link Builder} */ public Builder setAllowPoolingConnection(boolean allowPoolingConnection) { this.allowPoolingConnection = allowPoolingConnection; return this; } /** * Set true if connection can be pooled by a {@link ConnectionsPool}. Default is true. * * @param allowPoolingConnection true if connection can be pooled by a {@link ConnectionsPool} * @return a {@link Builder} * @deprecated - Use {@link com.ning.http.client.AsyncHttpClientConfig.Builder#setAllowPoolingConnection(boolean)} */ public Builder setKeepAlive(boolean allowPoolingConnection) { this.allowPoolingConnection = allowPoolingConnection; return this; } /** * Set the{@link ScheduledExecutorService} used to expire idle connections. * * @param reaper the{@link ScheduledExecutorService} used to expire idle connections. * @return a {@link Builder} */ public Builder setScheduledExecutorService(ScheduledExecutorService reaper) { if (this.reaper != null) this.reaper.shutdown(); this.reaper = reaper; return this; } /** * Set the {@link java.util.concurrent.ExecutorService} an {@link AsyncHttpClient} use for handling * asynchronous response. * * @param applicationThreadPool the {@link java.util.concurrent.ExecutorService} an {@link AsyncHttpClient} use for handling * asynchronous response. * @return a {@link Builder} */ public Builder setExecutorService(ExecutorService applicationThreadPool) { if (this.applicationThreadPool != null) this.applicationThreadPool.shutdown(); this.applicationThreadPool = applicationThreadPool; return this; } /** * Set an instance of {@link com.ning.http.client.ProxyServer} used by an {@link AsyncHttpClient} * * @param proxyServer instance of {@link com.ning.http.client.ProxyServer} * @return a {@link Builder} */ public Builder setProxyServer(ProxyServer proxyServer) { this.proxyServer = proxyServer; return this; } /** * Set the {@link SSLEngineFactory} for secure connection. * * @param sslEngineFactory the {@link SSLEngineFactory} for secure connection * @return a {@link Builder} */ public Builder setSSLEngineFactory(SSLEngineFactory sslEngineFactory) { this.sslEngineFactory = sslEngineFactory; return this; } /** * Set the {@link SSLContext} for secure connection. * * @param sslContext the {@link SSLContext} for secure connection * @return a {@link Builder} */ public Builder setSSLContext(final SSLContext sslContext) { this.sslEngineFactory = new SSLEngineFactory() { public SSLEngine newSSLEngine() throws GeneralSecurityException { SSLEngine sslEngine = sslContext.createSSLEngine(); sslEngine.setUseClientMode(true); return sslEngine; } }; this.sslContext = sslContext; return this; } /** * Set the {@link com.ning.http.client.AsyncHttpProviderConfig} * * @param providerConfig the {@link com.ning.http.client.AsyncHttpProviderConfig} * @return a {@link Builder} */ public Builder setAsyncHttpClientProviderConfig(AsyncHttpProviderConfig providerConfig) { this.providerConfig = providerConfig; return this; } /** * Set the {@link ConnectionsPool} * * @param connectionsPool the {@link ConnectionsPool} * @return a {@link Builder} */ public Builder setConnectionsPool(ConnectionsPool connectionsPool) { this.connectionsPool = connectionsPool; return this; } /** * Set the {@link Realm} that will be used for all requests. * * @param realm the {@link Realm} * @return a {@link Builder} */ public Builder setRealm(Realm realm) { this.realm = realm; return this; } /** * Add an {@link com.ning.http.client.filter.RequestFilter} that will be invoked before {@link com.ning.http.client.AsyncHttpClient#executeRequest(Request)} * * @param requestFilter {@link com.ning.http.client.filter.RequestFilter} * @return this */ public Builder addRequestFilter(RequestFilter requestFilter) { requestFilters.add(requestFilter); return this; } /** * Remove an {@link com.ning.http.client.filter.RequestFilter} that will be invoked before {@link com.ning.http.client.AsyncHttpClient#executeRequest(Request)} * * @param requestFilter {@link com.ning.http.client.filter.RequestFilter} * @return this */ public Builder removeRequestFilter(RequestFilter requestFilter) { requestFilters.remove(requestFilter); return this; } /** * Add an {@link com.ning.http.client.filter.ResponseFilter} that will be invoked as soon as the response is * received, and before {@link AsyncHandler#onStatusReceived(HttpResponseStatus)}. * * @param responseFilter an {@link com.ning.http.client.filter.ResponseFilter} * @return this */ public Builder addResponseFilter(ResponseFilter responseFilter) { responseFilters.add(responseFilter); return this; } /** * Remove an {@link com.ning.http.client.filter.ResponseFilter} that will be invoked as soon as the response is * received, and before {@link AsyncHandler#onStatusReceived(HttpResponseStatus)}. * * @param responseFilter an {@link com.ning.http.client.filter.ResponseFilter} * @return this */ public Builder removeResponseFilter(ResponseFilter responseFilter) { responseFilters.remove(responseFilter); return this; } /** * Add an {@link com.ning.http.client.filter.IOExceptionFilter} that will be invoked when an {@link java.io.IOException} * occurs during the download/upload operations. * * @param ioExceptionFilter an {@link com.ning.http.client.filter.ResponseFilter} * @return this */ public Builder addIOExceptionFilter(IOExceptionFilter ioExceptionFilter) { ioExceptionFilters.add(ioExceptionFilter); return this; } /** * Remove an {@link com.ning.http.client.filter.IOExceptionFilter} tthat will be invoked when an {@link java.io.IOException} * occurs during the download/upload operations. * * @param ioExceptionFilter an {@link com.ning.http.client.filter.ResponseFilter} * @return this */ public Builder removeIOExceptionFilter(IOExceptionFilter ioExceptionFilter) { ioExceptionFilters.remove(ioExceptionFilter); return this; } /** * Return the compression level, or -1 if no compression is used. * * @return the compression level, or -1 if no compression is use */ public int getRequestCompressionLevel() { return requestCompressionLevel; } /** * Set the compression level, or -1 if no compression is used. * * @param requestCompressionLevel compression level, or -1 if no compression is use * @return this */ public Builder setRequestCompressionLevel(int requestCompressionLevel) { this.requestCompressionLevel = requestCompressionLevel; return this; } /** * Set the number of time a request will be retried when an {@link java.io.IOException} occurs because of a Network exception. * * @param maxRequestRetry the number of time a request will be retried * @return this */ public Builder setMaxRequestRetry(int maxRequestRetry) { this.maxRequestRetry = maxRequestRetry; return this; } /** * Return true is if connections pooling is enabled. * * @param allowSslConnectionPool true if enabled * @return this */ public Builder setAllowSslConnectionPool(boolean allowSslConnectionPool) { this.allowSslConnectionPool = allowSslConnectionPool; return this; } /** * Allows use unescaped URLs in requests * useful for retrieving data from broken sites * * @param useRawUrl * @return this */ public Builder setUseRawUrl(boolean useRawUrl) { this.useRawUrl = useRawUrl; return this; } /** * Set to false if you don't want the query parameters removed when a redirect occurs. * @param removeQueryParamOnRedirect * @return this */ public Builder setRemoveQueryParamsOnRedirect(boolean removeQueryParamOnRedirect) { this.removeQueryParamOnRedirect = removeQueryParamOnRedirect; return this; } /** * Sets whether AHC should use the default http.proxy* system properties * to obtain proxy information. *

* If useProxyProperties is set to true but {@link #setProxyServer(ProxyServer)} was used * to explicitly set a proxy server, the latter is preferred. *

* See http://download.oracle.com/javase/1.4.2/docs/guide/net/properties.html */ public Builder setUseProxyProperties(boolean useProxyProperties) { this.useProxyProperties = useProxyProperties; return this; } public Builder setIOThreadMultiplier(int multiplier){ this.ioThreadMultiplier = multiplier; return this; } /** * Set the {@link HostnameVerifier} * @param hostnameVerifier {@link HostnameVerifier} * @return this */ public Builder setHostnameVerifier(HostnameVerifier hostnameVerifier){ this.hostnameVerifier = hostnameVerifier; return this; } /** * Create a config builder with values taken from the given prototype configuration. * * @param prototype the configuration to use as a prototype. */ public Builder(AsyncHttpClientConfig prototype) { allowPoolingConnection = prototype.getAllowPoolingConnection(); providerConfig = prototype.getAsyncHttpProviderConfig(); connectionsPool = prototype.getConnectionsPool(); defaultConnectionTimeOutInMs = prototype.getConnectionTimeoutInMs(); defaultIdleConnectionInPoolTimeoutInMs = prototype.getIdleConnectionInPoolTimeoutInMs(); allowPoolingConnection = prototype.getKeepAlive(); defaultMaxConnectionPerHost = prototype.getMaxConnectionPerHost(); maxDefaultRedirects = prototype.getMaxRedirects(); defaultMaxTotalConnections = prototype.getMaxTotalConnections(); proxyServer = prototype.getProxyServer(); realm = prototype.getRealm(); defaultRequestTimeoutInMs = prototype.getRequestTimeoutInMs(); sslContext = prototype.getSSLContext(); sslEngineFactory = prototype.getSSLEngineFactory(); userAgent = prototype.getUserAgent(); requestFilters.clear(); responseFilters.clear(); requestFilters.addAll(prototype.getRequestFilters()); responseFilters.addAll(prototype.getResponseFilters()); useRawUrl = prototype.isUseRawUrl(); ioThreadMultiplier = prototype.getIoThreadMultiplier(); } /** * Build an {@link AsyncHttpClientConfig} * * @return an {@link AsyncHttpClientConfig} */ public AsyncHttpClientConfig build() { if ( applicationThreadPool.isShutdown() ) { throw new IllegalStateException( "ExecutorServices closed" ); } if (proxyServer == null && useProxyProperties) { proxyServer = ProxyUtils.createProxy(System.getProperties()); } return new AsyncHttpClientConfig(defaultMaxTotalConnections, defaultMaxConnectionPerHost, defaultConnectionTimeOutInMs, defaultIdleConnectionInPoolTimeoutInMs, defaultRequestTimeoutInMs, redirectEnabled, maxDefaultRedirects, compressionEnabled, userAgent, allowPoolingConnection, reaper, applicationThreadPool, proxyServer, sslContext, sslEngineFactory, providerConfig, connectionsPool, realm, requestFilters, responseFilters, ioExceptionFilters, requestCompressionLevel, maxRequestRetry, allowSslConnectionPool, useRawUrl, removeQueryParamOnRedirect, hostnameVerifier, ioThreadMultiplier); } } } async-http-client-1.6.5/src/main/java/com/ning/http/client/AsyncHttpClientConfigBean.java000066400000000000000000000211521166553056000313360ustar00rootroot00000000000000/* * Copyright (c) 2010-2011 Sonatype, Inc. All rights reserved. * * This program is licensed to you under the Apache License Version 2.0, * and you may not use this file except in compliance with the Apache License Version 2.0. * You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0. * * Unless required by applicable law or agreed to in writing, * software distributed under the Apache License Version 2.0 is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. */ package com.ning.http.client; import com.ning.http.client.filter.IOExceptionFilter; import com.ning.http.client.filter.RequestFilter; import com.ning.http.client.filter.ResponseFilter; import com.ning.http.util.ProxyUtils; import javax.net.ssl.HostnameVerifier; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLSession; import java.util.LinkedList; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ThreadFactory; /** * Simple JavaBean version of {@link AsyncHttpClientConfig} */ public class AsyncHttpClientConfigBean extends AsyncHttpClientConfig { public AsyncHttpClientConfigBean() { configureExecutors(); configureDefaults(); configureFilters(); } void configureFilters() { requestFilters = new LinkedList(); responseFilters = new LinkedList(); ioExceptionFilters = new LinkedList(); } void configureDefaults() { maxTotalConnections = Integer.getInteger(ASYNC_CLIENT + "defaultMaxTotalConnections", -1); maxConnectionPerHost = Integer.getInteger(ASYNC_CLIENT + "defaultMaxConnectionsPerHost", -1); connectionTimeOutInMs = Integer.getInteger(ASYNC_CLIENT + "defaultConnectionTimeoutInMS", 60 * 1000); idleConnectionInPoolTimeoutInMs = Integer.getInteger(ASYNC_CLIENT + "defaultIdleConnectionInPoolTimeoutInMS", 60 * 1000); requestTimeoutInMs = Integer.getInteger(ASYNC_CLIENT + "defaultRequestTimeoutInMS", 60 * 1000); redirectEnabled = Boolean.getBoolean(ASYNC_CLIENT + "defaultRedirectsEnabled"); maxDefaultRedirects = Integer.getInteger(ASYNC_CLIENT + "defaultMaxRedirects", 5); compressionEnabled = Boolean.getBoolean(ASYNC_CLIENT + "compressionEnabled"); userAgent = System.getProperty(ASYNC_CLIENT + "userAgent", "NING/1.0"); boolean useProxyProperties = Boolean.getBoolean(ASYNC_CLIENT + "useProxyProperties"); if (useProxyProperties) { proxyServer = ProxyUtils.createProxy(System.getProperties()); } allowPoolingConnection = true; requestCompressionLevel = -1; maxRequestRetry = 5; allowSslConnectionPool = true; useRawUrl = false; removeQueryParamOnRedirect = true; hostnameVerifier = new HostnameVerifier() { public boolean verify(String s, SSLSession sslSession) { return true; } }; } void configureExecutors() { reaper = Executors.newScheduledThreadPool(Runtime.getRuntime().availableProcessors(), new ThreadFactory() { public Thread newThread(Runnable r) { Thread t = new Thread(r, "AsyncHttpClient-Reaper"); t.setDaemon(true); return t; } }); applicationThreadPool = Executors.newCachedThreadPool(new ThreadFactory() { public Thread newThread(Runnable r) { Thread t = new Thread(r, "AsyncHttpClient-Callback"); t.setDaemon(true); return t; } }); } public AsyncHttpClientConfigBean setMaxTotalConnections(int maxTotalConnections) { this.maxTotalConnections = maxTotalConnections; return this; } public AsyncHttpClientConfigBean setMaxConnectionPerHost(int maxConnectionPerHost) { this.maxConnectionPerHost = maxConnectionPerHost; return this; } public AsyncHttpClientConfigBean setConnectionTimeOutInMs(int connectionTimeOutInMs) { this.connectionTimeOutInMs = connectionTimeOutInMs; return this; } public AsyncHttpClientConfigBean setIdleConnectionInPoolTimeoutInMs(int idleConnectionInPoolTimeoutInMs) { this.idleConnectionInPoolTimeoutInMs = idleConnectionInPoolTimeoutInMs; return this; } public AsyncHttpClientConfigBean setRequestTimeoutInMs(int requestTimeoutInMs) { this.requestTimeoutInMs = requestTimeoutInMs; return this; } public AsyncHttpClientConfigBean setRedirectEnabled(boolean redirectEnabled) { this.redirectEnabled = redirectEnabled; return this; } public AsyncHttpClientConfigBean setMaxDefaultRedirects(int maxDefaultRedirects) { this.maxDefaultRedirects = maxDefaultRedirects; return this; } public AsyncHttpClientConfigBean setCompressionEnabled(boolean compressionEnabled) { this.compressionEnabled = compressionEnabled; return this; } public AsyncHttpClientConfigBean setUserAgent(String userAgent) { this.userAgent = userAgent; return this; } public AsyncHttpClientConfigBean setAllowPoolingConnection(boolean allowPoolingConnection) { this.allowPoolingConnection = allowPoolingConnection; return this; } public AsyncHttpClientConfigBean setReaper(ScheduledExecutorService reaper) { if (this.reaper != null) { this.reaper.shutdownNow(); } this.reaper = reaper; return this; } public AsyncHttpClientConfigBean setApplicationThreadPool(ExecutorService applicationThreadPool) { if (this.applicationThreadPool != null) { this.applicationThreadPool.shutdownNow(); } this.applicationThreadPool = applicationThreadPool; return this; } public AsyncHttpClientConfigBean setProxyServer(ProxyServer proxyServer) { this.proxyServer = proxyServer; return this; } public AsyncHttpClientConfigBean setSslContext(SSLContext sslContext) { this.sslContext = sslContext; return this; } public AsyncHttpClientConfigBean setSslEngineFactory(SSLEngineFactory sslEngineFactory) { this.sslEngineFactory = sslEngineFactory; return this; } public AsyncHttpClientConfigBean setProviderConfig(AsyncHttpProviderConfig providerConfig) { this.providerConfig = providerConfig; return this; } public AsyncHttpClientConfigBean setConnectionsPool(ConnectionsPool connectionsPool) { this.connectionsPool = connectionsPool; return this; } public AsyncHttpClientConfigBean setRealm(Realm realm) { this.realm = realm; return this; } public AsyncHttpClientConfigBean addRequestFilter(RequestFilter requestFilter) { requestFilters.add(requestFilter); return this; } public AsyncHttpClientConfigBean addResponseFilters(ResponseFilter responseFilter) { responseFilters.add(responseFilter); return this; } public AsyncHttpClientConfigBean addIoExceptionFilters(IOExceptionFilter ioExceptionFilter) { ioExceptionFilters.add(ioExceptionFilter); return this; } public AsyncHttpClientConfigBean setRequestCompressionLevel(int requestCompressionLevel) { this.requestCompressionLevel = requestCompressionLevel; return this; } public AsyncHttpClientConfigBean setMaxRequestRetry(int maxRequestRetry) { this.maxRequestRetry = maxRequestRetry; return this; } public AsyncHttpClientConfigBean setAllowSslConnectionPool(boolean allowSslConnectionPool) { this.allowSslConnectionPool = allowSslConnectionPool; return this; } public AsyncHttpClientConfigBean setUseRawUrl(boolean useRawUrl) { this.useRawUrl = useRawUrl; return this; } public AsyncHttpClientConfigBean setRemoveQueryParamOnRedirect(boolean removeQueryParamOnRedirect) { this.removeQueryParamOnRedirect = removeQueryParamOnRedirect; return this; } public AsyncHttpClientConfigBean setHostnameVerifier(HostnameVerifier hostnameVerifier) { this.hostnameVerifier = hostnameVerifier; return this; } public AsyncHttpClientConfigBean setIoThreadMultiplier(int ioThreadMultiplier) { this.ioThreadMultiplier = ioThreadMultiplier; return this; } } async-http-client-1.6.5/src/main/java/com/ning/http/client/AsyncHttpProvider.java000066400000000000000000000034621166553056000300020ustar00rootroot00000000000000/* * Copyright 2010 Ning, Inc. * * Ning licenses this file to you 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. */ package com.ning.http.client; import java.io.IOException; import java.util.Collection; /** * Interface to be used when implementing custom asynchronous I/O HTTP client. * By default, the {@link com.ning.http.client.providers.netty.NettyAsyncHttpProvider} is used. */ public interface AsyncHttpProvider { /** * Execute the request and invoke the {@link AsyncHandler} when the response arrive. * * @param handler an instance of {@link AsyncHandler} * @return a {@link ListenableFuture} of Type T. * @throws IOException */ public ListenableFuture execute(Request request, AsyncHandler handler) throws IOException; /** * Close the current underlying TCP/HTTP connection. */ public void close(); /** * Prepare a {@link Response} * @param status {@link HttpResponseStatus} * @param headers {@link HttpResponseHeaders} * @param bodyParts list of {@link HttpResponseBodyPart} * @return a {@link Response} */ public Response prepareResponse(HttpResponseStatus status, HttpResponseHeaders headers, Collection bodyParts); } async-http-client-1.6.5/src/main/java/com/ning/http/client/AsyncHttpProviderConfig.java000066400000000000000000000036651166553056000311350ustar00rootroot00000000000000/* * Copyright (c) 2010-2011 Sonatype, Inc. All rights reserved. * * This program is licensed to you under the Apache License Version 2.0, * and you may not use this file except in compliance with the Apache License Version 2.0. * You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0. * * Unless required by applicable law or agreed to in writing, * software distributed under the Apache License Version 2.0 is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. */ package com.ning.http.client; import java.util.Map; import java.util.Set; /** * {@link com.ning.http.client.AsyncHttpProvider} proprietary configurable properties. Note that properties are * AsyncHttpProvider dependent, so make sure you consult the AsyncHttpProvider's documentation * about what is supported and what's not. */ public interface AsyncHttpProviderConfig { /** * Add a property that will be used when the AsyncHttpClient initialize its {@link com.ning.http.client.AsyncHttpProvider} * * @param name the name of the property * @param value the value of the property * @return this instance of AsyncHttpProviderConfig */ public AsyncHttpProviderConfig addProperty(U name, V value); /** * Return the value associated with the property's name * * @param name * @return this instance of AsyncHttpProviderConfig */ public V getProperty(U name); /** * Remove the value associated with the property's name * * @param name * @return true if removed */ public V removeProperty(U name); /** * Return the curent entry set. * * @return a the curent entry set. */ public Set> propertiesSet(); } async-http-client-1.6.5/src/main/java/com/ning/http/client/Body.java000066400000000000000000000030211166553056000252360ustar00rootroot00000000000000 /* * Copyright (c) 2010-2011 Sonatype, Inc. All rights reserved. * * This program is licensed to you under the Apache License Version 2.0, * and you may not use this file except in compliance with the Apache License Version 2.0. * You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0. * * Unless required by applicable law or agreed to in writing, * software distributed under the Apache License Version 2.0 is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. */ package com.ning.http.client; import java.io.IOException; import java.nio.ByteBuffer; /** * A request body. */ public interface Body { /** * Gets the length of the body. * * @return The length of the body in bytes, or negative if unknown. */ long getContentLength(); /** * Reads the next chunk of bytes from the body. * * @param buffer The buffer to store the chunk in, must not be {@code null}. * @return The non-negative number of bytes actually read or {@code -1} if the body has been read completely. * @throws IOException If the chunk could not be read. */ long read(ByteBuffer buffer) throws IOException; /** * Releases any resources associated with this body. * * @throws IOException */ void close() throws IOException; } async-http-client-1.6.5/src/main/java/com/ning/http/client/BodyConsumer.java000066400000000000000000000024411166553056000267570ustar00rootroot00000000000000/* * Copyright (c) 2010-2011 Sonatype, Inc. All rights reserved. * * This program is licensed to you under the Apache License Version 2.0, * and you may not use this file except in compliance with the Apache License Version 2.0. * You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0. * * Unless required by applicable law or agreed to in writing, * software distributed under the Apache License Version 2.0 is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. */ package com.ning.http.client; import java.io.IOException; import java.nio.ByteBuffer; /** * A simple API to be used with the {@link SimpleAsyncHttpClient} class in order to process response's bytes. */ public interface BodyConsumer { /** * Consume the received bytes. * * @param byteBuffer a {@link ByteBuffer} represntation of the response's chunk. * @throws IOException */ void consume(ByteBuffer byteBuffer) throws IOException; /** * Invoked when all the response bytes has been processed. * @throws IOException */ void close() throws IOException; } async-http-client-1.6.5/src/main/java/com/ning/http/client/BodyDeferringAsyncHandler.java000066400000000000000000000237051166553056000313730ustar00rootroot00000000000000/* * Copyright (c) 2010-2011 Sonatype, Inc. All rights reserved. * * This program is licensed to you under the Apache License Version 2.0, * and you may not use this file except in compliance with the Apache License Version 2.0. * You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0. * * Unless required by applicable law or agreed to in writing, * software distributed under the Apache License Version 2.0 is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. */ package com.ning.http.client; import java.io.FilterInputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutionException; import java.util.concurrent.Future; import java.util.concurrent.Semaphore; import com.ning.http.client.Response.ResponseBuilder; /** * An AsyncHandler that returns Response (without body, so status code and * headers only) as fast as possible for inspection, but leaves you the option * to defer body consumption. *

* This class introduces new call: getResponse(), that blocks caller thread as * long as headers are received, and return Response as soon as possible, but * still pouring response body into supplied output stream. This handler is * meant for situations when the "recommended" way (using * client.prepareGet("http://foo.com/aResource").execute().get() * would not work for you, since a potentially large response body is about to * be GETted, but you need headers first, or you don't know yet (depending on * some logic, maybe coming from headers) where to save the body, or you just * want to leave body stream to some other component to consume it. *

* All these above means that this AsyncHandler needs a bit of different * handling than "recommended" way. Some examples: * *

 *     FileOutputStream fos = ...
 *     BodyDeferringAsyncHandler bdah = new BodyDeferringAsyncHandler(fos);
 *     // client executes async
 *     Future<Response> fr = client.prepareGet("http://foo.com/aresource").execute(
 * 	bdah);
 *     // main thread will block here until headers are available
 *     Response response = bdah.getResponse();
 *     // you can continue examine headers while actual body download happens
 *     // in separate thread
 *     // ...
 *     // finally "join" the download
 *     fr.get();
 * 
* *
 *     PipedOutputStream pout = new PipedOutputStream();
 *     BodyDeferringAsyncHandler bdah = new BodyDeferringAsyncHandler(pout);
 *     // client executes async
 *     Future<Response> fr = client.prepareGet("http://foo.com/aresource").execute(bdah);
 *     // main thread will block here until headers are available
 *     Response response = bdah.getResponse();
 *     if (response.getStatusCode() == 200) {
 *      InputStream pin = new BodyDeferringInputStream(fr,new PipedInputStream(pout));
 *      // consume InputStream
 *      ...
 *     } else {
 *      // handle unexpected response status code
 *      ...
 *     }
 * 
* */ public class BodyDeferringAsyncHandler implements AsyncHandler { private final ResponseBuilder responseBuilder = new ResponseBuilder(); private final CountDownLatch headersArrived = new CountDownLatch(1); private final OutputStream output; private volatile boolean responseSet; private volatile Response response; private volatile Throwable throwable; private final Semaphore semaphore = new Semaphore(1); public BodyDeferringAsyncHandler(final OutputStream os) { this.output = os; this.responseSet = false; } public void onThrowable(Throwable t) { this.throwable = t; // Counting down to handle error cases too. // In "premature exceptions" cases, the onBodyPartReceived() and // onCompleted() // methods will never be invoked, leaving caller of getResponse() method // blocked forever. try { semaphore.acquire(); } catch (InterruptedException e) { // Ignore } finally { headersArrived.countDown(); semaphore.release(); } try { closeOut(); } catch (IOException e) { // ignore } } public STATE onStatusReceived(HttpResponseStatus responseStatus) throws Exception { responseBuilder.reset(); responseBuilder.accumulate(responseStatus); return STATE.CONTINUE; } public STATE onHeadersReceived(HttpResponseHeaders headers) throws Exception { responseBuilder.accumulate(headers); return STATE.CONTINUE; } public STATE onBodyPartReceived(HttpResponseBodyPart bodyPart) throws Exception { // body arrived, flush headers if (!responseSet) { response = responseBuilder.build(); responseSet = true; headersArrived.countDown(); } bodyPart.writeTo(output); return STATE.CONTINUE; } protected void closeOut() throws IOException { try { output.flush(); } finally { output.close(); } } public Response onCompleted() throws IOException { // Counting down to handle error cases too. // In "normal" cases, latch is already at 0 here // But in other cases, for example when because of some error // onBodyPartReceived() is never called, the caller // of getResponse() would remain blocked infinitely. // By contract, onCompleted() is always invoked, even in case of errors headersArrived.countDown(); closeOut(); try { semaphore.acquire(); if (throwable != null) { IOException ioe = new IOException(throwable.getMessage()); ioe.initCause(throwable); throw ioe; } else { // sending out current response return responseBuilder.build(); } } catch (InterruptedException e) { return null; } finally { semaphore.release(); } } /** * This method -- unlike Future.get() -- will block only as long, * as headers arrive. This is useful for large transfers, to examine headers * ASAP, and defer body streaming to it's fine destination and prevent * unneeded bandwidth consumption. The response here will contain the very * 1st response from server, so status code and headers, but it might be * incomplete in case of broken servers sending trailing headers. In that * case, the "usual" Future.get() method will return complete * headers, but multiple invocations of getResponse() will always return the * 1st cached, probably incomplete one. Note: the response returned by this * method will contain everything except the response body itself, * so invoking any method like Response.getResponseBodyXXX() will result in * error! Also, please not that this method might return null * in case of some errors. * * @return a {@link Response} * @throws InterruptedException */ public Response getResponse() throws InterruptedException, IOException { // block here as long as headers arrive headersArrived.await(); try { semaphore.acquire(); if (throwable != null) { IOException ioe = new IOException(throwable.getMessage()); ioe.initCause(throwable); throw ioe; } else { return response; } } finally { semaphore.release(); } } // == /** * A simple helper class that is used to perform automatic "join" for async * download and the error checking of the Future of the request. */ public static class BodyDeferringInputStream extends FilterInputStream { private final Future future; private final BodyDeferringAsyncHandler bdah; public BodyDeferringInputStream(final Future future, final BodyDeferringAsyncHandler bdah, final InputStream in) { super(in); this.future = future; this.bdah = bdah; } /** * Closes the input stream, and "joins" (wait for complete execution * together with potential exception thrown) of the async request. */ public void close() throws IOException { // close super.close(); // "join" async request try { getLastResponse(); } catch (Exception e) { IOException ioe = new IOException(e.getMessage()); ioe.initCause(e); throw ioe; } } /** * Delegates to {@link BodyDeferringAsyncHandler#getResponse()}. Will * blocks as long as headers arrives only. Might return * null. See * {@link BodyDeferringAsyncHandler#getResponse()} method for details. * * @return a {@link Response} * @throws InterruptedException */ public Response getAsapResponse() throws InterruptedException, IOException { return bdah.getResponse(); } /** * Delegates to Future#get() method. Will block * as long as complete response arrives. * * @return a {@link Response} * @throws InterruptedException * @throws ExecutionException */ public Response getLastResponse() throws InterruptedException, ExecutionException { return future.get(); } } }async-http-client-1.6.5/src/main/java/com/ning/http/client/BodyGenerator.java000066400000000000000000000024701166553056000271140ustar00rootroot00000000000000/* * Copyright (c) 2010-2011 Sonatype, Inc. All rights reserved. * * This program is licensed to you under the Apache License Version 2.0, * and you may not use this file except in compliance with the Apache License Version 2.0. * You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0. * * Unless required by applicable law or agreed to in writing, * software distributed under the Apache License Version 2.0 is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. */ package com.ning.http.client; import java.io.IOException; /** * Creates a request body. */ public interface BodyGenerator { /** * Creates a new instance of the request body to be read. While each invocation of this method is supposed to create * a fresh instance of the body, the actual contents of all these body instances is the same. For example, the body * needs to be resend after an authentication challenge of a redirect. * * @return The request body, never {@code null}. * @throws IOException If the body could not be created. */ Body createBody() throws IOException; } async-http-client-1.6.5/src/main/java/com/ning/http/client/ByteArrayPart.java000066400000000000000000000026011166553056000270750ustar00rootroot00000000000000/* * Copyright 2010 Ning, Inc. * * Ning licenses this file to you 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. * */ package com.ning.http.client; public class ByteArrayPart implements Part { private String name; private String fileName; private byte[] data; private String mimeType; private String charSet; public ByteArrayPart(String name, String fileName, byte[] data, String mimeType, String charSet) { this.name = name; this.fileName = fileName; this.data = data; this.mimeType = mimeType; this.charSet = charSet; } public String getName() { return name; } public String getFileName() { return fileName; } public byte[] getData() { return data; } public String getMimeType() { return mimeType; } public String getCharSet() { return charSet; } } async-http-client-1.6.5/src/main/java/com/ning/http/client/ConnectionsPool.java000066400000000000000000000036421166553056000274660ustar00rootroot00000000000000/* * Copyright 2010 Ning, Inc. * * Ning licenses this file to you 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. * */ package com.ning.http.client; /** * An interface used by an {@link AsyncHttpProvider} for caching http connections. */ public interface ConnectionsPool { /** * Add a connection tpo the pool * @param uri a uri used to retrieve the cached connection * @param connection an I/O connection * @return true if added. */ public boolean offer(U uri, V connection); /** * Remove the connection associated with the uri. * @param uri the uri used when invoking addConnection * @return the connection associated with the uri */ public V poll(U uri); /** * Remove all connections from the cache. A connection might have been associated with several uri. * @param connection a connection * @return the true if the connection has been removed */ public boolean removeAll(V connection); /** * Return true if a connection can be cached. A implementation can decide based on some rules to allow caching * Calling this method is equivalent of checking the returned value of {@link ConnectionsPool#offer(Object, Object)} * @return true if a connection can be cached. */ public boolean canCacheConnection(); /** * Destroy all connections that has been cached by this instance. */ public void destroy(); } async-http-client-1.6.5/src/main/java/com/ning/http/client/Cookie.java000066400000000000000000000073471166553056000255710ustar00rootroot00000000000000/* * Copyright 2010 Ning, Inc. * * Ning licenses this file to you 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. * */ package com.ning.http.client; import java.util.Collections; import java.util.Set; import java.util.TreeSet; public class Cookie { private final String domain; private final String name; private final String value; private final String path; private final int maxAge; private final boolean secure; private final int version; private Set ports = Collections.emptySet(); private Set unmodifiablePorts = ports; public Cookie(String domain, String name, String value, String path, int maxAge, boolean secure) { this.domain = domain; this.name = name; this.value = value; this.path = path; this.maxAge = maxAge; this.secure = secure; this.version = 1; } public Cookie(String domain, String name, String value, String path, int maxAge, boolean secure, int version) { this.domain = domain; this.name = name; this.value = value; this.path = path; this.maxAge = maxAge; this.secure = secure; this.version = version; } public String getDomain() { return domain; } public String getName() { return name == null ? "" : name; } public String getValue() { return value == null ? "" : value; } public String getPath() { return path; } public int getMaxAge() { return maxAge; } public boolean isSecure() { return secure; } public int getVersion() { return version; } public Set getPorts() { if (unmodifiablePorts == null) { unmodifiablePorts = Collections.unmodifiableSet(ports); } return unmodifiablePorts; } public void setPorts(int... ports) { if (ports == null) { throw new NullPointerException("ports"); } int[] portsCopy = ports.clone(); if (portsCopy.length == 0) { unmodifiablePorts = this.ports = Collections.emptySet(); } else { Set newPorts = new TreeSet(); for (int p: portsCopy) { if (p <= 0 || p > 65535) { throw new IllegalArgumentException("port out of range: " + p); } newPorts.add(Integer.valueOf(p)); } this.ports = newPorts; unmodifiablePorts = null; } } public void setPorts(Iterable ports) { Set newPorts = new TreeSet(); for (int p: ports) { if (p <= 0 || p > 65535) { throw new IllegalArgumentException("port out of range: " + p); } newPorts.add(Integer.valueOf(p)); } if (newPorts.isEmpty()) { unmodifiablePorts = this.ports = Collections.emptySet(); } else { this.ports = newPorts; unmodifiablePorts = null; } } @Override public String toString() { return String.format("Cookie: domain=%s, name=%s, value=%s, path=%s, maxAge=%d, secure=%s", domain, name, value, path, maxAge, secure); } } async-http-client-1.6.5/src/main/java/com/ning/http/client/FilePart.java000066400000000000000000000024261166553056000260570ustar00rootroot00000000000000/* * Copyright 2010 Ning, Inc. * * Ning licenses this file to you 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. * */ package com.ning.http.client; import java.io.File; /** * A file multipart part. */ public class FilePart implements Part { private String name; private File file; private String mimeType; private String charSet; public FilePart(String name, File file, String mimeType, String charSet) { this.name = name; this.file = file; this.mimeType = mimeType; this.charSet = charSet; } public String getName() { return name; } public File getFile() { return file; } public String getMimeType() { return mimeType; } public String getCharSet() { return charSet; } }async-http-client-1.6.5/src/main/java/com/ning/http/client/FluentCaseInsensitiveStringsMap.java000066400000000000000000000347601166553056000326410ustar00rootroot00000000000000/* * Copyright 2010 Ning, Inc. * * Ning licenses this file to you 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. * */ package com.ning.http.client; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Set; /** * An implementation of a {@code String -> List} map that adds a fluent interface, i.e. methods that * return this instance. This class differs from {@link FluentStringsMap} in that keys are treated in an * case-insensitive matter, i.e. case of the key doesn't matter when retrieving values or changing the map. * However, the map preserves the key case (of the first insert or replace) and returns the keys in their * original case in the appropriate methods (e.g. {@link FluentCaseInsensitiveStringsMap#keySet()}). */ public class FluentCaseInsensitiveStringsMap implements Map>, Iterable>> { private final Map> values = new LinkedHashMap>(); private final Map keyLookup = new LinkedHashMap(); public FluentCaseInsensitiveStringsMap() { } public FluentCaseInsensitiveStringsMap(FluentCaseInsensitiveStringsMap src) { if (src != null) { for (Map.Entry> header : src) { add(header.getKey(), header.getValue()); } } } public FluentCaseInsensitiveStringsMap(Map> src) { if (src != null) { for (Map.Entry> header : src.entrySet()) { add(header.getKey(), header.getValue()); } } } /** * Adds the specified values and returns this object. * * @param key The key * @param values The value(s); if null then this method has no effect. Use the empty string to * generate an empty value * @return This object */ public FluentCaseInsensitiveStringsMap add(String key, String... values) { if ((values != null) && (values.length > 0)) { add(key, Arrays.asList(values)); } return this; } private List fetchValues( Collection values ) { List result = null; if (values != null) { for (String value : values) { if (value == null) { value = ""; } if (result == null) { // lazy initialization result = new ArrayList(); } result.add(value); } } return result; } /** * Adds the specified values and returns this object. * * @param key The key * @param values The value(s); if null then this method has no effect. Use an empty collection * to generate an empty value * @return This object */ public FluentCaseInsensitiveStringsMap add(String key, Collection values) { if (key != null) { List nonNullValues = fetchValues( values ); if (nonNullValues != null) { String lcKey = key.toLowerCase(); String realKey = keyLookup.get(lcKey); List curValues = null; if (realKey == null) { realKey = key; keyLookup.put(lcKey, key); } else { curValues = this.values.get(realKey); } if (curValues == null) { curValues = new ArrayList(); this.values.put(realKey, curValues); } curValues.addAll(nonNullValues); } } return this; } /** * Adds all key-values pairs from the given object to this object and returns this object. * * @param src The source object * @return This object */ public FluentCaseInsensitiveStringsMap addAll(FluentCaseInsensitiveStringsMap src) { if (src != null) { for (Map.Entry> header : src) { add(header.getKey(), header.getValue()); } } return this; } /** * Adds all key-values pairs from the given map to this object and returns this object. * * @param src The source map * @return This object */ public FluentCaseInsensitiveStringsMap addAll(Map> src) { if (src != null) { for (Map.Entry> header : src.entrySet()) { add(header.getKey(), header.getValue()); } } return this; } /** * Replaces the values for the given key with the given values. * * @param key The key * @param values The new values * @return This object */ public FluentCaseInsensitiveStringsMap replace(final String key, final String... values) { return replace(key, Arrays.asList(values)); } /** * Replaces the values for the given key with the given values. * * @param key The key * @param values The new values * @return This object */ public FluentCaseInsensitiveStringsMap replace(final String key, final Collection values) { if (key != null) { List nonNullValues = fetchValues( values ); String lcKkey = key.toLowerCase(); String realKey = keyLookup.get(lcKkey); if (nonNullValues == null) { keyLookup.remove(lcKkey); if (realKey != null) { this.values.remove(realKey); } } else { if (!key.equals(realKey)) { keyLookup.put(lcKkey, key); this.values.remove(realKey); } this.values.put(key, nonNullValues); } } return this; } /** * Replace the values for all keys from the given map that are also present in this object, with the values from the given map. * All key-values from the given object that are not present in this object, will be added to it. * * @param src The source object * @return This object */ public FluentCaseInsensitiveStringsMap replaceAll(FluentCaseInsensitiveStringsMap src) { if (src != null) { for (Map.Entry> header : src) { replace(header.getKey(), header.getValue()); } } return this; } /** * Replace the values for all keys from the given map that are also present in this object, with the values from the given map. * All key-values from the given object that are not present in this object, will be added to it. * * @param src The source map * @return This object */ public FluentCaseInsensitiveStringsMap replaceAll(Map> src) { if (src != null) { for (Map.Entry> header : src.entrySet()) { replace(header.getKey(), header.getValue()); } } return this; } /** * {@inheritDoc} */ /* @Override */ public List put(String key, List value) { if (key == null) { throw new NullPointerException("Null keys are not allowed"); } List oldValue = get(key); replace(key, value); return oldValue; } /** * {@inheritDoc} */ /* @Override */ public void putAll(Map> values) { replaceAll(values); } /** * Removes the values for the given key if present and returns this object. * * @param key The key * @return This object */ public FluentCaseInsensitiveStringsMap delete(String key) { if (key != null) { String lcKey = key.toLowerCase(); String realKey = keyLookup.remove(lcKey); if (realKey != null) { values.remove(realKey); } } return this; } /** * Removes the values for the given keys if present and returns this object. * * @param keys The keys * @return This object */ public FluentCaseInsensitiveStringsMap deleteAll(String... keys) { if (keys != null) { for (String key : keys) { remove(key); } } return this; } /** * Removes the values for the given keys if present and returns this object. * * @param keys The keys * @return This object */ public FluentCaseInsensitiveStringsMap deleteAll(Collection keys) { if (keys != null) { for (String key : keys) { remove(key); } } return this; } /** * {@inheritDoc} */ /* @Override */ public List remove(Object key) { if (key == null) { return null; } else { List oldValues = get(key.toString()); delete(key.toString()); return oldValues; } } /** * {@inheritDoc} */ /* @Override */ public void clear() { keyLookup.clear(); values.clear(); } /** * {@inheritDoc} */ /* @Override */ public Iterator>> iterator() { return Collections.unmodifiableSet(values.entrySet()).iterator(); } /** * {@inheritDoc} */ /* @Override */ public Set keySet() { return new LinkedHashSet(keyLookup.values()); } /** * {@inheritDoc} */ /* @Override */ public Set>> entrySet() { return values.entrySet(); } /** * {@inheritDoc} */ /* @Override */ public int size() { return values.size(); } /** * {@inheritDoc} */ /* @Override */ public boolean isEmpty() { return values.isEmpty(); } /** * {@inheritDoc} */ /* @Override */ public boolean containsKey(Object key) { return key == null ? false : keyLookup.containsKey(key.toString().toLowerCase()); } /** * {@inheritDoc} */ /* @Override */ public boolean containsValue(Object value) { return values.containsValue(value); } /** * Returns the value for the given key. If there are multiple values for this key, * then only the first one will be returned. * * @param key The key * @return The first value */ public String getFirstValue(String key) { List values = get(key); if (values == null) { return null; } else if (values.isEmpty()) { return ""; } else { return values.get(0); } } /** * Returns the values for the given key joined into a single string using the given delimiter. * * @param key The key * @return The value as a single string */ public String getJoinedValue(String key, String delimiter) { List values = get(key); if (values == null) { return null; } else if (values.size() == 1) { return values.get(0); } else { StringBuilder result = new StringBuilder(); for (String value : values) { if (result.length() > 0) { result.append(delimiter); } result.append(value); } return result.toString(); } } /** * {@inheritDoc} */ /* @Override */ public List get(Object key) { if (key == null) { return null; } String lcKey = key.toString().toLowerCase(); String realKey = keyLookup.get(lcKey); if (realKey == null) { return null; } else { return values.get(realKey); } } /** * {@inheritDoc} */ /* @Override */ public Collection> values() { return values.values(); } @Override public boolean equals(Object obj) { if (this == obj) { return true; } if (obj == null) { return false; } if (getClass() != obj.getClass()) { return false; } final FluentCaseInsensitiveStringsMap other = (FluentCaseInsensitiveStringsMap) obj; if (values == null) { if (other.values != null) { return false; } } else if (!values.equals(other.values)) { return false; } return true; } @Override public int hashCode() { return values == null ? 0 : values.hashCode(); } @Override public String toString() { StringBuilder result = new StringBuilder(); for (Map.Entry> entry : values.entrySet()) { if (result.length() > 0) { result.append("; "); } result.append("\""); result.append(entry.getKey()); result.append("="); boolean needsComma = false; for (String value : entry.getValue()) { if (needsComma) { result.append(", "); } else { needsComma = true; } result.append(value); } result.append("\""); } return result.toString(); } } async-http-client-1.6.5/src/main/java/com/ning/http/client/FluentStringsMap.java000066400000000000000000000310371166553056000276160ustar00rootroot00000000000000/* * Copyright 2010 Ning, Inc. * * Ning licenses this file to you 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. * */ package com.ning.http.client; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Set; /** * An implementation of a {@code String -> List} map that adds a fluent interface, i.e. methods that * return this instance. */ public class FluentStringsMap implements Map>, Iterable>> { private final Map> values = new LinkedHashMap>(); public FluentStringsMap() { } public FluentStringsMap(FluentStringsMap src) { if (src != null) { for (Map.Entry> header : src) { add(header.getKey(), header.getValue()); } } } public FluentStringsMap(Map> src) { if (src != null) { for (Map.Entry> header : src.entrySet()) { add(header.getKey(), header.getValue()); } } } /** * Adds the specified values and returns this object. * * @param key The key * @param values The value(s); if null then this method has no effect. Use the empty string to * generate an empty value * @return This object */ public FluentStringsMap add(String key, String... values) { if ((values != null) && (values.length > 0)) { add(key, Arrays.asList(values)); } return this; } private List fetchValues( Collection values ) { List result = null; if (values != null) { for (String value : values) { if (value == null) { value = ""; } if (result == null) { // lazy initialization result = new ArrayList(); } result.add(value); } } return result; } /** * Adds the specified values and returns this object. * * @param key The key * @param values The value(s); if null then this method has no effect. Use an empty collection * to generate an empty value * @return This object */ public FluentStringsMap add(String key, Collection values) { if (key != null) { List nonNullValues = fetchValues( values ); if (nonNullValues != null) { List curValues = this.values.get(key); if (curValues == null) { curValues = new ArrayList(); this.values.put(key, curValues); } curValues.addAll(nonNullValues); } } return this; } /** * Adds all key-values pairs from the given object to this object and returns this object. * * @param src The source object * @return This object */ public FluentStringsMap addAll(FluentStringsMap src) { if (src != null) { for (Map.Entry> header : src) { add(header.getKey(), header.getValue()); } } return this; } /** * Adds all key-values pairs from the given map to this object and returns this object. * * @param src The source map * @return This object */ public FluentStringsMap addAll(Map> src) { if (src != null) { for (Map.Entry> header : src.entrySet()) { add(header.getKey(), header.getValue()); } } return this; } /** * Replaces the values for the given key with the given values. * * @param key The key * @param values The new values * @return This object */ public FluentStringsMap replace(final String key, final String... values) { return replace(key, Arrays.asList(values)); } /** * Replaces the values for the given key with the given values. * * @param key The key * @param values The new values * @return This object */ public FluentStringsMap replace(final String key, final Collection values) { if (key != null) { List nonNullValues = fetchValues( values ); if (nonNullValues == null) { this.values.remove(key); } else { this.values.put(key, nonNullValues); } } return this; } /** * Replace the values for all keys from the given map that are also present in this object, with the values from the given map. * All key-values from the given object that are not present in this object, will be added to it. * * @param src The source object * @return This object */ public FluentStringsMap replaceAll(FluentStringsMap src) { if (src != null) { for (Map.Entry> header : src) { replace(header.getKey(), header.getValue()); } } return this; } /** * Replace the values for all keys from the given map that are also present in this object, with the values from the given map. * All key-values from the given object that are not present in this object, will be added to it. * * @param src The source map * @return This object */ public FluentStringsMap replaceAll(Map> src) { if (src != null) { for (Map.Entry> header : src.entrySet()) { replace(header.getKey(), header.getValue()); } } return this; } /** * {@inheritDoc} */ /* @Override */ public List put(String key, List value) { if (key == null) { throw new NullPointerException("Null keys are not allowed"); } List oldValue = get(key); replace(key, value); return oldValue; } /** * {@inheritDoc} */ /* @Override */ public void putAll(Map> values) { replaceAll(values); } /** * Removes the values for the given key if present and returns this object. * * @param key The key * @return This object */ public FluentStringsMap delete(String key) { values.remove(key); return this; } /** * Removes the values for the given keys if present and returns this object. * * @param keys The keys * @return This object */ public FluentStringsMap deleteAll(String... keys) { if (keys != null) { for (String key : keys) { remove(key); } } return this; } /** * Removes the values for the given keys if present and returns this object. * * @param keys The keys * @return This object */ public FluentStringsMap deleteAll(Collection keys) { if (keys != null) { for (String key : keys) { remove(key); } } return this; } /** * {@inheritDoc} */ /* @Override */ public List remove(Object key) { if (key == null) { return null; } else { List oldValues = get(key.toString()); delete(key.toString()); return oldValues; } } /** * {@inheritDoc} */ /* @Override */ public void clear() { values.clear(); } /** * {@inheritDoc} */ /* @Override */ public Iterator>> iterator() { return Collections.unmodifiableSet(values.entrySet()).iterator(); } /** * {@inheritDoc} */ /* @Override */ public Set keySet() { return Collections.unmodifiableSet(values.keySet()); } /** * {@inheritDoc} */ /* @Override */ public Set>> entrySet() { return values.entrySet(); } /** * {@inheritDoc} */ /* @Override */ public int size() { return values.size(); } /** * {@inheritDoc} */ /* @Override */ public boolean isEmpty() { return values.isEmpty(); } /** * {@inheritDoc} */ /* @Override */ public boolean containsKey(Object key) { return key == null ? false : values.containsKey(key.toString()); } /** * {@inheritDoc} */ /* @Override */ public boolean containsValue(Object value) { return values.containsValue(value); } /** * Returns the value for the given key. If there are multiple values for this key, * then only the first one will be returned. * * @param key The key * @return The first value */ public String getFirstValue(String key) { List values = get(key); if (values == null) { return null; } else if (values.isEmpty()) { return ""; } else { return values.get(0); } } /** * Returns the values for the given key joined into a single string using the given delimiter. * * @param key The key * @return The value as a single string */ public String getJoinedValue(String key, String delimiter) { List values = get(key); if (values == null) { return null; } else if (values.size() == 1) { return values.get(0); } else { StringBuilder result = new StringBuilder(); for (String value : values) { if (result.length() > 0) { result.append(delimiter); } result.append(value); } return result.toString(); } } /** * {@inheritDoc} */ /* @Override */ public List get(Object key) { if (key == null) { return null; } return values.get(key.toString()); } /** * {@inheritDoc} */ /* @Override */ public Collection> values() { return values.values(); } @Override public boolean equals(Object obj) { if (this == obj) { return true; } if (obj == null) { return false; } if (getClass() != obj.getClass()) { return false; } final FluentStringsMap other = (FluentStringsMap) obj; if (values == null) { if (other.values != null) { return false; } } else if (!values.equals(other.values)) { return false; } return true; } @Override public int hashCode() { return values == null ? 0 : values.hashCode(); } @Override public String toString() { StringBuilder result = new StringBuilder(); for (Map.Entry> entry : values.entrySet()) { if (result.length() > 0) { result.append("; "); } result.append("\""); result.append(entry.getKey()); result.append("="); boolean needsComma = false; for (String value : entry.getValue()) { if (needsComma) { result.append(", "); } else { needsComma = true; } result.append(value); } result.append("\""); } return result.toString(); } } async-http-client-1.6.5/src/main/java/com/ning/http/client/HttpContent.java000066400000000000000000000021611166553056000266170ustar00rootroot00000000000000/* * Copyright 2010 Ning, Inc. * * Ning licenses this file to you 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. */ package com.ning.http.client; import java.net.URI; /** * Base class for callback class used by {@link com.ning.http.client.AsyncHandler} */ public class HttpContent { protected final AsyncHttpProvider provider; protected final URI uri; protected HttpContent(URI url, AsyncHttpProvider provider) { this.provider = provider; this.uri= url; } public final AsyncHttpProvider provider() { return provider; } public final URI getUrl( ){ return uri; } } async-http-client-1.6.5/src/main/java/com/ning/http/client/HttpResponseBodyPart.java000066400000000000000000000033011166553056000304450ustar00rootroot00000000000000/* * Copyright 2010 Ning, Inc. * * Ning licenses this file to you 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. */ package com.ning.http.client; import java.io.IOException; import java.io.OutputStream; import java.net.URI; import java.nio.ByteBuffer; /** * A callback class used when an HTTP response body is received. */ public abstract class HttpResponseBodyPart extends HttpContent { public HttpResponseBodyPart(URI uri, AsyncHttpProvider provider) { super(uri, provider); } /** * Return the response body's part bytes received. * @return the response body's part bytes received. */ abstract public byte[] getBodyPartBytes(); /** * Write the available bytes to the {@link java.io.OutputStream} * @param outputStream * @throws IOException * @return The number of bytes written */ abstract public int writeTo(OutputStream outputStream) throws IOException; /** * Return a {@link ByteBuffer} that wraps the actual bytes read from the response's chunk. The {@link ByteBuffer} * capacity is equal to the number of bytes available. * * @return {@link ByteBuffer} */ abstract public ByteBuffer getBodyByteBuffer(); } async-http-client-1.6.5/src/main/java/com/ning/http/client/HttpResponseHeaders.java000066400000000000000000000030631166553056000303010ustar00rootroot00000000000000/* * Copyright 2010 Ning, Inc. * * Ning licenses this file to you 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. */ package com.ning.http.client; import java.net.URI; /** * A class that represent the HTTP headers. */ public abstract class HttpResponseHeaders extends HttpContent { private final boolean traillingHeaders; public HttpResponseHeaders(URI uri, AsyncHttpProvider provider) { super(uri, provider); this.traillingHeaders = false; } public HttpResponseHeaders(URI uri, AsyncHttpProvider provider, boolean traillingHeaders) { super(uri, provider); this.traillingHeaders = traillingHeaders; } /** * Return the HTTP header * @return an {@link FluentCaseInsensitiveStringsMap} */ abstract public FluentCaseInsensitiveStringsMap getHeaders(); /** * Return true is headers has been received after the response body. * @return true is headers has been received after the response body. */ public boolean isTraillingHeadersReceived() { return traillingHeaders; } } async-http-client-1.6.5/src/main/java/com/ning/http/client/HttpResponseStatus.java000066400000000000000000000033351166553056000302130ustar00rootroot00000000000000/* * Copyright 2010 Ning, Inc. * * Ning licenses this file to you 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. * */ package com.ning.http.client; import java.net.URI; /** * A class that represent the HTTP response' status line (code + text) */ public abstract class HttpResponseStatus extends HttpContent { public HttpResponseStatus(URI uri, AsyncHttpProvider provider) { super(uri, provider); } /** * Return the response status code * @return the response status code */ abstract public int getStatusCode(); /** * Return the response status text * @return the response status text */ abstract public String getStatusText(); /** * Protocol name from status line. * * @return Protocol name. */ abstract public String getProtocolName(); /** * Protocol major version. * * @return Major version. */ abstract public int getProtocolMajorVersion(); /** * Protocol minor version. * * @return Minor version. */ abstract public int getProtocolMinorVersion(); /** * Full protocol name + version * * @return protocol name + version */ abstract public String getProtocolText(); } async-http-client-1.6.5/src/main/java/com/ning/http/client/ListenableFuture.java000077500000000000000000000067111166553056000276320ustar00rootroot00000000000000/* * Copyright 2010 Ning, Inc. * * Ning licenses this file to you 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. */ /* * Copyright (C) 2007 Google Inc. * * 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. */ package com.ning.http.client; import java.util.concurrent.Callable; import java.util.concurrent.Executor; import java.util.concurrent.Future; /** * Extended {@link Future} * * @param Type of the value that will be returned. */ public interface ListenableFuture extends Future { /** * Execute a {@link Callable} and if there is no exception, mark this Future as done and release the internal lock. * * @param callable */ void done(Callable callable); /** * Abort the current processing, and propagate the {@link Throwable} to the {@link AsyncHandler} or {@link Future} * * @param t */ void abort(Throwable t); /** * Set the content that will be returned by this instance * * @param v the content that will be returned by this instance */ void content(V v); /** * Touch the current instance to prevent external service to times out. */ void touch(); /** * Write the {@link Request} headers */ boolean getAndSetWriteHeaders(boolean writeHeader); /** * Write the {@link Request} body */ boolean getAndSetWriteBody(boolean writeBody); /** *

Adds a listener and executor to the ListenableFuture. * The listener will be {@linkplain java.util.concurrent.Executor#execute(Runnable) passed * to the executor} for execution when the {@code Future}'s computation is * {@linkplain Future#isDone() complete}. *

*

There is no guaranteed ordering of execution of listeners, they may get * called in the order they were added and they may get called out of order, * but any listener added through this method is guaranteed to be called once * the computation is complete. * * @param listener the listener to run when the computation is complete. * @param exec the executor to run the listener in. * @return this Future * @throws NullPointerException if the executor or listener was null. * @throws java.util.concurrent.RejectedExecutionException * if we tried to execute the listener * immediately but the executor rejected it. */ ListenableFuture addListener(Runnable listener, Executor exec); } async-http-client-1.6.5/src/main/java/com/ning/http/client/MaxRedirectException.java000066400000000000000000000022231166553056000304320ustar00rootroot00000000000000/* * Copyright 2010 Ning, Inc. * * Ning licenses this file to you 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. * */ package com.ning.http.client; /** * Thrown when the {@link AsyncHttpClientConfig#getMaxRedirects()} has been reached. */ public class MaxRedirectException extends Exception { private static final long serialVersionUID = 1L; public MaxRedirectException() { super(); } public MaxRedirectException(String msg) { super(msg); } public MaxRedirectException(Throwable cause) { super(cause); } public MaxRedirectException(String message, Throwable cause) { super(message, cause); } }async-http-client-1.6.5/src/main/java/com/ning/http/client/Part.java000066400000000000000000000013751166553056000252610ustar00rootroot00000000000000/* * Copyright 2010 Ning, Inc. * * Ning licenses this file to you 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. * */ package com.ning.http.client; /** * Interface for the parts in a multipart request. */ public interface Part { public String getName(); }async-http-client-1.6.5/src/main/java/com/ning/http/client/PerRequestConfig.java000066400000000000000000000025201166553056000275710ustar00rootroot00000000000000/* * Copyright 2010 Ning, Inc. * * Ning licenses this file to you 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. */ package com.ning.http.client; /** * Per request configuration. * * @author Hubert Iwaniuk */ public class PerRequestConfig { private final ProxyServer proxyServer; private int requestTimeoutInMs; public PerRequestConfig() { this(null, 0); } public PerRequestConfig(ProxyServer proxyServer, int requestTimeoutInMs) { this.proxyServer = proxyServer; this.requestTimeoutInMs = requestTimeoutInMs; } public ProxyServer getProxyServer() { return proxyServer; } public int getRequestTimeoutInMs() { return requestTimeoutInMs; } public void setRequestTimeoutInMs(int requestTimeoutInMs) { this.requestTimeoutInMs = requestTimeoutInMs; } } async-http-client-1.6.5/src/main/java/com/ning/http/client/ProgressAsyncHandler.java000066400000000000000000000043431166553056000304510ustar00rootroot00000000000000/* * Copyright (c) 2010-2011 Sonatype, Inc. All rights reserved. * * This program is licensed to you under the Apache License Version 2.0, * and you may not use this file except in compliance with the Apache License Version 2.0. * You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0. * * Unless required by applicable law or agreed to in writing, * software distributed under the Apache License Version 2.0 is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. */ package com.ning.http.client; /** * An extended {@link AsyncHandler} with two extra callback who get invoked during the content upload to a remote server. * This {@link AsyncHandler} must be used only with PUT and POST request. */ public interface ProgressAsyncHandler extends AsyncHandler { /** * Invoked when the content (a {@link java.io.File}, {@link String} or {@link java.io.FileInputStream} has been fully * written on the I/O socket. * * @return a {@link com.ning.http.client.AsyncHandler.STATE} telling to CONTINUE or ABORT the current processing. */ STATE onHeaderWriteCompleted(); /** * Invoked when the content (a {@link java.io.File}, {@link String} or {@link java.io.FileInputStream} has been fully * written on the I/O socket. * * @return a {@link com.ning.http.client.AsyncHandler.STATE} telling to CONTINUE or ABORT the current processing. */ STATE onContentWriteCompleted(); /** * Invoked when the I/O operation associated with the {@link Request} body wasn't fully written in a single I/O write * operation. This method is never invoked if the write operation complete in a sinfle I/O write. * * @param amount The amount of bytes to transfer. * @param current The amount of bytes transferred * @param total The total number of bytes transferred * @return a {@link com.ning.http.client.AsyncHandler.STATE} telling to CONTINUE or ABORT the current processing. */ STATE onContentWriteProgress(long amount, long current, long total); } async-http-client-1.6.5/src/main/java/com/ning/http/client/ProxyServer.java000066400000000000000000000067441166553056000266700ustar00rootroot00000000000000/* * Copyright 2010 Ning, Inc. * * Ning licenses this file to you 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. * */ package com.ning.http.client; import java.util.ArrayList; import java.util.Collections; import java.util.List; /** * Represents a proxy server. */ public class ProxyServer { public enum Protocol { HTTP("http"), HTTPS("https"), NTLM("NTLM"), KERBEROS("KERBEROS"), SPNEGO("SPNEGO"); private final String protocol; private Protocol(final String protocol) { this.protocol = protocol; } public String getProtocol() { return protocol; } @Override public String toString() { return getProtocol(); } } private String encoding = "UTF-8"; private final List nonProxyHosts = new ArrayList(); private final Protocol protocol; private final String host; private final String principal; private final String password; private int port; private String ntlmDomain = System.getProperty("http.auth.ntlm.domain", ""); public ProxyServer(final Protocol protocol, final String host, final int port, String principal, String password) { this.protocol = protocol; this.host = host; this.port = port; this.principal = principal; this.password = password; } public ProxyServer(final String host, final int port, String principal, String password) { this(Protocol.HTTP, host, port, principal, password); } public ProxyServer(final Protocol protocol, final String host, final int port) { this(protocol, host, port, null, null); } public ProxyServer(final String host, final int port) { this(Protocol.HTTP, host, port, null, null); } public Protocol getProtocol() { return protocol; } public String getProtocolAsString() { return protocol.toString(); } public String getHost() { return host; } public int getPort() { return port; } public String getPrincipal() { return principal; } public String getPassword() { return password; } public ProxyServer setEncoding(String encoding) { this.encoding = encoding; return this; } public String getEncoding() { return encoding; } public ProxyServer addNonProxyHost(String uri) { nonProxyHosts.add(uri); return this; } public ProxyServer removeNonProxyHost(String uri) { nonProxyHosts.remove(uri); return this; } public List getNonProxyHosts(){ return Collections.unmodifiableList(nonProxyHosts); } public ProxyServer setNtlmDomain(String ntlmDomain) { this.ntlmDomain = ntlmDomain; return this; } public String getNtlmDomain() { return ntlmDomain; } @Override public String toString() { return String.format("%s://%s:%d", protocol.toString(), host, port); } } async-http-client-1.6.5/src/main/java/com/ning/http/client/RandomAccessBody.java000066400000000000000000000030661166553056000275320ustar00rootroot00000000000000 /* * Copyright (c) 2010-2011 Sonatype, Inc. All rights reserved. * * This program is licensed to you under the Apache License Version 2.0, * and you may not use this file except in compliance with the Apache License Version 2.0. * You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0. * * Unless required by applicable law or agreed to in writing, * software distributed under the Apache License Version 2.0 is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. */ package com.ning.http.client; import java.io.IOException; import java.nio.channels.WritableByteChannel; /** * A request body which supports random access to its contents. */ public interface RandomAccessBody extends Body { /** * Transfers the specified chunk of bytes from this body to the specified channel. * * @param position The zero-based byte index from which to start the transfer, must not be negative. * @param count The maximum number of bytes to transfer, must not be negative. * @param target The destination channel to transfer the body chunk to, must not be {@code null}. * @return The non-negative number of bytes actually transferred. * @throws IOException If the body chunk could not be transferred. */ long transferTo(long position, long count, WritableByteChannel target) throws IOException; } async-http-client-1.6.5/src/main/java/com/ning/http/client/Realm.java000066400000000000000000000424771166553056000254230ustar00rootroot00000000000000/* * Copyright 2010 Ning, Inc. * * Ning licenses this file to you 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. * */ package com.ning.http.client; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.UnsupportedEncodingException; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; /** * This class is required when authentication is needed. The class support DIGEST and BASIC. */ public class Realm { private static final String NC = "00000001"; private final String principal; private final String password; private final AuthScheme scheme; private final String realmName; private final String nonce; private final String algorithm; private final String response; private final String qop; private final String nc; private final String cnonce; private final String uri; private final String methodName; private final boolean usePreemptiveAuth; private final String enc; private final String host; private final boolean messageType2Received; private final String domain; public enum AuthScheme { DIGEST, BASIC, NTLM, SPNEGO, KERBEROS, NONE } private Realm(AuthScheme scheme, String principal, String password, String realmName, String nonce, String algorithm, String response, String qop, String nc, String cnonce, String uri, String method, boolean usePreemptiveAuth, String domain, String enc, String host, boolean messageType2Received) { this.principal = principal; this.password = password; this.scheme = scheme; this.realmName = realmName; this.nonce = nonce; this.algorithm = algorithm; this.response = response; this.qop = qop; this.nc = nc; this.cnonce = cnonce; this.uri = uri; this.methodName = method; this.usePreemptiveAuth = usePreemptiveAuth; this.domain = domain; this.enc = enc; this.host = host; this.messageType2Received = messageType2Received; } public String getPrincipal() { return principal; } public String getPassword() { return password; } public AuthScheme getAuthScheme() { return scheme; } public AuthScheme getScheme() { return scheme; } public String getRealmName() { return realmName; } public String getNonce() { return nonce; } public String getAlgorithm() { return algorithm; } public String getResponse() { return response; } public String getQop() { return qop; } public String getNc() { return nc; } public String getCnonce() { return cnonce; } public String getUri() { return uri; } public String getEncoding(){ return enc; } public String getMethodName() { return methodName; } /** * Return true is preemptive authentication is enabled * @return true is preemptive authentication is enabled */ public boolean getUsePreemptiveAuth() { return usePreemptiveAuth; } /** * Return the NTLM domain to use. This value should map the JDK * @return the NTLM domain * @deprecated - use getNtlmDomain() */ public String getDomain() { return domain; } /** * Return the NTLM domain to use. This value should map the JDK * @return the NTLM domain */ public String getNtlmDomain() { return domain; } /** * Return the NTLM host. * @return the NTLM host */ public String getNtlmHost(){ return host; } public boolean isNtlmMessageType2Received(){ return messageType2Received; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Realm realm = (Realm) o; if (algorithm != null ? !algorithm.equals(realm.algorithm) : realm.algorithm != null) return false; if (cnonce != null ? !cnonce.equals(realm.cnonce) : realm.cnonce != null) return false; if (nc != null ? !nc.equals(realm.nc) : realm.nc != null) return false; if (nonce != null ? !nonce.equals(realm.nonce) : realm.nonce != null) return false; if (password != null ? !password.equals(realm.password) : realm.password != null) return false; if (principal != null ? !principal.equals(realm.principal) : realm.principal != null) return false; if (qop != null ? !qop.equals(realm.qop) : realm.qop != null) return false; if (realmName != null ? !realmName.equals(realm.realmName) : realm.realmName != null) return false; if (response != null ? !response.equals(realm.response) : realm.response != null) return false; if (scheme != realm.scheme) return false; if (uri != null ? !uri.equals(realm.uri) : realm.uri != null) return false; return true; } @Override public String toString() { return "Realm{" + "principal='" + principal + '\'' + ", password='" + password + '\'' + ", scheme=" + scheme + ", realmName='" + realmName + '\'' + ", nonce='" + nonce + '\'' + ", algorithm='" + algorithm + '\'' + ", response='" + response + '\'' + ", qop='" + qop + '\'' + ", nc='" + nc + '\'' + ", cnonce='" + cnonce + '\'' + ", uri='" + uri + '\'' + ", methodName='" + methodName + '\'' + '}'; } @Override public int hashCode() { int result = principal != null ? principal.hashCode() : 0; result = 31 * result + (password != null ? password.hashCode() : 0); result = 31 * result + (scheme != null ? scheme.hashCode() : 0); result = 31 * result + (realmName != null ? realmName.hashCode() : 0); result = 31 * result + (nonce != null ? nonce.hashCode() : 0); result = 31 * result + (algorithm != null ? algorithm.hashCode() : 0); result = 31 * result + (response != null ? response.hashCode() : 0); result = 31 * result + (qop != null ? qop.hashCode() : 0); result = 31 * result + (nc != null ? nc.hashCode() : 0); result = 31 * result + (cnonce != null ? cnonce.hashCode() : 0); result = 31 * result + (uri != null ? uri.hashCode() : 0); return result; } /** * A builder for {@link Realm} */ public static class RealmBuilder { private static final Logger logger = LoggerFactory.getLogger(RealmBuilder.class); // // Portions of code (newCnonce, newResponse) are highly inspired be Jetty 6 BasicAuthentication.java class. // This code is already Apache licenced. // private String principal = ""; private String password = ""; private AuthScheme scheme = AuthScheme.NONE; private String realmName = ""; private String nonce = ""; private String algorithm = "MD5"; private String response = ""; private String qop = "auth"; private String nc = "00000001"; private String cnonce = ""; private String uri = ""; private String methodName = "GET"; private boolean usePreemptive = false; private String domain = System.getProperty("http.auth.ntlm.domain", ""); private String enc = "UTF-8"; private String host = "localhost"; private boolean messageType2Received = false; @Deprecated public String getDomain() { return domain; } @Deprecated public RealmBuilder setDomain(String domain) { this.domain = domain; return this; } public String getNtlmDomain() { return domain; } public RealmBuilder setNtlmDomain(String domain) { this.domain = domain; return this; } public String getNtlmHost() { return host; } public RealmBuilder setNtlmHost(String host) { this.host = host; return this; } public String getPrincipal() { return principal; } public RealmBuilder setPrincipal(String principal) { this.principal = principal; return this; } public String getPassword() { return password; } public RealmBuilder setPassword(String password) { this.password = password; return this; } public AuthScheme getScheme() { return scheme; } public RealmBuilder setScheme(AuthScheme scheme) { this.scheme = scheme; return this; } public String getRealmName() { return realmName; } public RealmBuilder setRealmName(String realmName) { this.realmName = realmName; return this; } public String getNonce() { return nonce; } public RealmBuilder setNonce(String nonce) { this.nonce = nonce; return this; } public String getAlgorithm() { return algorithm; } public RealmBuilder setAlgorithm(String algorithm) { this.algorithm = algorithm; return this; } public String getResponse() { return response; } public RealmBuilder setResponse(String response) { this.response = response; return this; } public String getQop() { return qop; } public RealmBuilder setQop(String qop) { this.qop = qop; return this; } public String getNc() { return nc; } public RealmBuilder setNc(String nc) { this.nc = nc; return this; } public String getUri() { return uri; } public RealmBuilder setUri(String uri) { this.uri = uri; return this; } public String getMethodName() { return methodName; } public RealmBuilder setMethodName(String methodName) { this.methodName = methodName; return this; } public boolean getUsePreemptiveAuth() { return usePreemptive; } public RealmBuilder setUsePreemptiveAuth(boolean usePreemptiveAuth) { this.usePreemptive = usePreemptiveAuth; return this; } public RealmBuilder parseWWWAuthenticateHeader(String headerLine) { setRealmName(match(headerLine, "realm")); setNonce(match(headerLine, "nonce")); setAlgorithm(match(headerLine, "algorithm")); setQop(match(headerLine, "qop")); if (getNonce() != null && !getNonce().equalsIgnoreCase("")) { setScheme(AuthScheme.DIGEST); } else { setScheme(AuthScheme.BASIC); } return this; } public RealmBuilder setNtlmMessageType2Received(boolean messageType2Received) { this.messageType2Received = messageType2Received; return this; } public RealmBuilder clone(Realm clone) { setRealmName(clone.getRealmName()); setAlgorithm(clone.getAlgorithm()); setMethodName(clone.getMethodName()); setNc(clone.getNc()); setNonce(clone.getNonce()); setPassword(clone.getPassword()); setPrincipal(clone.getPrincipal()); setEnconding(clone.getEncoding()); setQop(clone.getQop()); setScheme(clone.getScheme()); setUri(clone.getUri()); setUsePreemptiveAuth(clone.getUsePreemptiveAuth()); setNtlmDomain(clone.getNtlmDomain()); setNtlmHost(clone.getNtlmHost()); setNtlmMessageType2Received(clone.isNtlmMessageType2Received()); return this; } private void newCnonce() { try { MessageDigest md = MessageDigest.getInstance("MD5"); byte[] b = md.digest(String.valueOf(System.currentTimeMillis()).getBytes("ISO-8859-1")); cnonce = toHexString(b); } catch (Exception e) { throw new SecurityException(e); } } /** * TODO: A Pattern/Matcher may be better. */ private String match(String headerLine, String token) { if (headerLine == null) { return ""; } int match = headerLine.indexOf(token); if (match <= 0) return ""; // = to skip match += token.length() + 1; int traillingComa = headerLine.indexOf(",", match); String value = headerLine.substring(match, traillingComa > 0 ? traillingComa : headerLine.length()); value = value.endsWith("\"") ? value.substring(0, value.length() - 1) : value; return value.startsWith("\"") ? value.substring(1) : value; } public String getEncoding() { return enc; } public RealmBuilder setEnconding(String enc) { this.enc = enc; return this; } private void newResponse() throws UnsupportedEncodingException { MessageDigest md = null; try { md = MessageDigest.getInstance("MD5"); } catch (NoSuchAlgorithmException e) { throw new SecurityException(e); } md.update(new StringBuilder(principal) .append(":") .append(realmName) .append(":") .append(password) .toString().getBytes("ISO-8859-1")); byte[] ha1 = md.digest(); md.reset(); md.update(new StringBuilder(methodName) .append(':') .append(uri).toString().getBytes("ISO-8859-1")); byte[] ha2 = md.digest(); md.update(new StringBuilder(toBase16(ha1)) .append(':') .append(nonce) .append(':') .append(NC) .append(':') .append(cnonce) .append(':') .append(qop) .append(':') .append(toBase16(ha2)).toString().getBytes("ISO-8859-1")); byte[] digest = md.digest(); response = toHexString(digest); } private static String toHexString(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(); } private static String toBase16(byte[] bytes) { int base = 16; StringBuilder buf = new StringBuilder(); for (byte b : bytes) { int bi = 0xff & b; int c = '0' + (bi / base) % base; if (c > '9') c = 'a' + (c - '0' - 10); buf.append((char) c); c = '0' + bi % base; if (c > '9') c = 'a' + (c - '0' - 10); buf.append((char) c); } return buf.toString(); } /** * Build a {@link Realm} * @return a {@link Realm} */ public Realm build() { // Avoid generating if (nonce != null && !nonce.equals("")) { newCnonce(); try { newResponse(); } catch (UnsupportedEncodingException e) { throw new RuntimeException(e); } } return new Realm(scheme, principal, password, realmName, nonce, algorithm, response, qop, nc, cnonce, uri, methodName, usePreemptive, domain, enc, host, messageType2Received); } } } async-http-client-1.6.5/src/main/java/com/ning/http/client/Request.java000066400000000000000000000123331166553056000257770ustar00rootroot00000000000000/* * Copyright 2010 Ning, Inc. * * Ning licenses this file to you 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. * */ package com.ning.http.client; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.Collection; import java.util.List; /** * The Request class can be used to construct HTTP request: * {@code * Request r = new RequestBuilder().setUrl("url") * .setRealm((new Realm.RealmBuilder()).setPrincipal(user) * .setPassword(admin) * .setRealmName("MyRealm") * .setScheme(Realm.AuthScheme.DIGEST).build()); * r.execute(); * } */ public interface Request { /** * An entity that can be used to manipulate the Request's body output before it get sent. */ public static interface EntityWriter { public void writeEntity(OutputStream out) throws IOException; } /** * Return the request's type (GET, POST, etc.) * @return the request's type (GET, POST, etc.) * @deprecated - use getMethod */ public String getReqType(); /** * Return the request's method name (GET, POST, etc.) * @return the request's method name (GET, POST, etc.) */ public String getMethod(); /** * Return the decoded url * @return the decoded url */ public String getUrl(); /** * Return the undecoded url * @return the undecoded url */ public String getRawUrl(); /** * Return the current set of Headers. * @return a {@link FluentCaseInsensitiveStringsMap} contains headers. */ public FluentCaseInsensitiveStringsMap getHeaders(); /** * Return Coookie. * @return an unmodifiable Collection of Cookies */ public Collection getCookies(); /** * Return the current request's body as a byte array * @return a byte array of the current request's body. */ public byte[] getByteData(); /** * Return the current request's body as a string * @return an String representation of the current request's body. */ public String getStringData(); /** * Return the current request's body as an InputStream * @return an InputStream representation of the current request's body. */ public InputStream getStreamData(); /** * Return the current request's body as an EntityWriter * @return an EntityWriter representation of the current request's body. */ public EntityWriter getEntityWriter(); /** * Return the current request's body generator. * @return A generator for the request body. */ public BodyGenerator getBodyGenerator(); /** * Return the current size of the content-lenght header based on the body's size. * @return the current size of the content-lenght header based on the body's size. * @deprecated */ public long getLength(); /** * Return the current size of the content-lenght header based on the body's size. * @return the current size of the content-lenght header based on the body's size. */ public long getContentLength(); /** * Return the current parameters. * @return a {@link FluentStringsMap} of parameters. */ public FluentStringsMap getParams(); /** * Return the current {@link Part} * @return the current {@link Part} */ public List getParts(); /** * Return the virtual host value. * @return the virtual host value. */ public String getVirtualHost(); /** * Return the query params. * @return {@link FluentStringsMap} of query string */ public FluentStringsMap getQueryParams(); /** * Return the {@link ProxyServer} * @return the {@link ProxyServer} */ public ProxyServer getProxyServer(); /** * Return the {@link Realm} * @return the {@link Realm} */ public Realm getRealm(); /** * Return the {@link File} to upload. * @return the {@link File} to upload. */ public File getFile(); /** * Return the true> to follow redirect * @return the true> to follow redirect */ public boolean isRedirectEnabled(); /** * Return Per request configuration. * * @return Per request configuration. */ public PerRequestConfig getPerRequestConfig(); /** * Return the HTTP Range header value, or * @return the range header value, or 0 is not set. */ public long getRangeOffset(); /** * Return the encoding value used when encoding the request's body. * @return the encoding value used when encoding the request's body. */ public String getBodyEncoding(); } async-http-client-1.6.5/src/main/java/com/ning/http/client/RequestBuilder.java000066400000000000000000000117371166553056000273150ustar00rootroot00000000000000/* * Copyright 2010 Ning, Inc. * * Ning licenses this file to you 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. */ package com.ning.http.client; import com.ning.http.client.Request.EntityWriter; import java.io.InputStream; import java.util.Collection; import java.util.Map; /** * Builder for a {@link Request}. */ public class RequestBuilder extends RequestBuilderBase { public RequestBuilder() { super(RequestBuilder.class, "GET"); } public RequestBuilder(String method) { super(RequestBuilder.class, method); } public RequestBuilder(Request prototype) { super(RequestBuilder.class, prototype); } // Note: For now we keep the delegates in place even though they are not needed // since otherwise Clojure (and maybe other languages) won't be able to // access these methods - see Clojure tickets 126 and 259 @Override public RequestBuilder addBodyPart(Part part) throws IllegalArgumentException { return super.addBodyPart(part); } @Override public RequestBuilder addCookie(Cookie cookie) { return super.addCookie(cookie); } @Override public RequestBuilder addHeader(String name, String value) { return super.addHeader(name, value); } @Override public RequestBuilder addParameter(String key, String value) throws IllegalArgumentException { return super.addParameter(key, value); } @Override public RequestBuilder addQueryParameter(String name, String value) { return super.addQueryParameter(name, value); } @Override public RequestBuilder setQueryParameters(FluentStringsMap parameters) { return super.setQueryParameters(parameters); } @Override public Request build() { return super.build(); } @Override public RequestBuilder setBody(byte[] data) throws IllegalArgumentException { return super.setBody(data); } @Override public RequestBuilder setBody(EntityWriter dataWriter, long length) throws IllegalArgumentException { return super.setBody(dataWriter, length); } @Override public RequestBuilder setBody(EntityWriter dataWriter) { return super.setBody(dataWriter); } /** * Deprecated - Use setBody(new InputStreamBodyGenerator(inputStream)). * @param stream - An {@link InputStream} * @return a {@link RequestBuilder} * @throws IllegalArgumentException * @deprecated {@link #setBody(BodyGenerator)} setBody(new InputStreamBodyGenerator(inputStream)) * @see #setBody(BodyGenerator) InputStreamBodyGenerator(inputStream) * @see com.ning.http.client.generators.InputStreamBodyGenerator */ @Override @Deprecated public RequestBuilder setBody(InputStream stream) throws IllegalArgumentException { return super.setBody(stream); } @Override public RequestBuilder setBody(String data) throws IllegalArgumentException { return super.setBody(data); } @Override public RequestBuilder setHeader(String name, String value) { return super.setHeader(name, value); } @Override public RequestBuilder setHeaders(FluentCaseInsensitiveStringsMap headers) { return super.setHeaders(headers); } @Override public RequestBuilder setHeaders(Map> headers) { return super.setHeaders(headers); } @Override public RequestBuilder setParameters(Map> parameters) throws IllegalArgumentException { return super.setParameters(parameters); } @Override public RequestBuilder setParameters(FluentStringsMap parameters) throws IllegalArgumentException { return super.setParameters(parameters); } @Override public RequestBuilder setMethod(String method) { return super.setMethod(method); } @Override public RequestBuilder setUrl(String url) { return super.setUrl(url); } @Override public RequestBuilder setProxyServer(ProxyServer proxyServer) { return super.setProxyServer(proxyServer); } @Override public RequestBuilder setVirtualHost(String virtualHost) { return super.setVirtualHost(virtualHost); } @Override public RequestBuilder setFollowRedirects(boolean followRedirects) { return super.setFollowRedirects(followRedirects); } @Override public RequestBuilder addOrReplaceCookie(Cookie c) { return super.addOrReplaceCookie(c); } } async-http-client-1.6.5/src/main/java/com/ning/http/client/RequestBuilderBase.java000066400000000000000000000442601166553056000301050ustar00rootroot00000000000000/* * Copyright 2010 Ning, Inc. * * Ning licenses this file to you 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. */ package com.ning.http.client; import com.ning.http.client.Request.EntityWriter; import com.ning.http.util.UTF8UrlEncoder; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.File; import java.io.InputStream; import java.io.UnsupportedEncodingException; import java.net.URI; import java.net.URLDecoder; import java.util.*; import java.util.Map.Entry; /** * Builder for {@link Request} * * @param */ public abstract class RequestBuilderBase> { private final static Logger logger = LoggerFactory.getLogger(RequestBuilderBase.class); private static final class RequestImpl implements Request { private String method; private String url = null; private FluentCaseInsensitiveStringsMap headers = new FluentCaseInsensitiveStringsMap(); private Collection cookies = new ArrayList(); private byte[] byteData; private String stringData; private InputStream streamData; private EntityWriter entityWriter; private BodyGenerator bodyGenerator; private FluentStringsMap params; private List parts; private String virtualHost; private long length = -1; public FluentStringsMap queryParams; public ProxyServer proxyServer; private Realm realm; private File file; private boolean followRedirects; private PerRequestConfig perRequestConfig; private long rangeOffset = 0; public String charset; public RequestImpl() { } public RequestImpl(Request prototype) { if (prototype != null) { this.method = prototype.getMethod(); int pos = prototype.getUrl().indexOf("?"); this.url = pos > 0 ? prototype.getUrl().substring(0,pos) : prototype.getUrl(); this.headers = new FluentCaseInsensitiveStringsMap(prototype.getHeaders()); this.cookies = new ArrayList(prototype.getCookies()); this.byteData = prototype.getByteData(); this.stringData = prototype.getStringData(); this.streamData = prototype.getStreamData(); this.entityWriter = prototype.getEntityWriter(); this.bodyGenerator = prototype.getBodyGenerator(); this.params = (prototype.getParams() == null ? null : new FluentStringsMap(prototype.getParams())); this.queryParams = (prototype.getQueryParams() == null ? null : new FluentStringsMap(prototype.getQueryParams())); this.parts = (prototype.getParts() == null ? null : new ArrayList(prototype.getParts())); this.virtualHost = prototype.getVirtualHost(); this.length = prototype.getContentLength(); this.proxyServer = prototype.getProxyServer(); this.realm = prototype.getRealm(); this.file = prototype.getFile(); this.followRedirects = prototype.isRedirectEnabled(); this.perRequestConfig = prototype.getPerRequestConfig(); this.rangeOffset = prototype.getRangeOffset(); this.charset = prototype.getBodyEncoding(); } } /* @Override */ public String getReqType() { return getMethod(); } public String getMethod() { return method; } /* @Override */ public String getUrl() { return toUrl(true); } private String toUrl(boolean encode) { if (url == null) { logger.debug("setUrl hasn't been invoked. Using http://localhost"); url = "http://localhost"; } String uri; try { uri = URI.create(url).toURL().toString(); } catch (Throwable e) { throw new IllegalArgumentException("Illegal URL: " + url, e); } if (queryParams != null) { StringBuilder builder = new StringBuilder(); if (!url.substring(8).contains("/")) { // no other "/" than http[s]:// -> http://localhost:1234 builder.append("/"); } builder.append("?"); for (Iterator>> i = queryParams.iterator(); i.hasNext();) { Map.Entry> param = i.next(); String name = param.getKey(); for (Iterator j = param.getValue().iterator(); j.hasNext();) { String value = j.next(); if (encode) { UTF8UrlEncoder.appendEncoded(builder, name); } else { builder.append(name); } if (value != null && !value.equals("")) { builder.append('='); if (encode) { UTF8UrlEncoder.appendEncoded(builder, value); } else { builder.append(value); } } if (j.hasNext()) { builder.append('&'); } } if (i.hasNext()) { builder.append('&'); } } uri += builder.toString(); } return uri; } /* @Override */ public String getRawUrl() { return toUrl(false); } /* @Override */ public FluentCaseInsensitiveStringsMap getHeaders() { return headers; } /* @Override */ public Collection getCookies() { return Collections.unmodifiableCollection(cookies); } /* @Override */ public byte[] getByteData() { return byteData; } /* @Override */ public String getStringData() { return stringData; } /* @Override */ public InputStream getStreamData() { return streamData; } /* @Override */ public EntityWriter getEntityWriter() { return entityWriter; } /* @Override */ public BodyGenerator getBodyGenerator() { return bodyGenerator; } /* @Override */ /** * @deprecated * @return */ public long getLength() { return length; } public long getContentLength() { return length; } /* @Override */ public FluentStringsMap getParams() { return params; } /* @Override */ public List getParts() { return parts; } /* @Override */ public String getVirtualHost() { return virtualHost; } public FluentStringsMap getQueryParams() { return queryParams; } public ProxyServer getProxyServer() { return proxyServer; } public Realm getRealm() { return realm; } public File getFile() { return file; } public boolean isRedirectEnabled() { return followRedirects; } public PerRequestConfig getPerRequestConfig() { return perRequestConfig; } public long getRangeOffset() { return rangeOffset; } public String getBodyEncoding() { return charset; } @Override public String toString() { StringBuilder sb = new StringBuilder(url); sb.append("\t"); sb.append(method); for (String name : headers.keySet()) { sb.append("\t"); sb.append(name); sb.append(":"); sb.append(headers.getJoinedValue(name, ", ")); } return sb.toString(); } } private final Class derived; protected final RequestImpl request; protected RequestBuilderBase(Class derived, String method) { this.derived = derived; request = new RequestImpl(); request.method = method; } protected RequestBuilderBase(Class derived, Request prototype) { this.derived = derived; request = new RequestImpl(prototype); } public T setUrl(String url) { request.url = buildUrl(url); return derived.cast(this); } private String buildUrl(String url) { URI uri = URI.create(url); StringBuilder buildedUrl = new StringBuilder(); if (uri.getScheme() != null) { buildedUrl.append(uri.getScheme()); buildedUrl.append("://"); } if (uri.getAuthority() != null) { buildedUrl.append(uri.getAuthority()); } if (uri.getRawPath() != null) { buildedUrl.append(uri.getRawPath()); } else { // AHC-96 // Let's try to derive it if (url.indexOf("://") == -1) { String s = buildedUrl.toString(); url = s + url.substring(uri.getScheme().length() + 1); return buildUrl(url); } else { throw new IllegalArgumentException("Invalid url " + uri.toString()); } } if (uri.getRawQuery() != null && !uri.getRawQuery().equals("")) { String[] queries = uri.getRawQuery().split("&"); int pos; for( String query : queries) { pos = query.indexOf("="); if (pos <= 0) { addQueryParameter(query, null); }else{ try { addQueryParameter(URLDecoder.decode(query.substring(0, pos), "UTF-8") , URLDecoder.decode(query.substring(pos +1), "UTF-8")); } catch ( UnsupportedEncodingException e ) { throw new RuntimeException(e); } } } } return buildedUrl.toString(); } public T setVirtualHost(String virtualHost) { request.virtualHost = virtualHost; return derived.cast(this); } public T setHeader(String name, String value) { request.headers.replace(name, value); return derived.cast(this); } public T addHeader(String name, String value) { if (value == null) { logger.warn("Value was null, set to \"\""); value = ""; } request.headers.add(name, value); return derived.cast(this); } public T setHeaders(FluentCaseInsensitiveStringsMap headers) { request.headers = (headers == null ? new FluentCaseInsensitiveStringsMap() : new FluentCaseInsensitiveStringsMap(headers)); return derived.cast(this); } public T setHeaders(Map> headers) { request.headers = (headers == null ? new FluentCaseInsensitiveStringsMap() : new FluentCaseInsensitiveStringsMap(headers)); return derived.cast(this); } public T setContentLength(int length) { request.length = length; return derived.cast(this); } public T addCookie(Cookie cookie) { request.cookies.add(cookie); return derived.cast(this); } private void resetParameters() { request.params = null; } private void resetNonMultipartData() { request.byteData = null; request.stringData = null; request.streamData = null; request.entityWriter = null; request.length = -1; } private void resetMultipartData() { request.parts = null; } private void checkIfBodyAllowed() { if ("GET".equals(request.method) || "HEAD".equals(request.method)) { throw new IllegalArgumentException("Can NOT set Body on HTTP Request Method GET nor HEAD."); } } public T setBody(File file) { checkIfBodyAllowed(); request.file = file; return derived.cast(this); } public T setBody(byte[] data) throws IllegalArgumentException { checkIfBodyAllowed(); resetParameters(); resetNonMultipartData(); resetMultipartData(); request.byteData = data; return derived.cast(this); } public T setBody(String data) throws IllegalArgumentException { checkIfBodyAllowed(); resetParameters(); resetNonMultipartData(); resetMultipartData(); request.stringData = data; return derived.cast(this); } public T setBody(InputStream stream) throws IllegalArgumentException { checkIfBodyAllowed(); resetParameters(); resetNonMultipartData(); resetMultipartData(); request.streamData = stream; return derived.cast(this); } public T setBody(EntityWriter dataWriter) { return setBody(dataWriter, -1); } public T setBody(EntityWriter dataWriter, long length) throws IllegalArgumentException { checkIfBodyAllowed(); resetParameters(); resetNonMultipartData(); resetMultipartData(); request.entityWriter = dataWriter; request.length = length; return derived.cast(this); } public T setBody(BodyGenerator bodyGenerator) { checkIfBodyAllowed(); request.bodyGenerator = bodyGenerator; return derived.cast(this); } public T addQueryParameter(String name, String value) { if (request.queryParams == null) { request.queryParams = new FluentStringsMap(); } request.queryParams.add(name, value); return derived.cast(this); } public T setQueryParameters(FluentStringsMap parameters){ if (parameters == null) { request.queryParams = null; } else { request.queryParams = new FluentStringsMap(parameters); } return derived.cast(this); } public T addParameter(String key, String value) throws IllegalArgumentException { resetNonMultipartData(); resetMultipartData(); if (request.params == null) { request.params = new FluentStringsMap(); } request.params.add(key, value); return derived.cast(this); } public T setParameters(FluentStringsMap parameters) throws IllegalArgumentException { resetNonMultipartData(); resetMultipartData(); request.params = new FluentStringsMap(parameters); return derived.cast(this); } public T setParameters(Map> parameters) throws IllegalArgumentException { resetNonMultipartData(); resetMultipartData(); request.params = new FluentStringsMap(parameters); return derived.cast(this); } public T addBodyPart(Part part) throws IllegalArgumentException { resetParameters(); resetNonMultipartData(); if (request.parts == null) { request.parts = new ArrayList(); } request.parts.add(part); return derived.cast(this); } public T setProxyServer(ProxyServer proxyServer) { request.proxyServer = proxyServer; return derived.cast(this); } public T setRealm(Realm realm) { request.realm = realm; return derived.cast(this); } public T setFollowRedirects(boolean followRedirects) { request.followRedirects = followRedirects; return derived.cast(this); } public T setPerRequestConfig(PerRequestConfig perRequestConfig) { request.perRequestConfig = perRequestConfig; return derived.cast(this); } public T setRangeOffset(long rangeOffset) { request.rangeOffset = rangeOffset; return derived.cast(this); } public T setMethod(String method) { request.method = method; return derived.cast(this); } public T setBodyEncoding(String charset) { request.charset = charset; return derived.cast(this); } public Request build() { if ((request.length < 0) && (request.streamData == null) && allowBody(request.getMethod())) { // can't concatenate content-length String contentLength = request.headers.getFirstValue("Content-Length"); if (contentLength != null) { try { request.length = Long.parseLong(contentLength); } catch (NumberFormatException e) { // NoOp -- we wdn't specify length so it will be chunked? } } } return request; } private boolean allowBody(String method) { if ( method.equalsIgnoreCase("GET") || method.equalsIgnoreCase("OPTIONS") && method.equalsIgnoreCase("TRACE") && method.equalsIgnoreCase("HEAD")) { return false; } else { return true; } } public T addOrReplaceCookie(Cookie cookie) { String cookieKey = cookie.getName(); boolean replace = false; int index = 0; for (Cookie c : request.cookies) { if (c.getName().equals(cookieKey)) { replace = true; break; } index++; } if (replace) { ((ArrayList) request.cookies).set(index, cookie); } else { request.cookies.add(cookie); } return derived.cast(this); } } async-http-client-1.6.5/src/main/java/com/ning/http/client/Response.java000066400000000000000000000155741166553056000261570ustar00rootroot00000000000000/* * Copyright 2010 Ning, Inc. * * Ning licenses this file to you 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. * */ package com.ning.http.client; import java.io.IOException; import java.io.InputStream; import java.net.MalformedURLException; import java.net.URI; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.List; /** * Represents the asynchronous HTTP response callback for an {@link com.ning.http.client.AsyncCompletionHandler} * */ public interface Response { /** * Returns the status code for the request. * * @return The status code */ public int getStatusCode(); /** * Returns the status text for the request. * * @return The status text */ public String getStatusText(); /** * Returns an input stream for the response body. Note that you should not try to get this more than once, * and that you should not close the stream. * * @return The input stream * @throws java.io.IOException */ public InputStream getResponseBodyAsStream() throws IOException; /** * Returns the first maxLength bytes of the response body as a string. Note that this does not check * whether the content type is actually a textual one, but it will use the charset if present in the content * type header. * * @param maxLength The maximum number of bytes to read * @param charset the charset to use when decoding the stream * @return The response body * @throws java.io.IOException */ public String getResponseBodyExcerpt(int maxLength, String charset) throws IOException; /** * Return the entire response body as a String. * @param charset the charset to use when decoding the stream * @return the entire response body as a String. * @throws IOException */ public String getResponseBody(String charset) throws IOException; /** * Returns the first maxLength bytes of the response body as a string. Note that this does not check * whether the content type is actually a textual one, but it will use the charset if present in the content * type header. * * @param maxLength The maximum number of bytes to read * @return The response body * @throws java.io.IOException */ public String getResponseBodyExcerpt(int maxLength) throws IOException; /** * Return the entire response body as a String. * @return the entire response body as a String. * @throws IOException */ public String getResponseBody() throws IOException; /** * Return the request {@link URI}. Note that if the request got redirected, the value of the {@link URI} will be * the last valid redirect url. * @return the request {@link URI}. * @throws MalformedURLException */ public URI getUri() throws MalformedURLException; /** * Return the content-type header value. * @return the content-type header value. */ public String getContentType(); /** * Return the response header * @return the response header */ public String getHeader(String name); /** * Return a {@link List} of the response header value. * @return the response header */ public List getHeaders(String name); public FluentCaseInsensitiveStringsMap getHeaders(); /** * Return true if the response redirects to another object. * * @return True if the response redirects to another object. */ boolean isRedirected(); /** * Subclasses SHOULD implement toString() in a way that identifies the request for logging. * @return The textual representation */ public String toString(); /** * Return the list of {@link Cookie}. */ public List getCookies(); /** * Return true if the response's status has been computed by an {@link AsyncHandler} * @return true if the response's status has been computed by an {@link AsyncHandler} */ public boolean hasResponseStatus(); /** * Return true if the response's headers has been computed by an {@link AsyncHandler} It will return false if the * either {@link com.ning.http.client.AsyncHandler#onStatusReceived(HttpResponseStatus)} * or {@link AsyncHandler#onHeadersReceived(HttpResponseHeaders)} returned {@link com.ning.http.client.AsyncHandler.STATE#ABORT} * @return true if the response's headers has been computed by an {@link AsyncHandler} */ public boolean hasResponseHeaders(); /** * Return true if the response's body has been computed by an {@link AsyncHandler}. It will return false if the * either {@link com.ning.http.client.AsyncHandler#onStatusReceived(HttpResponseStatus)} * or {@link AsyncHandler#onHeadersReceived(HttpResponseHeaders)} returned {@link com.ning.http.client.AsyncHandler.STATE#ABORT} * @return true if the response's body has been computed by an {@link AsyncHandler} */ public boolean hasResponseBody(); public static class ResponseBuilder { private final Collection bodies = Collections.synchronizedCollection(new ArrayList()); private HttpResponseStatus status; private HttpResponseHeaders headers; /** * Accumulate {@link HttpContent} in order to build a {@link Response} * @param httpContent {@link HttpContent} * @return this */ public ResponseBuilder accumulate(HttpContent httpContent) { if (httpContent instanceof HttpResponseStatus) { status = (HttpResponseStatus) httpContent; } else if (httpContent instanceof HttpResponseHeaders) { headers = (HttpResponseHeaders) httpContent; } else if (httpContent instanceof HttpResponseBodyPart) { bodies.add((HttpResponseBodyPart)httpContent); } return this; } /** * Build a {@link Response} instance * @return a {@link Response} instance */ public Response build() { return status == null ? null : status.provider().prepareResponse(status, headers, bodies); } /** * Reset the internal state of this builder. */ public void reset() { bodies.clear(); status = null; headers = null; } } }async-http-client-1.6.5/src/main/java/com/ning/http/client/ResumableBodyConsumer.java000066400000000000000000000023521166553056000306200ustar00rootroot00000000000000 /* * Copyright (c) 2010-2011 Sonatype, Inc. All rights reserved. * * This program is licensed to you under the Apache License Version 2.0, * and you may not use this file except in compliance with the Apache License Version 2.0. * You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0. * * Unless required by applicable law or agreed to in writing, * software distributed under the Apache License Version 2.0 is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. */ package com.ning.http.client; import java.io.IOException; /** * @author Benjamin Hanzelmann */ public interface ResumableBodyConsumer extends BodyConsumer { /** * Prepare this consumer to resume a download, for example by seeking to the end of the underlying file. * * @throws IOException */ void resume() throws IOException; /** * Get the previously transferred bytes, for example the current file size. * * @throws IOException */ long getTransferredBytes() throws IOException; } async-http-client-1.6.5/src/main/java/com/ning/http/client/SSLEngineFactory.java000066400000000000000000000020761166553056000274710ustar00rootroot00000000000000/* * Copyright 2010 Ning, Inc. * * Ning licenses this file to you 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. */ package com.ning.http.client; import java.security.GeneralSecurityException; import javax.net.ssl.SSLEngine; /** * Factory that creates an {@link SSLEngine} to be used for a single SSL connection. */ public interface SSLEngineFactory { /** * Creates new {@link SSLEngine}. * * @return new engine * @throws GeneralSecurityException if the SSLEngine cannot be created */ SSLEngine newSSLEngine() throws GeneralSecurityException; } async-http-client-1.6.5/src/main/java/com/ning/http/client/SignatureCalculator.java000066400000000000000000000031231166553056000303170ustar00rootroot00000000000000/* * Copyright 2010 Ning, Inc. * * Ning licenses this file to you 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. */ package com.ning.http.client; /** * Interface that allows injecting signature calculator into * {@link RequestBuilder} so that signature calculation and inclusion can * be added as a pluggable component. * * @since 1.1 */ public interface SignatureCalculator { /** * Method called when {@link RequestBuilder#build} method is called. * Should first calculate signature information and then modify request * (using passed {@link RequestBuilder}) to add signature (usually as * an HTTP header). * * @param requestBuilder builder that can be used to modify request, usually * by adding header that includes calculated signature. Be sure NOT to * call {@link RequestBuilder#build} since this will cause infinite recursion * @param request Request that is being built; needed to access content to * be signed */ public void calculateAndAddSignature(String url, Request request, RequestBuilderBase requestBuilder); } async-http-client-1.6.5/src/main/java/com/ning/http/client/SimpleAsyncHttpClient.java000066400000000000000000000751261166553056000306060ustar00rootroot00000000000000/* * Copyright (c) 2010 Sonatype, Inc. All rights reserved. * * This program is licensed to you under the Apache License Version 2.0, * and you may not use this file except in compliance with the Apache License Version 2.0. * You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0. * * Unless required by applicable law or agreed to in writing, * software distributed under the Apache License Version 2.0 is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. */ package com.ning.http.client; import com.ning.http.client.resumable.ResumableAsyncHandler; import com.ning.http.client.resumable.ResumableIOExceptionFilter; import com.ning.http.client.simple.HeaderMap; import com.ning.http.client.simple.SimpleAHCTransferListener; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.net.ssl.SSLContext; import java.io.IOException; import java.util.Collection; import java.util.Map; import java.util.concurrent.ExecutorService; import java.util.concurrent.Future; import java.util.concurrent.ScheduledExecutorService; /** * Simple implementation of {@link AsyncHttpClient} and it's related builders ({@link com.ning.http.client.AsyncHttpClientConfig}, * {@link Realm}, {@link com.ning.http.client.ProxyServer} and {@link com.ning.http.client.AsyncHandler}. You can * build powerful application by just using this class. *

* This class rely on {@link BodyGenerator} and {@link BodyConsumer} for handling the request and response body. No * {@link AsyncHandler} are required. As simple as: *

* {@code * SimpleAsyncHttpClient client = new SimpleAsyncHttpClient.Builder() * .setIdleConnectionInPoolTimeoutInMs(100) * .setMaximumConnectionsTotal(50) * .setRequestTimeoutInMs(5 * 60 * 1000) * .setUrl(getTargetUrl()) * .setHeader("Content-Type", "text/html").build(); *

* StringBuilder s = new StringBuilder(); * Future future = client.post(new InputStreamBodyGenerator(new ByteArrayInputStream(MY_MESSAGE.getBytes())), new AppendableBodyConsumer(s)); * } * or * {@code * public void ByteArrayOutputStreamBodyConsumerTest() throws Throwable { *

* SimpleAsyncHttpClient client = new SimpleAsyncHttpClient.Builder() * .setUrl(getTargetUrl()) * .build(); *

* ByteArrayOutputStream o = new ByteArrayOutputStream(10); * Future future = client.post(new FileodyGenerator(myFile), new OutputStreamBodyConsumer(o)); * } * } */ public class SimpleAsyncHttpClient { private final static Logger logger = LoggerFactory.getLogger(SimpleAsyncHttpClient.class); private final AsyncHttpClientConfig config; private final RequestBuilder requestBuilder; private AsyncHttpClient asyncHttpClient; private final ThrowableHandler defaultThrowableHandler; private final boolean resumeEnabled; private final ErrorDocumentBehaviour errorDocumentBehaviour; private final SimpleAHCTransferListener listener; private final boolean derived; private SimpleAsyncHttpClient(AsyncHttpClientConfig config, RequestBuilder requestBuilder, ThrowableHandler defaultThrowableHandler, ErrorDocumentBehaviour errorDocumentBehaviour, boolean resumeEnabled, AsyncHttpClient ahc, SimpleAHCTransferListener listener) { this.config = config; this.requestBuilder = requestBuilder; this.defaultThrowableHandler = defaultThrowableHandler; this.resumeEnabled = resumeEnabled; this.errorDocumentBehaviour = errorDocumentBehaviour; this.asyncHttpClient = ahc; this.listener = listener; this.derived = ahc != null; } public Future post(Part... parts) throws IOException { RequestBuilder r = rebuildRequest(requestBuilder.build()); r.setMethod("POST"); for ( Part part : parts ) { r.addBodyPart( part ); } return execute(r, null, null); } public Future post(BodyConsumer consumer, Part... parts) throws IOException { RequestBuilder r = rebuildRequest(requestBuilder.build()); r.setMethod("POST"); for ( Part part : parts ) { r.addBodyPart( part ); } return execute(r, consumer, null); } public Future post(BodyGenerator bodyGenerator) throws IOException { RequestBuilder r = rebuildRequest(requestBuilder.build()); r.setMethod("POST"); r.setBody(bodyGenerator); return execute(r, null, null); } public Future post(BodyGenerator bodyGenerator, ThrowableHandler throwableHandler) throws IOException { RequestBuilder r = rebuildRequest(requestBuilder.build()); r.setMethod("POST"); r.setBody(bodyGenerator); return execute(r, null, throwableHandler); } public Future post(BodyGenerator bodyGenerator, BodyConsumer bodyConsumer) throws IOException { RequestBuilder r = rebuildRequest(requestBuilder.build()); r.setMethod("POST"); r.setBody(bodyGenerator); return execute(r, bodyConsumer, null); } public Future post(BodyGenerator bodyGenerator, BodyConsumer bodyConsumer, ThrowableHandler throwableHandler) throws IOException { RequestBuilder r = rebuildRequest(requestBuilder.build()); r.setMethod("POST"); r.setBody(bodyGenerator); return execute(r, bodyConsumer, throwableHandler); } public Future put(Part... parts) throws IOException { RequestBuilder r = rebuildRequest(requestBuilder.build()); r.setMethod("POST"); for ( Part part : parts ) { r.addBodyPart( part ); } return execute(r, null, null); } public Future put(BodyConsumer consumer, Part... parts) throws IOException { RequestBuilder r = rebuildRequest(requestBuilder.build()); r.setMethod("POST"); for ( Part part : parts ) { r.addBodyPart( part ); } return execute(r, consumer, null); } public Future put(BodyGenerator bodyGenerator, BodyConsumer bodyConsumer) throws IOException { RequestBuilder r = rebuildRequest(requestBuilder.build()); r.setMethod("PUT"); r.setBody(bodyGenerator); return execute(r, bodyConsumer, null); } public Future put(BodyGenerator bodyGenerator, BodyConsumer bodyConsumer, ThrowableHandler throwableHandler) throws IOException { RequestBuilder r = rebuildRequest(requestBuilder.build()); r.setMethod("PUT"); r.setBody(bodyGenerator); return execute(r, bodyConsumer, throwableHandler); } public Future put(BodyGenerator bodyGenerator) throws IOException { RequestBuilder r = rebuildRequest(requestBuilder.build()); r.setMethod("PUT"); r.setBody(bodyGenerator); return execute(r, null, null); } public Future put(BodyGenerator bodyGenerator, ThrowableHandler throwableHandler) throws IOException { RequestBuilder r = rebuildRequest(requestBuilder.build()); r.setMethod("PUT"); r.setBody(bodyGenerator); return execute(r, null, throwableHandler); } public Future get() throws IOException { RequestBuilder r = rebuildRequest(requestBuilder.build()); return execute(r, null, null); } public Future get(ThrowableHandler throwableHandler) throws IOException { RequestBuilder r = rebuildRequest(requestBuilder.build()); return execute(r, null, throwableHandler); } public Future get(BodyConsumer bodyConsumer) throws IOException { RequestBuilder r = rebuildRequest(requestBuilder.build()); return execute(r, bodyConsumer, null); } public Future get(BodyConsumer bodyConsumer, ThrowableHandler throwableHandler) throws IOException { RequestBuilder r = rebuildRequest(requestBuilder.build()); return execute(r, bodyConsumer, throwableHandler); } public Future delete() throws IOException { RequestBuilder r = rebuildRequest(requestBuilder.build()); r.setMethod("DELETE"); return execute(r, null, null); } public Future delete(ThrowableHandler throwableHandler) throws IOException { RequestBuilder r = rebuildRequest(requestBuilder.build()); r.setMethod("DELETE"); return execute(r, null, throwableHandler); } public Future delete(BodyConsumer bodyConsumer) throws IOException { RequestBuilder r = rebuildRequest(requestBuilder.build()); r.setMethod("DELETE"); return execute(r, bodyConsumer, null); } public Future delete(BodyConsumer bodyConsumer, ThrowableHandler throwableHandler) throws IOException { RequestBuilder r = rebuildRequest(requestBuilder.build()); r.setMethod("DELETE"); return execute(r, bodyConsumer, throwableHandler); } public Future head() throws IOException { RequestBuilder r = rebuildRequest(requestBuilder.build()); r.setMethod("HEAD"); return execute(r, null, null); } public Future head(ThrowableHandler throwableHandler) throws IOException { RequestBuilder r = rebuildRequest(requestBuilder.build()); r.setMethod("HEAD"); return execute(r, null, throwableHandler); } public Future options() throws IOException { RequestBuilder r = rebuildRequest(requestBuilder.build()); r.setMethod("OPTIONS"); return execute(r, null, null); } public Future options(ThrowableHandler throwableHandler) throws IOException { RequestBuilder r = rebuildRequest(requestBuilder.build()); r.setMethod("OPTIONS"); return execute(r, null, throwableHandler); } public Future options(BodyConsumer bodyConsumer) throws IOException { RequestBuilder r = rebuildRequest(requestBuilder.build()); r.setMethod("OPTIONS"); return execute(r, bodyConsumer, null); } public Future options(BodyConsumer bodyConsumer, ThrowableHandler throwableHandler) throws IOException { RequestBuilder r = rebuildRequest(requestBuilder.build()); r.setMethod("OPTIONS"); return execute(r, bodyConsumer, throwableHandler); } private RequestBuilder rebuildRequest(Request rb) { return new RequestBuilder(rb); } private Future execute(RequestBuilder rb, BodyConsumer bodyConsumer, ThrowableHandler throwableHandler) throws IOException { if (throwableHandler == null) { throwableHandler = defaultThrowableHandler; } Request request = rb.build(); ProgressAsyncHandler handler = new BodyConsumerAsyncHandler(bodyConsumer, throwableHandler, errorDocumentBehaviour, request.getUrl(), listener); if (resumeEnabled && request.getMethod().equals("GET") && bodyConsumer != null && bodyConsumer instanceof ResumableBodyConsumer) { ResumableBodyConsumer fileBodyConsumer = (ResumableBodyConsumer) bodyConsumer; long length = fileBodyConsumer.getTransferredBytes(); fileBodyConsumer.resume(); handler = new ResumableBodyConsumerAsyncHandler(length, handler); } return asyncHttpClient().executeRequest(request, handler); } private AsyncHttpClient asyncHttpClient() { synchronized (config) { if (asyncHttpClient == null) { asyncHttpClient = new AsyncHttpClient(config); } } return asyncHttpClient; } /** * Close the underlying AsyncHttpClient for this instance. *

* If this instance is derived from another instance, this method does * nothing as the client instance is managed by the original * SimpleAsyncHttpClient. * * @see #derive() * @see AsyncHttpClient#close() */ public void close() { if (!derived && asyncHttpClient != null) { asyncHttpClient.close(); } } /** * Returns a Builder for a derived SimpleAsyncHttpClient that uses the same * instance of {@link AsyncHttpClient} to execute requests. * *

* * The original SimpleAsyncHttpClient is responsible for managing the * underlying AsyncHttpClient. For the derived instance, {@link #close()} is * a NOOP. If the original SimpleAsyncHttpClient is closed, all derived * instances become invalid. * * @return a Builder for a derived SimpleAsyncHttpClient that uses the same * instance of {@link AsyncHttpClient} to execute requests, never * {@code null}. */ public DerivedBuilder derive() { return new Builder(this); } public enum ErrorDocumentBehaviour { /** * Write error documents as usual via * {@link BodyConsumer#consume(java.nio.ByteBuffer)}. */ WRITE, /** * Accumulate error documents in memory but do not consume. */ ACCUMULATE, /** * Omit error documents. An error document will neither be available in * the response nor written via a {@link BodyConsumer}. */ OMIT; } /** * This interface contains possible configuration changes for a derived SimpleAsyncHttpClient. * * @see SimpleAsyncHttpClient#derive() */ public interface DerivedBuilder { DerivedBuilder setFollowRedirects(boolean followRedirects); DerivedBuilder setVirtualHost(String virtualHost); DerivedBuilder setUrl(String url); DerivedBuilder setParameters(FluentStringsMap parameters) throws IllegalArgumentException; DerivedBuilder setParameters(Map> parameters) throws IllegalArgumentException; DerivedBuilder setHeaders(Map> headers); DerivedBuilder setHeaders(FluentCaseInsensitiveStringsMap headers); DerivedBuilder setHeader(String name, String value); DerivedBuilder addQueryParameter(String name, String value); DerivedBuilder addParameter(String key, String value) throws IllegalArgumentException; DerivedBuilder addHeader(String name, String value); DerivedBuilder addCookie(Cookie cookie); DerivedBuilder addBodyPart(Part part) throws IllegalArgumentException; DerivedBuilder setResumableDownload(boolean resume); SimpleAsyncHttpClient build(); } public final static class Builder implements DerivedBuilder { private final RequestBuilder requestBuilder; private final AsyncHttpClientConfig.Builder configBuilder = new AsyncHttpClientConfig.Builder(); private Realm.RealmBuilder realmBuilder = null; private ProxyServer.Protocol proxyProtocol = null; private String proxyHost = null; private String proxyPrincipal = null; private String proxyPassword = null; private int proxyPort = 80; private ThrowableHandler defaultThrowableHandler = null; private boolean enableResumableDownload = false; private ErrorDocumentBehaviour errorDocumentBehaviour = ErrorDocumentBehaviour.WRITE; private AsyncHttpClient ahc = null; private SimpleAHCTransferListener listener = null; public Builder() { requestBuilder = new RequestBuilder("GET"); } private Builder(SimpleAsyncHttpClient client) { this.requestBuilder = new RequestBuilder(client.requestBuilder.build()); this.defaultThrowableHandler = client.defaultThrowableHandler; this.errorDocumentBehaviour = client.errorDocumentBehaviour; this.enableResumableDownload = client.resumeEnabled; this.ahc = client.asyncHttpClient(); this.listener = client.listener; } public Builder addBodyPart(Part part) throws IllegalArgumentException { requestBuilder.addBodyPart(part); return this; } public Builder addCookie(Cookie cookie) { requestBuilder.addCookie(cookie); return this; } public Builder addHeader(String name, String value) { requestBuilder.addHeader(name, value); return this; } public Builder addParameter(String key, String value) throws IllegalArgumentException { requestBuilder.addParameter(key, value); return this; } public Builder addQueryParameter(String name, String value) { requestBuilder.addQueryParameter(name, value); return this; } public Builder setHeader(String name, String value) { requestBuilder.setHeader(name, value); return this; } public Builder setHeaders(FluentCaseInsensitiveStringsMap headers) { requestBuilder.setHeaders(headers); return this; } public Builder setHeaders(Map> headers) { requestBuilder.setHeaders(headers); return this; } public Builder setParameters(Map> parameters) throws IllegalArgumentException { requestBuilder.setParameters(parameters); return this; } public Builder setParameters(FluentStringsMap parameters) throws IllegalArgumentException { requestBuilder.setParameters(parameters); return this; } public Builder setUrl(String url) { requestBuilder.setUrl(url); return this; } public Builder setVirtualHost(String virtualHost) { requestBuilder.setVirtualHost(virtualHost); return this; } public Builder setFollowRedirects(boolean followRedirects) { requestBuilder.setFollowRedirects(followRedirects); return this; } public Builder setMaximumConnectionsTotal(int defaultMaxTotalConnections) { configBuilder.setMaximumConnectionsTotal(defaultMaxTotalConnections); return this; } public Builder setMaximumConnectionsPerHost(int defaultMaxConnectionPerHost) { configBuilder.setMaximumConnectionsPerHost(defaultMaxConnectionPerHost); return this; } public Builder setConnectionTimeoutInMs(int connectionTimeuot) { configBuilder.setConnectionTimeoutInMs(connectionTimeuot); return this; } public Builder setIdleConnectionInPoolTimeoutInMs(int defaultIdleConnectionInPoolTimeoutInMs) { configBuilder.setIdleConnectionInPoolTimeoutInMs(defaultIdleConnectionInPoolTimeoutInMs); return this; } public Builder setRequestTimeoutInMs(int defaultRequestTimeoutInMs) { configBuilder.setRequestTimeoutInMs(defaultRequestTimeoutInMs); return this; } public Builder setMaximumNumberOfRedirects(int maxDefaultRedirects) { configBuilder.setMaximumNumberOfRedirects(maxDefaultRedirects); return this; } public Builder setCompressionEnabled(boolean compressionEnabled) { configBuilder.setCompressionEnabled(compressionEnabled); return this; } public Builder setUserAgent(String userAgent) { configBuilder.setUserAgent(userAgent); return this; } public Builder setAllowPoolingConnection(boolean allowPoolingConnection) { configBuilder.setAllowPoolingConnection(allowPoolingConnection); return this; } public Builder setScheduledExecutorService(ScheduledExecutorService reaper) { configBuilder.setScheduledExecutorService(reaper); return this; } public Builder setExecutorService(ExecutorService applicationThreadPool) { configBuilder.setExecutorService(applicationThreadPool); return this; } public Builder setSSLEngineFactory(SSLEngineFactory sslEngineFactory) { configBuilder.setSSLEngineFactory(sslEngineFactory); return this; } public Builder setSSLContext(final SSLContext sslContext) { configBuilder.setSSLContext(sslContext); return this; } public Builder setRequestCompressionLevel(int requestCompressionLevel) { configBuilder.setRequestCompressionLevel(requestCompressionLevel); return this; } public Builder setRealmDomain(String domain) { realm().setDomain(domain); return this; } public Builder setRealmPrincipal(String principal) { realm().setPrincipal(principal); return this; } public Builder setRealmPassword(String password) { realm().setPassword(password); return this; } public Builder setRealmScheme(Realm.AuthScheme scheme) { realm().setScheme(scheme); return this; } public Builder setRealmName(String realmName) { realm().setRealmName(realmName); return this; } public Builder setRealmUsePreemptiveAuth(boolean usePreemptiveAuth) { realm().setUsePreemptiveAuth(usePreemptiveAuth); return this; } public Builder setRealmEnconding(String enc) { realm().setEnconding(enc); return this; } public Builder setProxyProtocol(ProxyServer.Protocol protocol) { this.proxyProtocol = protocol; return this; } public Builder setProxyHost(String host) { this.proxyHost = host; return this; } public Builder setProxyPrincipal(String principal) { this.proxyPrincipal = principal; return this; } public Builder setProxyPassword(String password) { this.proxyPassword = password; return this; } public Builder setProxyPort(int port) { this.proxyPort = port; return this; } public Builder setDefaultThrowableHandler(ThrowableHandler throwableHandler) { this.defaultThrowableHandler = throwableHandler; return this; } /** * This setting controls whether an error document should be written via * the {@link BodyConsumer} after an error status code was received (e.g. * 404). Default is {@link ErrorDocumentBehaviour#WRITE}. */ public Builder setErrorDocumentBehaviour(ErrorDocumentBehaviour behaviour) { this.errorDocumentBehaviour = behaviour; return this; } /** * Enable resumable downloads for the SimpleAHC. Resuming downloads will only work for GET requests * with an instance of {@link ResumableBodyConsumer}. */ public Builder setResumableDownload(boolean enableResumableDownload) { this.enableResumableDownload = enableResumableDownload; return this; } private Realm.RealmBuilder realm() { if (realmBuilder == null) { realmBuilder = new Realm.RealmBuilder(); } return realmBuilder; } /** * Set the listener to notify about connection progress. */ public Builder setListener(SimpleAHCTransferListener listener) { this.listener = listener; return this; } /** * Set the number of time a request will be retried when an {@link java.io.IOException} occurs because of a Network exception. * @param maxRequestRetry the number of time a request will be retried * @return this */ public Builder setMaxRequestRetry(int maxRequestRetry) { configBuilder.setMaxRequestRetry(maxRequestRetry); return this; } public SimpleAsyncHttpClient build() { if (realmBuilder != null) { configBuilder.setRealm(realmBuilder.build()); } if (proxyHost != null) { configBuilder.setProxyServer(new ProxyServer(proxyProtocol, proxyHost, proxyPort, proxyPrincipal, proxyPassword)); } configBuilder.addIOExceptionFilter(new ResumableIOExceptionFilter()); SimpleAsyncHttpClient sc = new SimpleAsyncHttpClient(configBuilder.build(), requestBuilder, defaultThrowableHandler, errorDocumentBehaviour, enableResumableDownload, ahc, listener); return sc; } } private final static class ResumableBodyConsumerAsyncHandler extends ResumableAsyncHandler implements ProgressAsyncHandler { private final ProgressAsyncHandler delegate; public ResumableBodyConsumerAsyncHandler(long byteTransferred, ProgressAsyncHandler delegate) { super(byteTransferred, delegate); this.delegate = delegate; } public com.ning.http.client.AsyncHandler.STATE onHeaderWriteCompleted() { return delegate.onHeaderWriteCompleted(); } public com.ning.http.client.AsyncHandler.STATE onContentWriteCompleted() { return delegate.onContentWriteCompleted(); } public com.ning.http.client.AsyncHandler.STATE onContentWriteProgress(long amount, long current, long total) { return delegate.onContentWriteProgress(amount, current, total); } } private final static class BodyConsumerAsyncHandler extends AsyncCompletionHandlerBase { private final BodyConsumer bodyConsumer; private final ThrowableHandler exceptionHandler; private final ErrorDocumentBehaviour errorDocumentBehaviour; private final String url; private final SimpleAHCTransferListener listener; private boolean accumulateBody = false; private boolean omitBody = false; private int amount = 0; private long total = -1; public BodyConsumerAsyncHandler(BodyConsumer bodyConsumer, ThrowableHandler exceptionHandler, ErrorDocumentBehaviour errorDocumentBehaviour, String url, SimpleAHCTransferListener listener) { this.bodyConsumer = bodyConsumer; this.exceptionHandler = exceptionHandler; this.errorDocumentBehaviour = errorDocumentBehaviour; this.url = url; this.listener = listener; } @Override public void onThrowable(Throwable t) { try { if (exceptionHandler != null) { exceptionHandler.onThrowable(t); } else { super.onThrowable(t); } } finally { closeConsumer(); } } /** * {@inheritDoc} */ public STATE onBodyPartReceived(final HttpResponseBodyPart content) throws Exception { fireReceived(content); if (omitBody) { return STATE.CONTINUE; } if (!accumulateBody && bodyConsumer != null) { bodyConsumer.consume(content.getBodyByteBuffer()); } else { return super.onBodyPartReceived(content); } return STATE.CONTINUE; } /** * {@inheritDoc} */ @Override public Response onCompleted(Response response) throws Exception { fireCompleted(response); closeConsumer(); return super.onCompleted(response); } private void closeConsumer() { try { if (bodyConsumer != null) { bodyConsumer.close(); } } catch (IOException ex) { logger.warn("Unable to close a BodyConsumer {}", bodyConsumer); } } @Override public STATE onStatusReceived(HttpResponseStatus status) throws Exception { fireStatus(status); if (isErrorStatus(status)) { switch (errorDocumentBehaviour) { case ACCUMULATE: accumulateBody = true; break; case OMIT: omitBody = true; break; default: break; } } return super.onStatusReceived(status); } private boolean isErrorStatus(HttpResponseStatus status) { return status.getStatusCode() >= 400; } @Override public STATE onHeadersReceived(HttpResponseHeaders headers) throws Exception { calculateTotal(headers); fireHeaders(headers); return super.onHeadersReceived(headers); } private void calculateTotal(HttpResponseHeaders headers) { String length = headers.getHeaders().getFirstValue("Content-Length"); try { total = Integer.valueOf(length); } catch (Exception e) { total = -1; } } @Override public STATE onContentWriteProgress(long amount, long current, long total) { fireSent(url, amount, current, total); return super.onContentWriteProgress(amount, current, total); } private void fireStatus(HttpResponseStatus status) { if (listener != null) { listener.onStatus(url, status.getStatusCode(), status.getStatusText()); } } private void fireReceived(HttpResponseBodyPart content) { int remaining = content.getBodyByteBuffer().remaining(); amount += remaining; if (listener != null) { listener.onBytesReceived(url, amount, remaining, total); } } private void fireHeaders(HttpResponseHeaders headers) { if (listener != null) { listener.onHeaders(url, new HeaderMap(headers.getHeaders())); } } private void fireSent(String url, long amount, long current, long total) { if (listener != null) { listener.onBytesSent(url, amount, current, total); } } private void fireCompleted(Response response) { if (listener != null) { listener.onCompleted(url, response.getStatusCode(), response.getStatusText()); } } } } async-http-client-1.6.5/src/main/java/com/ning/http/client/StringPart.java000066400000000000000000000024431166553056000264450ustar00rootroot00000000000000/* * Copyright 2010 Ning, Inc. * * Ning licenses this file to you 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. * */ package com.ning.http.client; /** * A string multipart part. */ public class StringPart implements Part { private final String name; private final String value; private final String charset; public StringPart(String name, String value, String charset) { this.name = name; this.value = value; this.charset = charset; } public StringPart(String name, String value) { this.name = name; this.value = value; this.charset = "UTF-8"; } public String getName() { return name; } public String getValue() { return value; } public String getCharset() { return charset; } }async-http-client-1.6.5/src/main/java/com/ning/http/client/ThrowableHandler.java000066400000000000000000000015761166553056000276030ustar00rootroot00000000000000 /* * Copyright (c) 2010-2011 Sonatype, Inc. All rights reserved. * * This program is licensed to you under the Apache License Version 2.0, * and you may not use this file except in compliance with the Apache License Version 2.0. * You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0. * * Unless required by applicable law or agreed to in writing, * software distributed under the Apache License Version 2.0 is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. */ package com.ning.http.client; /** * Simple {@link Throwable} handler to be used with {@link SimpleAsyncHttpClient} */ public interface ThrowableHandler { void onThrowable(Throwable t); } async-http-client-1.6.5/src/main/java/com/ning/http/client/consumers/000077500000000000000000000000001166553056000255205ustar00rootroot00000000000000async-http-client-1.6.5/src/main/java/com/ning/http/client/consumers/AppendableBodyConsumer.java000066400000000000000000000031371166553056000327540ustar00rootroot00000000000000/* * Copyright (c) 2010-2011 Sonatype, Inc. All rights reserved. * * This program is licensed to you under the Apache License Version 2.0, * and you may not use this file except in compliance with the Apache License Version 2.0. * You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0. * * Unless required by applicable law or agreed to in writing, * software distributed under the Apache License Version 2.0 is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. */ package com.ning.http.client.consumers; import com.ning.http.client.BodyConsumer; import java.io.Closeable; import java.io.IOException; import java.nio.ByteBuffer; public class AppendableBodyConsumer implements BodyConsumer { private final Appendable appendable; private final String encoding; public AppendableBodyConsumer(Appendable appendable, String encoding) { this.appendable = appendable; this.encoding = encoding; } public AppendableBodyConsumer(Appendable appendable) { this.appendable = appendable; this.encoding = "UTF-8"; } public void consume(ByteBuffer byteBuffer) throws IOException { appendable.append(new String(byteBuffer.array(), encoding)); } public void close() throws IOException { if (Closeable.class.isAssignableFrom(appendable.getClass())) { Closeable.class.cast(appendable).close(); } } } async-http-client-1.6.5/src/main/java/com/ning/http/client/consumers/ByteBufferBodyConsumer.java000066400000000000000000000023251166553056000327540ustar00rootroot00000000000000/* * Copyright (c) 2010-2011 Sonatype, Inc. All rights reserved. * * This program is licensed to you under the Apache License Version 2.0, * and you may not use this file except in compliance with the Apache License Version 2.0. * You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0. * * Unless required by applicable law or agreed to in writing, * software distributed under the Apache License Version 2.0 is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. */ package com.ning.http.client.consumers; import com.ning.http.client.BodyConsumer; import java.io.IOException; import java.nio.ByteBuffer; public class ByteBufferBodyConsumer implements BodyConsumer { private final ByteBuffer byteBuffer; public ByteBufferBodyConsumer(ByteBuffer byteBuffer) { this.byteBuffer = byteBuffer; } public void consume(ByteBuffer byteBuffer) throws IOException { byteBuffer.put(byteBuffer); } public void close() throws IOException { byteBuffer.flip(); } } async-http-client-1.6.5/src/main/java/com/ning/http/client/consumers/FileBodyConsumer.java000066400000000000000000000030011166553056000315660ustar00rootroot00000000000000/* * Copyright (c) 2010-2011 Sonatype, Inc. All rights reserved. * * This program is licensed to you under the Apache License Version 2.0, * and you may not use this file except in compliance with the Apache License Version 2.0. * You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0. * * Unless required by applicable law or agreed to in writing, * software distributed under the Apache License Version 2.0 is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. */ package com.ning.http.client.consumers; import com.ning.http.client.ResumableBodyConsumer; import java.io.IOException; import java.io.RandomAccessFile; import java.nio.ByteBuffer; public class FileBodyConsumer implements ResumableBodyConsumer { private final RandomAccessFile file; public FileBodyConsumer(RandomAccessFile file) { this.file = file; } public void consume(ByteBuffer byteBuffer) throws IOException { // TODO: Channel.transferFrom may be a good idea to investigate. file.write(byteBuffer.array()); } public void close() throws IOException { file.close(); } public long getTransferredBytes() throws IOException { return file.length(); } public void resume() throws IOException { file.seek( getTransferredBytes() ); } } async-http-client-1.6.5/src/main/java/com/ning/http/client/consumers/OutputStreamBodyConsumer.java000066400000000000000000000024221166553056000333710ustar00rootroot00000000000000/* * Copyright (c) 2010-2011 Sonatype, Inc. All rights reserved. * * This program is licensed to you under the Apache License Version 2.0, * and you may not use this file except in compliance with the Apache License Version 2.0. * You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0. * * Unless required by applicable law or agreed to in writing, * software distributed under the Apache License Version 2.0 is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. */ package com.ning.http.client.consumers; import com.ning.http.client.BodyConsumer; import java.io.IOException; import java.io.OutputStream; import java.nio.ByteBuffer; public class OutputStreamBodyConsumer implements BodyConsumer { private final OutputStream outputStream; public OutputStreamBodyConsumer(OutputStream outputStream) { this.outputStream = outputStream; } public void consume(ByteBuffer byteBuffer) throws IOException { outputStream.write(byteBuffer.array()); } public void close() throws IOException { outputStream.close(); } } async-http-client-1.6.5/src/main/java/com/ning/http/client/extra/000077500000000000000000000000001166553056000246255ustar00rootroot00000000000000ResumableRandomAccessFileListener.java000066400000000000000000000043231166553056000341230ustar00rootroot00000000000000async-http-client-1.6.5/src/main/java/com/ning/http/client/extra/* * Copyright (c) 2010-2011 Sonatype, Inc. All rights reserved. * * This program is licensed to you under the Apache License Version 2.0, * and you may not use this file except in compliance with the Apache License Version 2.0. * You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0. * * Unless required by applicable law or agreed to in writing, * software distributed under the Apache License Version 2.0 is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. */ package com.ning.http.client.extra; import com.ning.http.client.resumable.ResumableListener; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.IOException; import java.io.RandomAccessFile; import java.nio.ByteBuffer; import java.util.concurrent.atomic.AtomicLong; /** * A {@link com.ning.http.client.listener.TransferListener} which use a {@link RandomAccessFile} for storing the received bytes. */ public class ResumableRandomAccessFileListener implements ResumableListener { private final RandomAccessFile file; private final static Logger logger = LoggerFactory.getLogger(ThrottleRequestFilter.class); public ResumableRandomAccessFileListener(RandomAccessFile file) { this.file = file; } /** * This method uses the last valid bytes written on disk to position a {@link RandomAccessFile}, allowing * resumable file download. * * @param buffer a {@link ByteBuffer} * @throws IOException */ public void onBytesReceived(ByteBuffer buffer) throws IOException { file.seek(file.length()); file.write(buffer.array()); } /** * {@inheritDoc} */ public void onAllBytesReceived() { if (file != null) { try { file.close(); } catch (IOException e) { ; } } } /** * {@inheritDoc} */ public long length() { try { return file.length(); } catch (IOException e) { ; } return 0; } } async-http-client-1.6.5/src/main/java/com/ning/http/client/extra/ThrottleRequestFilter.java000066400000000000000000000105071166553056000320170ustar00rootroot00000000000000/* * Copyright (c) 2010-2011 Sonatype, Inc. All rights reserved. * * This program is licensed to you under the Apache License Version 2.0, * and you may not use this file except in compliance with the Apache License Version 2.0. * You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0. * * Unless required by applicable law or agreed to in writing, * software distributed under the Apache License Version 2.0 is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. */ package com.ning.http.client.extra; import com.ning.http.client.AsyncHandler; import com.ning.http.client.HttpResponseBodyPart; import com.ning.http.client.HttpResponseHeaders; import com.ning.http.client.HttpResponseStatus; import com.ning.http.client.filter.FilterContext; import com.ning.http.client.filter.FilterException; import com.ning.http.client.filter.RequestFilter; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.concurrent.Semaphore; import java.util.concurrent.TimeUnit; /** * A {@link com.ning.http.client.filter.RequestFilter} throttles requests and block when the number of permits is reached, waiting for * the response to arrives before executing the next request. */ public class ThrottleRequestFilter implements RequestFilter { private final static Logger logger = LoggerFactory.getLogger(ThrottleRequestFilter.class); private final int maxConnections; private final Semaphore available; private final int maxWait; public ThrottleRequestFilter(int maxConnections) { this.maxConnections = maxConnections; this.maxWait = Integer.MAX_VALUE; available = new Semaphore(maxConnections, true); } public ThrottleRequestFilter(int maxConnections, int maxWait) { this.maxConnections = maxConnections; this.maxWait = maxWait; available = new Semaphore(maxConnections, true); } public FilterContext filter(FilterContext ctx) throws FilterException { try { if (logger.isDebugEnabled()) { logger.debug("Current Throttling Status {}", available.availablePermits()); } if (!available.tryAcquire(maxWait, TimeUnit.MILLISECONDS)) { throw new FilterException( String.format("No slot available for processing Request %s with AsyncHandler %s", ctx.getRequest(), ctx.getAsyncHandler())); } ; } catch (InterruptedException e) { throw new FilterException( String.format("Interrupted Request %s with AsyncHandler %s", ctx.getRequest(), ctx.getAsyncHandler())); } return new FilterContext.FilterContextBuilder(ctx).asyncHandler(new AsyncHandlerWrapper(ctx.getAsyncHandler())).build(); } private class AsyncHandlerWrapper implements AsyncHandler { private final AsyncHandler asyncHandler; public AsyncHandlerWrapper(AsyncHandler asyncHandler) { this.asyncHandler = asyncHandler; } public void onThrowable(Throwable t) { try { asyncHandler.onThrowable(t); } finally { available.release(); if (logger.isDebugEnabled()) { logger.debug("Current Throttling Status after onThrowable {}", available.availablePermits()); } } } public STATE onBodyPartReceived(HttpResponseBodyPart bodyPart) throws Exception { return asyncHandler.onBodyPartReceived(bodyPart); } public STATE onStatusReceived(HttpResponseStatus responseStatus) throws Exception { return asyncHandler.onStatusReceived(responseStatus); } public STATE onHeadersReceived(HttpResponseHeaders headers) throws Exception { return asyncHandler.onHeadersReceived(headers); } public T onCompleted() throws Exception { available.release(); if (logger.isDebugEnabled()) { logger.debug("Current Throttling Status {}", available.availablePermits()); } return asyncHandler.onCompleted(); } } } async-http-client-1.6.5/src/main/java/com/ning/http/client/filter/000077500000000000000000000000001166553056000247675ustar00rootroot00000000000000async-http-client-1.6.5/src/main/java/com/ning/http/client/filter/FilterContext.java000066400000000000000000000166321166553056000304340ustar00rootroot00000000000000/* * Copyright (c) 2010-2011 Sonatype, Inc. All rights reserved. * * This program is licensed to you under the Apache License Version 2.0, * and you may not use this file except in compliance with the Apache License Version 2.0. * You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0. * * Unless required by applicable law or agreed to in writing, * software distributed under the Apache License Version 2.0 is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. */ package com.ning.http.client.filter; import com.ning.http.client.AsyncHandler; import com.ning.http.client.HttpResponseStatus; import com.ning.http.client.Request; import java.io.IOException; /** * A {@link FilterContext} can be used to decorate {@link Request} and {@link AsyncHandler} from a list of {@link RequestFilter}. * {@link RequestFilter} gets executed before the HTTP request is made to the remote server. Once the response bytes are * received, a {@link FilterContext} is then passed to the list of {@link ResponseFilter}. {@link ResponseFilter} * gets invoked before the response gets processed, e.g. before authorization, redirection and invokation of {@link AsyncHandler} * gets processed. *

* Invoking {@link com.ning.http.client.filter.FilterContext#getResponseStatus()} returns an instance of {@link HttpResponseStatus} * that can be used to decide if the response processing should continue or not. You can stop the current response processing * and replay the request but creating a {@link FilterContext}. The {@link com.ning.http.client.AsyncHttpProvider} * will interrupt the processing and "replay" the associated {@link Request} instance. */ public class FilterContext { private final AsyncHandler asyncHandler; private final Request request; private final HttpResponseStatus responseStatus; private final boolean replayRequest ; private final IOException ioException; /** * Create a new {@link FilterContext} * * @param asyncHandler an {@link AsyncHandler} * @param request a {@link Request} * @deprecated use {@link FilterContextBuilder} instead */ public FilterContext(AsyncHandler asyncHandler, Request request) { this(asyncHandler, request, null, false, null); } /** * Create a new {@link FilterContext} * * @param asyncHandler an {@link AsyncHandler} * @param request a {@link Request} * @param ioException an {@link IOException} * @deprecated use {@link FilterContextBuilder} instead */ public FilterContext(AsyncHandler asyncHandler, Request request, IOException ioException) { this(asyncHandler, request, null, false, ioException); } /** * Create a new {@link FilterContext} * * @param asyncHandler an {@link AsyncHandler} * @param request a {@link Request} * @param responseStatus a {@link HttpResponseStatus} * @deprecated use {@link FilterContextBuilder} instead */ public FilterContext(AsyncHandler asyncHandler, Request request, HttpResponseStatus responseStatus) { this(asyncHandler, request, responseStatus, false, null); } private FilterContext(AsyncHandler asyncHandler, Request request, HttpResponseStatus responseStatus, boolean replayRequest, IOException ioException) { this.asyncHandler = asyncHandler; this.request = request; this.responseStatus = responseStatus; this.replayRequest = replayRequest; this.ioException = ioException; } /** * Create a new {@link FilterContext} * * @param asyncHandler an {@link AsyncHandler} * @param request a {@link Request} * @param replayRequest true if the current response processing needs to be interrupted, and a new {@link Request} be processed. * @deprecated use {@link FilterContextBuilder} instead */ public FilterContext(AsyncHandler asyncHandler, Request request, boolean replayRequest) { this(asyncHandler, request, null, replayRequest, null); } /** * Return the original or decorated {@link AsyncHandler} * * @return the original or decorated {@link AsyncHandler} */ public AsyncHandler getAsyncHandler() { return asyncHandler; } /** * Return the original or decorated {@link Request} * * @return the original or decorated {@link Request} */ public Request getRequest() { return request; } /** * Return the unprocessed response's {@link HttpResponseStatus} * * @return the unprocessed response's {@link HttpResponseStatus} */ public HttpResponseStatus getResponseStatus() { return responseStatus; } /** * Return true if the current response's processing needs to be interrupted and a new {@link Request} be executed. * * @return true if the current response's processing needs to be interrupted and a new {@link Request} be executed. */ public boolean replayRequest() { return replayRequest; } /** * Return the {@link IOException} * * @return the {@link IOException} */ public IOException getIOException() { return ioException; } public static class FilterContextBuilder { private AsyncHandler asyncHandler = null; private Request request = null; private HttpResponseStatus responseStatus = null; private boolean replayRequest = false; private IOException ioException = null; public FilterContextBuilder(){ } public FilterContextBuilder(FilterContext clone) { asyncHandler = clone.getAsyncHandler(); request = clone.getRequest(); responseStatus = clone.getResponseStatus(); replayRequest = clone.replayRequest(); ioException = clone.getIOException(); } public AsyncHandler getAsyncHandler() { return asyncHandler; } public FilterContextBuilder asyncHandler(AsyncHandler asyncHandler) { this.asyncHandler = asyncHandler; return this; } public Request getRequest() { return request; } public FilterContextBuilder request(Request request) { this.request = request; return this; } public HttpResponseStatus getResponseStatus() { return responseStatus; } public FilterContextBuilder responseStatus(HttpResponseStatus responseStatus) { this.responseStatus = responseStatus; return this; } public boolean replayRequest() { return replayRequest; } public FilterContextBuilder replayRequest(boolean replayRequest) { this.replayRequest = replayRequest; return this; } public IOException getIoException() { return ioException; } public FilterContextBuilder ioException(IOException ioException) { this.ioException = ioException; return this; } public FilterContext build() { return new FilterContext(asyncHandler, request, responseStatus, replayRequest, ioException); } } } async-http-client-1.6.5/src/main/java/com/ning/http/client/filter/FilterException.java000066400000000000000000000024351166553056000307420ustar00rootroot00000000000000/* * Copyright (c) 2010-2011 Sonatype, Inc. All rights reserved. * * This program is licensed to you under the Apache License Version 2.0, * and you may not use this file except in compliance with the Apache License Version 2.0. * You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0. * * Unless required by applicable law or agreed to in writing, * software distributed under the Apache License Version 2.0 is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. */ package com.ning.http.client.filter; /** * An exception that can be thrown by an {@link com.ning.http.client.AsyncHandler} to interrupt invocation of * the {@link RequestFilter} and {@link ResponseFilter}. It also interrupt the request and response processing. * */ public class FilterException extends Exception { /** * @param message */ public FilterException(final String message) { super(message); } /** * @param message * @param cause */ public FilterException(final String message, final Throwable cause) { super(message, cause); } } async-http-client-1.6.5/src/main/java/com/ning/http/client/filter/IOExceptionFilter.java000066400000000000000000000026261166553056000311740ustar00rootroot00000000000000/* * Copyright (c) 2010-2011 Sonatype, Inc. All rights reserved. * * This program is licensed to you under the Apache License Version 2.0, * and you may not use this file except in compliance with the Apache License Version 2.0. * You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0. * * Unless required by applicable law or agreed to in writing, * software distributed under the Apache License Version 2.0 is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. */ package com.ning.http.client.filter; /** * This filter is invoked when an {@link java.io.IOException} occurs during an http transaction. */ public interface IOExceptionFilter { /** * An {@link com.ning.http.client.AsyncHttpProvider} will invoke {@link IOExceptionFilter#filter} and will * use the returned {@link FilterContext} to replay the {@link com.ning.http.client.Request} or abort the processing. * * @param ctx a {@link FilterContext} * @return {@link FilterContext}. The {@link FilterContext} instance may not the same as the original one. * @throws FilterException to interrupt the filter processing. */ public FilterContext filter(FilterContext ctx) throws FilterException; } async-http-client-1.6.5/src/main/java/com/ning/http/client/filter/RequestFilter.java000066400000000000000000000026171166553056000304360ustar00rootroot00000000000000/* * Copyright (c) 2010-2011 Sonatype, Inc. All rights reserved. * * This program is licensed to you under the Apache License Version 2.0, * and you may not use this file except in compliance with the Apache License Version 2.0. * You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0. * * Unless required by applicable law or agreed to in writing, * software distributed under the Apache License Version 2.0 is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. */ package com.ning.http.client.filter; /** * A Filter interface that gets invoked before making an actual request. */ public interface RequestFilter { /** * An {@link com.ning.http.client.AsyncHttpProvider} will invoke {@link RequestFilter#filter} and will use the * returned {@link FilterContext#getRequest()} and {@link FilterContext#getAsyncHandler()} to continue the request * processing. * * @param ctx a {@link FilterContext} * @return {@link FilterContext}. The {@link FilterContext} instance may not the same as the original one. * @throws FilterException to interrupt the filter processing. */ public FilterContext filter(FilterContext ctx) throws FilterException; } async-http-client-1.6.5/src/main/java/com/ning/http/client/filter/ResponseFilter.java000066400000000000000000000035171166553056000306040ustar00rootroot00000000000000/* * Copyright (c) 2010-2011 Sonatype, Inc. All rights reserved. * * This program is licensed to you under the Apache License Version 2.0, * and you may not use this file except in compliance with the Apache License Version 2.0. * You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0. * * Unless required by applicable law or agreed to in writing, * software distributed under the Apache License Version 2.0 is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. */ package com.ning.http.client.filter; /** * A Filter interface that gets invoked before making the processing of the response bytes. {@link ResponseFilter} are invoked * before the actual response's status code get processed. That means authorization, proxy authentication and redirects * processing hasn't occured when {@link ResponseFilter} gets invoked. */ public interface ResponseFilter { /** * An {@link com.ning.http.client.AsyncHttpProvider} will invoke {@link ResponseFilter#filter} and will use the * returned {@link FilterContext#replayRequest()} and {@link FilterContext#getAsyncHandler()} to decide if the response * processing can continue. If {@link FilterContext#replayRequest()} return true, a new request will be made * using {@link FilterContext#getRequest()} and the current response processing will be ignored. * * @param ctx a {@link FilterContext} * @return {@link FilterContext}. The {@link FilterContext} instance may not the same as the original one. * @throws FilterException to interrupt the filter processing. */ public FilterContext filter(FilterContext ctx) throws FilterException; } async-http-client-1.6.5/src/main/java/com/ning/http/client/generators/000077500000000000000000000000001166553056000256535ustar00rootroot00000000000000async-http-client-1.6.5/src/main/java/com/ning/http/client/generators/ByteArrayBodyGenerator.java000066400000000000000000000040201166553056000331010ustar00rootroot00000000000000/* * Copyright (c) 2010-2011 Sonatype, Inc. All rights reserved. * * This program is licensed to you under the Apache License Version 2.0, * and you may not use this file except in compliance with the Apache License Version 2.0. * You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0. * * Unless required by applicable law or agreed to in writing, * software distributed under the Apache License Version 2.0 is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. */ package com.ning.http.client.generators; import com.ning.http.client.Body; import com.ning.http.client.BodyGenerator; import java.io.IOException; import java.nio.ByteBuffer; /** * A {@link BodyGenerator} backed by a byte array. */ public class ByteArrayBodyGenerator implements BodyGenerator { private final byte[] bytes; public ByteArrayBodyGenerator(byte[] bytes) { this.bytes = bytes; } protected final class ByteBody implements Body { private boolean eof = false; private int lastPosition = 0; public long getContentLength() { return bytes.length; } public long read(ByteBuffer byteBuffer) throws IOException { if (eof) { return -1; } if (bytes.length - lastPosition <= byteBuffer.capacity()) { byteBuffer.put(bytes, lastPosition, bytes.length); eof = true; } else { byteBuffer.put(bytes, lastPosition, byteBuffer.capacity()); lastPosition = bytes.length - byteBuffer.capacity(); } return bytes.length; } public void close() throws IOException { lastPosition = 0; eof = false; } } public Body createBody() throws IOException { return new ByteBody(); } } async-http-client-1.6.5/src/main/java/com/ning/http/client/generators/FileBodyGenerator.java000066400000000000000000000063761166553056000320760ustar00rootroot00000000000000/* * Copyright (c) 2010-2011 Sonatype, Inc. All rights reserved. * * This program is licensed to you under the Apache License Version 2.0, * and you may not use this file except in compliance with the Apache License Version 2.0. * You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0. * * Unless required by applicable law or agreed to in writing, * software distributed under the Apache License Version 2.0 is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. */ package com.ning.http.client.generators; import com.ning.http.client.BodyGenerator; import com.ning.http.client.RandomAccessBody; import java.io.File; import java.io.IOException; import java.io.RandomAccessFile; import java.nio.ByteBuffer; import java.nio.channels.FileChannel; import java.nio.channels.WritableByteChannel; /** * Creates a request body from the contents of a file. */ public class FileBodyGenerator implements BodyGenerator { private final File file; private final long regionSeek; private final long regionLength; public FileBodyGenerator(File file) { if (file == null) { throw new IllegalArgumentException("no file specified"); } this.file = file; this.regionLength = file.length(); this.regionSeek = 0; } public FileBodyGenerator(File file, long regionSeek, long regionLength) { if (file == null) { throw new IllegalArgumentException("no file specified"); } this.file = file; this.regionLength = regionLength; this.regionSeek = regionSeek; } public RandomAccessBody createBody() throws IOException { return new FileBody(file, regionSeek, regionLength); } protected static class FileBody implements RandomAccessBody { private final RandomAccessFile file; private final FileChannel channel; private final long length; public FileBody(File file) throws IOException { this.file = new RandomAccessFile(file, "r"); channel = this.file.getChannel(); length = file.length(); } public FileBody(File file, long regionSeek, long regionLength) throws IOException { this.file = new RandomAccessFile(file, "r"); channel = this.file.getChannel(); length = regionLength; if (regionSeek > 0) { this.file.seek(regionSeek); } } public long getContentLength() { return length; } public long read(ByteBuffer buffer) throws IOException { return channel.read(buffer); } public long transferTo(long position, long count, WritableByteChannel target) throws IOException { if (count > length) { count = length; } return channel.transferTo(position, count, target); } public void close() throws IOException { file.close(); } } } async-http-client-1.6.5/src/main/java/com/ning/http/client/generators/InputStreamBodyGenerator.java000066400000000000000000000077541166553056000334730ustar00rootroot00000000000000/* * Copyright (c) 2010-2011 Sonatype, Inc. All rights reserved. * * This program is licensed to you under the Apache License Version 2.0, * and you may not use this file except in compliance with the Apache License Version 2.0. * You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0. * * Unless required by applicable law or agreed to in writing, * software distributed under the Apache License Version 2.0 is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. */ package com.ning.http.client.generators; import com.ning.http.client.Body; import com.ning.http.client.BodyGenerator; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.IOException; import java.io.InputStream; import java.nio.ByteBuffer; /** * A {@link BodyGenerator} which use an {@link InputStream} for reading bytes, without having to read the entire * stream in memory. *

* NOTE: The {@link InputStream} must support the {@link InputStream#mark} and {@link java.io.InputStream#reset()} operation. * If not, mechanisms like authentication, redirect, or resumable download will not works. */ public class InputStreamBodyGenerator implements BodyGenerator { private final static byte[] END_PADDING = "\r\n".getBytes(); private final static byte[] ZERO = "0".getBytes(); private final InputStream inputStream; private final static Logger logger = LoggerFactory.getLogger(InputStreamBodyGenerator.class); public InputStreamBodyGenerator(InputStream inputStream) { this.inputStream = inputStream; if (inputStream.markSupported()) { inputStream.mark(0); } else { logger.warn("inputStream.markSupported() not supported. Some features will not works"); } } public Body createBody() throws IOException { return new ISBody(); } protected class ISBody implements Body { private boolean eof = false; private int endDataCount = 0; private byte[] chunk; public long getContentLength() { return -1; } public long read(ByteBuffer buffer) throws IOException { // To be safe. chunk = new byte[buffer.capacity() - 10]; int read = -1; try { read = inputStream.read(chunk); } catch (IOException ex) { logger.warn("Unable to read", ex); } if (read == -1) { // Since we are chuncked, we must output extra bytes before considering the input stream closed. // chunking requires to end the chunking: // - A Terminating chunk of "0\r\n".getBytes(), // - Then a separate packet of "\r\n".getBytes() if (!eof) { endDataCount++; if (endDataCount == 2) eof = true; if (endDataCount == 1) buffer.put(ZERO); buffer.put(END_PADDING); return buffer.position(); } else { if (inputStream.markSupported()) { inputStream.reset(); } eof = false; } return -1; } /** * Netty 3.2.3 doesn't support chunking encoding properly, so we chunk encoding ourself. */ buffer.put(Integer.toHexString(read).getBytes()); // Chunking is separated by "\r\n" buffer.put(END_PADDING); buffer.put(chunk, 0, read); // Was missing the final chunk \r\n. buffer.put(END_PADDING); return read; } public void close() throws IOException { inputStream.close(); } } } async-http-client-1.6.5/src/main/java/com/ning/http/client/listenable/000077500000000000000000000000001166553056000256245ustar00rootroot00000000000000async-http-client-1.6.5/src/main/java/com/ning/http/client/listenable/AbstractListenableFuture.java000066400000000000000000000051501166553056000334310ustar00rootroot00000000000000/* * Copyright (c) 2010-2011 Sonatype, Inc. All rights reserved. * * This program is licensed to you under the Apache License Version 2.0, * and you may not use this file except in compliance with the Apache License Version 2.0. * You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0. * * Unless required by applicable law or agreed to in writing, * software distributed under the Apache License Version 2.0 is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. */ /* * Copyright (C) 2007 Google Inc. * * 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. */ package com.ning.http.client.listenable; import com.ning.http.client.ListenableFuture; import java.util.concurrent.Executor; /** *

An abstract base implementation of the listener support provided by * {@link ListenableFuture}. This class uses an {@link ExecutionList} to * guarantee that all registered listeners will be executed. Listener/Executor * pairs are stored in the execution list and executed in the order in which * they were added, but because of thread scheduling issues there is no * guarantee that the JVM will execute them in order. In addition, listeners * added after the task is complete will be executed immediately, even if some * previously added listeners have not yet been executed. * * @author Sven Mawson * @since 1 */ public abstract class AbstractListenableFuture implements ListenableFuture { // The execution list to hold our executors. private final ExecutionList executionList = new ExecutionList(); /* * Adds a listener/executor pair to execution list to execute when this task * is completed. */ public ListenableFuture addListener(Runnable listener, Executor exec) { executionList.add(listener, exec); return this; } /* * Override the done method to execute the execution list. */ protected void done() { executionList.run(); } } async-http-client-1.6.5/src/main/java/com/ning/http/client/listenable/ExecutionList.java000066400000000000000000000122661166553056000312750ustar00rootroot00000000000000/* * Copyright (c) 2010-2011 Sonatype, Inc. All rights reserved. * * This program is licensed to you under the Apache License Version 2.0, * and you may not use this file except in compliance with the Apache License Version 2.0. * You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0. * * Unless required by applicable law or agreed to in writing, * software distributed under the Apache License Version 2.0 is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. */ /* * Copyright (C) 2007 Google Inc. * * 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. */ package com.ning.http.client.listenable; import java.util.Queue; import java.util.concurrent.Executor; import java.util.concurrent.LinkedBlockingQueue; import java.util.logging.Level; import java.util.logging.Logger; /** *

A list of ({@code Runnable}, {@code Executor}) pairs that guarantees * that every {@code Runnable} that is added using the add method will be * executed in its associated {@code Executor} after {@link #run()} is called. * {@code Runnable}s added after {@code run} is called are still guaranteed to * execute. * * @author Nishant Thakkar * @author Sven Mawson * @since 1 */ public final class ExecutionList implements Runnable { // Logger to log exceptions caught when running runnables. private static final Logger log = Logger.getLogger(ExecutionList.class.getName()); // The runnable,executor pairs to execute. private final Queue runnables = new LinkedBlockingQueue(); // Boolean we use mark when execution has started. Only accessed from within // synchronized blocks. private boolean executed = false; /** * Add the runnable/executor pair to the list of pairs to execute. Executes * the pair immediately if we've already started execution. */ public void add(Runnable runnable, Executor executor) { if (runnable == null) { throw new NullPointerException("Runnable is null"); } if (executor == null) { throw new NullPointerException("Executor is null"); } boolean executeImmediate = false; // Lock while we check state. We must maintain the lock while adding the // new pair so that another thread can't run the list out from under us. // We only add to the list if we have not yet started execution. synchronized (runnables) { if (!executed) { runnables.add(new RunnableExecutorPair(runnable, executor)); } else { executeImmediate = true; } } // Execute the runnable immediately. Because of scheduling this may end up // getting called before some of the previously added runnables, but we're // ok with that. If we want to change the contract to guarantee ordering // among runnables we'd have to modify the logic here to allow it. if (executeImmediate) { executor.execute(runnable); } } /** * Runs this execution list, executing all pairs in the order they were * added. Pairs added after this method has started executing the list will * be executed immediately. */ public void run() { // Lock while we update our state so the add method above will finish adding // any listeners before we start to run them. synchronized (runnables) { executed = true; } // At this point the runnables will never be modified by another // thread, so we are safe using it outside of the synchronized block. while (!runnables.isEmpty()) { runnables.poll().execute(); } } private static class RunnableExecutorPair { final Runnable runnable; final Executor executor; RunnableExecutorPair(Runnable runnable, Executor executor) { this.runnable = runnable; this.executor = executor; } void execute() { try { executor.execute(runnable); } catch (RuntimeException e) { // Log it and keep going, bad runnable and/or executor. Don't // punish the other runnables if we're given a bad one. We only // catch RuntimeException because we want Errors to propagate up. log.log(Level.SEVERE, "RuntimeException while executing runnable " + runnable + " with executor " + executor, e); } } } } async-http-client-1.6.5/src/main/java/com/ning/http/client/listener/000077500000000000000000000000001166553056000253275ustar00rootroot00000000000000async-http-client-1.6.5/src/main/java/com/ning/http/client/listener/TransferCompletionHandler.java000066400000000000000000000224501166553056000333110ustar00rootroot00000000000000/* * Copyright (c) 2010-2011 Sonatype, Inc. All rights reserved. * * This program is licensed to you under the Apache License Version 2.0, * and you may not use this file except in compliance with the Apache License Version 2.0. * You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0. * * Unless required by applicable law or agreed to in writing, * software distributed under the Apache License Version 2.0 is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. */ package com.ning.http.client.listener; import com.ning.http.client.AsyncCompletionHandlerBase; import com.ning.http.client.FluentCaseInsensitiveStringsMap; import com.ning.http.client.HttpResponseBodyPart; import com.ning.http.client.HttpResponseHeaders; import com.ning.http.client.Response; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.IOException; import java.nio.ByteBuffer; import java.util.List; import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.atomic.AtomicLong; /** * A {@link com.ning.http.client.AsyncHandler} that can be used to notify a set of {@link com.ning.http.client.listener.TransferListener} * * {@code AsyncHttpClient client = new AsyncHttpClient(); TransferCompletionHandler tl = new TransferCompletionHandler(); tl.addTransferListener(new TransferListener() { public void onRequestHeadersSent(FluentCaseInsensitiveStringsMap headers) { } public void onResponseHeadersReceived(FluentCaseInsensitiveStringsMap headers) { } public void onBytesReceived(ByteBuffer buffer) { } public void onBytesSent(ByteBuffer buffer) { } public void onRequestResponseCompleted() { } public void onThrowable(Throwable t) { } }); Response response = httpClient.prepareGet("http://...").execute(tl).get(); } * */ public class TransferCompletionHandler extends AsyncCompletionHandlerBase { private final static Logger logger = LoggerFactory.getLogger(TransferCompletionHandler.class); private final ConcurrentLinkedQueue listeners = new ConcurrentLinkedQueue(); private final boolean accumulateResponseBytes; private TransferAdapter transferAdapter; private AtomicLong bytesTransferred = new AtomicLong(); private AtomicLong totalBytesToTransfer = new AtomicLong(0); /** * Create a TransferCompletionHandler that will not accumulate bytes. The resulting {@link com.ning.http.client.Response#getResponseBody()}, * {@link com.ning.http.client.Response#getResponseBodyAsStream()} and {@link Response#getResponseBodyExcerpt(int)} will * throw an IllegalStateException if called. * */ public TransferCompletionHandler(){ this(false); } /** * Create a TransferCompletionHandler that can or cannot accumulate bytes and make it available when * {@link com.ning.http.client.Response#getResponseBody()} get called. The default is false. * * @param accumulateResponseBytes true to accumulates bytes in memory. */ public TransferCompletionHandler(boolean accumulateResponseBytes){ this.accumulateResponseBytes = accumulateResponseBytes; } /** * Add a {@link com.ning.http.client.listener.TransferListener} * @param t a {@link com.ning.http.client.listener.TransferListener} * @return this */ public TransferCompletionHandler addTransferListener(TransferListener t) { listeners.offer(t); return this; } /** * Remove a {@link com.ning.http.client.listener.TransferListener} * @param t a {@link com.ning.http.client.listener.TransferListener} * @return this */ public TransferCompletionHandler removeTransferListener(TransferListener t) { listeners.remove(t); return this; } /** * Associate a {@link com.ning.http.client.listener.TransferCompletionHandler.TransferAdapter} with this listener. * @param transferAdapter {@link TransferAdapter} */ public void transferAdapter(TransferAdapter transferAdapter) { this.transferAdapter = transferAdapter; } /** * {@inheritDoc} */ /* @Override */ public STATE onHeadersReceived(final HttpResponseHeaders headers) throws Exception { fireOnHeaderReceived(headers.getHeaders()); return super.onHeadersReceived(headers); } @Override public STATE onBodyPartReceived(final HttpResponseBodyPart content) throws Exception { STATE s = STATE.CONTINUE; if (accumulateResponseBytes) { s = super.onBodyPartReceived(content); } fireOnBytesReceived(content.getBodyPartBytes()); return s; } @Override public Response onCompleted(Response response) throws Exception { fireOnEnd(); return response; } /** * {@inheritDoc} */ public STATE onHeaderWriteCompleted() { List list = transferAdapter.getHeaders().get("Content-Length"); if (list != null && list.size() > 0 && list.get(0) != "") { totalBytesToTransfer.set(Long.valueOf(list.get(0))); } fireOnHeadersSent(transferAdapter.getHeaders()); return STATE.CONTINUE; } /** * {@inheritDoc} */ public STATE onContentWriteCompleted() { return STATE.CONTINUE; } /** * {@inheritDoc} */ public STATE onContentWriteProgress(long amount, long current, long total) { if (bytesTransferred.get() == -1) { return STATE.CONTINUE; } if (totalBytesToTransfer.get() == 0) { totalBytesToTransfer.set(total); } // We need to track the count because all is asynchronous and Netty may not invoke us on time. bytesTransferred.addAndGet(amount); if (transferAdapter != null) { byte[] bytes = new byte[(int) (amount)]; transferAdapter.getBytes(bytes); fireOnBytesSent(bytes); } return STATE.CONTINUE; } @Override public void onThrowable(Throwable t) { fireOnThrowable(t); } private void fireOnHeadersSent(FluentCaseInsensitiveStringsMap headers){ for (TransferListener l: listeners) { try { l.onRequestHeadersSent(headers); } catch (Throwable t) { l.onThrowable(t); } } } private void fireOnHeaderReceived(FluentCaseInsensitiveStringsMap headers){ for (TransferListener l: listeners) { try { l.onResponseHeadersReceived(headers); } catch (Throwable t) { l.onThrowable(t); } } } private void fireOnEnd(){ // There is a probability that the asynchronous listener never gets called, so we fake it at the end once // we are 100% sure the response has been received. long count = bytesTransferred.getAndSet(-1); if (count != totalBytesToTransfer.get()) { if (transferAdapter != null) { byte[] bytes = new byte[8192]; int leftBytes = (int) (totalBytesToTransfer.get() - count); int length = 8192; while (leftBytes > 0) { if (leftBytes > 8192) { leftBytes -= 8192; } else { length = leftBytes; leftBytes = 0; } if (length < 8192) { bytes = new byte[length]; } transferAdapter.getBytes(bytes); fireOnBytesSent(bytes); } } } for (TransferListener l: listeners) { try { l.onRequestResponseCompleted(); } catch (Throwable t) { l.onThrowable(t); } } } private void fireOnBytesReceived(byte[] b){ for (TransferListener l: listeners) { try { l.onBytesReceived(ByteBuffer.wrap(b)); } catch (Throwable t) { l.onThrowable(t); } } } private void fireOnBytesSent(byte[] b){ for (TransferListener l: listeners) { try { l.onBytesSent(ByteBuffer.wrap(b)); } catch (Throwable t) { l.onThrowable(t); } } } private void fireOnThrowable(Throwable t){ for (TransferListener l: listeners) { try { l.onThrowable(t); } catch (Throwable t2) { logger.warn("onThrowable", t2); } } } public abstract static class TransferAdapter { private final FluentCaseInsensitiveStringsMap headers; public TransferAdapter(FluentCaseInsensitiveStringsMap headers) throws IOException { this.headers = headers; } public FluentCaseInsensitiveStringsMap getHeaders() { return headers; } public abstract void getBytes(byte[] bytes); } } async-http-client-1.6.5/src/main/java/com/ning/http/client/listener/TransferListener.java000066400000000000000000000036621166553056000314730ustar00rootroot00000000000000/* * Copyright (c) 2010-2011 Sonatype, Inc. All rights reserved. * * This program is licensed to you under the Apache License Version 2.0, * and you may not use this file except in compliance with the Apache License Version 2.0. * You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0. * * Unless required by applicable law or agreed to in writing, * software distributed under the Apache License Version 2.0 is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. */ package com.ning.http.client.listener; import com.ning.http.client.FluentCaseInsensitiveStringsMap; import java.io.IOException; import java.nio.ByteBuffer; /** * A simple interface an application can implements in order to received byte transfer information. */ public interface TransferListener { /** * Invoked when the request bytes are starting to get send. */ public void onRequestHeadersSent(FluentCaseInsensitiveStringsMap headers); /** * Invoked when the response bytes are starting to get received. */ public void onResponseHeadersReceived(FluentCaseInsensitiveStringsMap headers); /** * Invoked every time response's chunk are received. * * @param buffer a {@link ByteBuffer} */ public void onBytesReceived(ByteBuffer buffer) throws IOException; /** * Invoked every time request's chunk are sent. * * @param buffer a {@link ByteBuffer} */ public void onBytesSent(ByteBuffer buffer); /** * Invoked when the response bytes are been fully received. */ public void onRequestResponseCompleted(); /** * Invoked when there is an unexpected issue. * * @param t a {@link Throwable} */ public void onThrowable(Throwable t); } async-http-client-1.6.5/src/main/java/com/ning/http/client/ntlm/000077500000000000000000000000001166553056000244545ustar00rootroot00000000000000async-http-client-1.6.5/src/main/java/com/ning/http/client/ntlm/NTLMEngine.java000066400000000000000000001441431166553056000272260ustar00rootroot00000000000000/* * Copyright (c) 2010-2011 Sonatype, Inc. All rights reserved. * * This program is licensed to you under the Apache License Version 2.0, * and you may not use this file except in compliance with the Apache License Version 2.0. * You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0. * * Unless required by applicable law or agreed to in writing, * software distributed under the Apache License Version 2.0 is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. */ /* * ==================================================================== * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Software Foundation. For more * information on the Apache Software Foundation, please see * . * */ package com.ning.http.client.ntlm; import com.ning.http.util.Base64; import javax.crypto.Cipher; import javax.crypto.spec.SecretKeySpec; import java.io.UnsupportedEncodingException; import java.security.Key; import java.security.MessageDigest; import java.util.Arrays; import java.util.Locale; /** * Provides an implementation for NTLMv1, NTLMv2, and NTLM2 Session forms of the NTLM * authentication protocol. * * @since 4.1 */ public class NTLMEngine { // Flags we use protected final static int FLAG_UNICODE_ENCODING = 0x00000001; protected final static int FLAG_TARGET_DESIRED = 0x00000004; protected final static int FLAG_NEGOTIATE_SIGN = 0x00000010; protected final static int FLAG_NEGOTIATE_SEAL = 0x00000020; protected final static int FLAG_NEGOTIATE_NTLM = 0x00000200; protected final static int FLAG_NEGOTIATE_ALWAYS_SIGN = 0x00008000; protected final static int FLAG_NEGOTIATE_NTLM2 = 0x00080000; protected final static int FLAG_NEGOTIATE_128 = 0x20000000; protected final static int FLAG_NEGOTIATE_KEY_EXCH = 0x40000000; /** Secure random generator */ private static final java.security.SecureRandom RND_GEN; static { java.security.SecureRandom rnd = null; try { rnd = java.security.SecureRandom.getInstance("SHA1PRNG"); } catch (Exception e) { } RND_GEN = rnd; } /** Character encoding */ static final String DEFAULT_CHARSET = "ASCII"; /** The character set to use for encoding the credentials */ private String credentialCharset = DEFAULT_CHARSET; /** The signature string as bytes in the default encoding */ private static byte[] SIGNATURE; static { byte[] bytesWithoutNull = new byte[0]; try { bytesWithoutNull = "NTLMSSP".getBytes("ASCII"); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } SIGNATURE = new byte[bytesWithoutNull.length + 1]; System.arraycopy(bytesWithoutNull, 0, SIGNATURE, 0, bytesWithoutNull.length); SIGNATURE[bytesWithoutNull.length] = (byte) 0x00; } /** * Returns the response for the given message. * * @param message * the message that was received from the server. * @param username * the username to authenticate with. * @param password * the password to authenticate with. * @param host * The host. * @param domain * the NT domain to authenticate in. * @return The response. * @throws NTLMEngineException * If the messages cannot be retrieved. */ final String getResponseFor(String message, String username, String password, String host, String domain) throws NTLMEngineException { final String response; if (message == null || message.trim().equals("")) { response = getType1Message(host, domain); } else { Type2Message t2m = new Type2Message(message); response = getType3Message(username, password, host, domain, t2m.getChallenge(), t2m .getFlags(), t2m.getTarget(), t2m.getTargetInfo()); } return response; } /** * Creates the first message (type 1 message) in the NTLM authentication * sequence. This message includes the user name, domain and host for the * authentication session. * * @param host * the computer name of the host requesting authentication. * @param domain * The domain to authenticate with. * @return String the message to add to the HTTP request header. */ String getType1Message(String host, String domain) throws NTLMEngineException { try { return new Type1Message(domain, host).getResponse(); } catch (UnsupportedEncodingException e) { throw new NTLMEngineException("Unsupported encoding" , e); } } /** * Creates the type 3 message using the given server nonce. The type 3 * message includes all the information for authentication, host, domain, * username and the result of encrypting the nonce sent by the server using * the user's password as the key. * * @param user * The user name. This should not include the domain name. * @param password * The password. * @param host * The host that is originating the authentication request. * @param domain * The domain to authenticate within. * @param nonce * the 8 byte array the server sent. * @return The type 3 message. * @throws NTLMEngineException * If {@encrypt(byte[],byte[])} fails. */ String getType3Message(String user, String password, String host, String domain, byte[] nonce, int type2Flags, String target, byte[] targetInformation) throws NTLMEngineException { try { return new Type3Message(domain, host, user, password, nonce, type2Flags, target, targetInformation).getResponse(); } catch (UnsupportedEncodingException e) { throw new NTLMEngineException("Unsupported encoding" , e); } } /** * @return Returns the credentialCharset. */ String getCredentialCharset() { return credentialCharset; } /** * @param credentialCharset * The credentialCharset to set. */ void setCredentialCharset(String credentialCharset) { this.credentialCharset = credentialCharset; } /** Strip dot suffix from a name */ private static String stripDotSuffix(String value) { int index = value.indexOf("."); if (index != -1) return value.substring(0, index); return value; } /** Convert host to standard form */ private static String convertHost(String host) { return stripDotSuffix(host); } /** Convert domain to standard form */ private static String convertDomain(String domain) { return stripDotSuffix(domain); } private static int readULong(byte[] src, int index) throws NTLMEngineException { if (src.length < index + 4) throw new NTLMEngineException("NTLM authentication - buffer too small for DWORD"); return (src[index] & 0xff) | ((src[index + 1] & 0xff) << 8) | ((src[index + 2] & 0xff) << 16) | ((src[index + 3] & 0xff) << 24); } private static int readUShort(byte[] src, int index) throws NTLMEngineException { if (src.length < index + 2) throw new NTLMEngineException("NTLM authentication - buffer too small for WORD"); return (src[index] & 0xff) | ((src[index + 1] & 0xff) << 8); } private static byte[] readSecurityBuffer(byte[] src, int index) throws NTLMEngineException { int length = readUShort(src, index); int offset = readULong(src, index + 4); if (src.length < offset + length) throw new NTLMEngineException( "NTLM authentication - buffer too small for data item"); byte[] buffer = new byte[length]; System.arraycopy(src, offset, buffer, 0, length); return buffer; } /** Calculate a challenge block */ private static byte[] makeRandomChallenge() throws NTLMEngineException { if (RND_GEN == null) { throw new NTLMEngineException("Random generator not available"); } byte[] rval = new byte[8]; synchronized (RND_GEN) { RND_GEN.nextBytes(rval); } return rval; } /** Calculate an NTLM2 challenge block */ private static byte[] makeNTLM2RandomChallenge() throws NTLMEngineException { if (RND_GEN == null) { throw new NTLMEngineException("Random generator not available"); } byte[] rval = new byte[24]; synchronized (RND_GEN) { RND_GEN.nextBytes(rval); } // 8-byte challenge, padded with zeros to 24 bytes. Arrays.fill(rval, 8, 24, (byte) 0x00); return rval; } /** * Calculates the LM Response for the given challenge, using the specified * password. * * @param password * The user's password. * @param challenge * The Type 2 challenge from the server. * * @return The LM Response. */ static byte[] getLMResponse(String password, byte[] challenge) throws NTLMEngineException { byte[] lmHash = lmHash(password); return lmResponse(lmHash, challenge); } /** * Calculates the NTLM Response for the given challenge, using the specified * password. * * @param password * The user's password. * @param challenge * The Type 2 challenge from the server. * * @return The NTLM Response. */ static byte[] getNTLMResponse(String password, byte[] challenge) throws NTLMEngineException { byte[] ntlmHash = ntlmHash(password); return lmResponse(ntlmHash, challenge); } /** * Calculates the NTLMv2 Response for the given challenge, using the * specified authentication target, username, password, target information * block, and client challenge. * * @param target * The authentication target (i.e., domain). * @param user * The username. * @param password * The user's password. * @param targetInformation * The target information block from the Type 2 message. * @param challenge * The Type 2 challenge from the server. * @param clientChallenge * The random 8-byte client challenge. * * @return The NTLMv2 Response. */ static byte[] getNTLMv2Response(String target, String user, String password, byte[] challenge, byte[] clientChallenge, byte[] targetInformation) throws NTLMEngineException { byte[] ntlmv2Hash = ntlmv2Hash(target, user, password); byte[] blob = createBlob(clientChallenge, targetInformation); return lmv2Response(ntlmv2Hash, challenge, blob); } /** * Calculates the LMv2 Response for the given challenge, using the specified * authentication target, username, password, and client challenge. * * @param target * The authentication target (i.e., domain). * @param user * The username. * @param password * The user's password. * @param challenge * The Type 2 challenge from the server. * @param clientChallenge * The random 8-byte client challenge. * * @return The LMv2 Response. */ static byte[] getLMv2Response(String target, String user, String password, byte[] challenge, byte[] clientChallenge) throws NTLMEngineException { byte[] ntlmv2Hash = ntlmv2Hash(target, user, password); return lmv2Response(ntlmv2Hash, challenge, clientChallenge); } /** * Calculates the NTLM2 Session Response for the given challenge, using the * specified password and client challenge. * * @param password * The user's password. * @param challenge * The Type 2 challenge from the server. * @param clientChallenge * The random 8-byte client challenge. * * @return The NTLM2 Session Response. This is placed in the NTLM response * field of the Type 3 message; the LM response field contains the * client challenge, null-padded to 24 bytes. */ static byte[] getNTLM2SessionResponse(String password, byte[] challenge, byte[] clientChallenge) throws NTLMEngineException { try { byte[] ntlmHash = ntlmHash(password); // Look up MD5 algorithm (was necessary on jdk 1.4.2) // This used to be needed, but java 1.5.0_07 includes the MD5 // algorithm (finally) // Class x = Class.forName("gnu.crypto.hash.MD5"); // Method updateMethod = x.getMethod("update",new // Class[]{byte[].class}); // Method digestMethod = x.getMethod("digest",new Class[0]); // Object mdInstance = x.newInstance(); // updateMethod.invoke(mdInstance,new Object[]{challenge}); // updateMethod.invoke(mdInstance,new Object[]{clientChallenge}); // byte[] digest = (byte[])digestMethod.invoke(mdInstance,new // Object[0]); MessageDigest md5 = MessageDigest.getInstance("MD5"); md5.update(challenge); md5.update(clientChallenge); byte[] digest = md5.digest(); byte[] sessionHash = new byte[8]; System.arraycopy(digest, 0, sessionHash, 0, 8); return lmResponse(ntlmHash, sessionHash); } catch (Exception e) { if (e instanceof NTLMEngineException) throw (NTLMEngineException) e; throw new NTLMEngineException(e.getMessage(), e); } } /** * Creates the LM Hash of the user's password. * * @param password * The password. * * @return The LM Hash of the given password, used in the calculation of the * LM Response. */ private static byte[] lmHash(String password) throws NTLMEngineException { try { byte[] oemPassword = password.toUpperCase(Locale.ENGLISH).getBytes("US-ASCII"); int length = Math.min(oemPassword.length, 14); byte[] keyBytes = new byte[14]; System.arraycopy(oemPassword, 0, keyBytes, 0, length); Key lowKey = createDESKey(keyBytes, 0); Key highKey = createDESKey(keyBytes, 7); byte[] magicConstant = "KGS!@#$%".getBytes("US-ASCII"); Cipher des = Cipher.getInstance("DES/ECB/NoPadding"); des.init(Cipher.ENCRYPT_MODE, lowKey); byte[] lowHash = des.doFinal(magicConstant); des.init(Cipher.ENCRYPT_MODE, highKey); byte[] highHash = des.doFinal(magicConstant); byte[] lmHash = new byte[16]; System.arraycopy(lowHash, 0, lmHash, 0, 8); System.arraycopy(highHash, 0, lmHash, 8, 8); return lmHash; } catch (Exception e) { throw new NTLMEngineException(e.getMessage(), e); } } /** * Creates the NTLM Hash of the user's password. * * @param password * The password. * * @return The NTLM Hash of the given password, used in the calculation of * the NTLM Response and the NTLMv2 and LMv2 Hashes. */ private static byte[] ntlmHash(String password) throws NTLMEngineException { try { byte[] unicodePassword = password.getBytes("UnicodeLittleUnmarked"); MD4 md4 = new MD4(); md4.update(unicodePassword); return md4.getOutput(); } catch (java.io.UnsupportedEncodingException e) { throw new NTLMEngineException("Unicode not supported: " + e.getMessage(), e); } } /** * Creates the NTLMv2 Hash of the user's password. * * @param target * The authentication target (i.e., domain). * @param user * The username. * @param password * The password. * * @return The NTLMv2 Hash, used in the calculation of the NTLMv2 and LMv2 * Responses. */ private static byte[] ntlmv2Hash(String target, String user, String password) throws NTLMEngineException { try { byte[] ntlmHash = ntlmHash(password); HMACMD5 hmacMD5 = new HMACMD5(ntlmHash); // Upper case username, mixed case target!! hmacMD5.update(user.toUpperCase(Locale.ENGLISH).getBytes("UnicodeLittleUnmarked")); hmacMD5.update(target.getBytes("UnicodeLittleUnmarked")); return hmacMD5.getOutput(); } catch (java.io.UnsupportedEncodingException e) { throw new NTLMEngineException("Unicode not supported! " + e.getMessage(), e); } } /** * Creates the LM Response from the given hash and Type 2 challenge. * * @param hash * The LM or NTLM Hash. * @param challenge * The server challenge from the Type 2 message. * * @return The response (either LM or NTLM, depending on the provided hash). */ private static byte[] lmResponse(byte[] hash, byte[] challenge) throws NTLMEngineException { try { byte[] keyBytes = new byte[21]; System.arraycopy(hash, 0, keyBytes, 0, 16); Key lowKey = createDESKey(keyBytes, 0); Key middleKey = createDESKey(keyBytes, 7); Key highKey = createDESKey(keyBytes, 14); Cipher des = Cipher.getInstance("DES/ECB/NoPadding"); des.init(Cipher.ENCRYPT_MODE, lowKey); byte[] lowResponse = des.doFinal(challenge); des.init(Cipher.ENCRYPT_MODE, middleKey); byte[] middleResponse = des.doFinal(challenge); des.init(Cipher.ENCRYPT_MODE, highKey); byte[] highResponse = des.doFinal(challenge); byte[] lmResponse = new byte[24]; System.arraycopy(lowResponse, 0, lmResponse, 0, 8); System.arraycopy(middleResponse, 0, lmResponse, 8, 8); System.arraycopy(highResponse, 0, lmResponse, 16, 8); return lmResponse; } catch (Exception e) { throw new NTLMEngineException(e.getMessage(), e); } } /** * Creates the LMv2 Response from the given hash, client data, and Type 2 * challenge. * * @param hash * The NTLMv2 Hash. * @param clientData * The client data (blob or client challenge). * @param challenge * The server challenge from the Type 2 message. * * @return The response (either NTLMv2 or LMv2, depending on the client * data). */ private static byte[] lmv2Response(byte[] hash, byte[] challenge, byte[] clientData) throws NTLMEngineException { HMACMD5 hmacMD5 = new HMACMD5(hash); hmacMD5.update(challenge); hmacMD5.update(clientData); byte[] mac = hmacMD5.getOutput(); byte[] lmv2Response = new byte[mac.length + clientData.length]; System.arraycopy(mac, 0, lmv2Response, 0, mac.length); System.arraycopy(clientData, 0, lmv2Response, mac.length, clientData.length); return lmv2Response; } /** * Creates the NTLMv2 blob from the given target information block and * client challenge. * * @param targetInformation * The target information block from the Type 2 message. * @param clientChallenge * The random 8-byte client challenge. * * @return The blob, used in the calculation of the NTLMv2 Response. */ private static byte[] createBlob(byte[] clientChallenge, byte[] targetInformation) { byte[] blobSignature = new byte[] { (byte) 0x01, (byte) 0x01, (byte) 0x00, (byte) 0x00 }; byte[] reserved = new byte[] { (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00 }; byte[] unknown1 = new byte[] { (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00 }; long time = System.currentTimeMillis(); time += 11644473600000l; // milliseconds from January 1, 1601 -> epoch. time *= 10000; // tenths of a microsecond. // convert to little-endian byte array. byte[] timestamp = new byte[8]; for (int i = 0; i < 8; i++) { timestamp[i] = (byte) time; time >>>= 8; } byte[] blob = new byte[blobSignature.length + reserved.length + timestamp.length + 8 + unknown1.length + targetInformation.length]; int offset = 0; System.arraycopy(blobSignature, 0, blob, offset, blobSignature.length); offset += blobSignature.length; System.arraycopy(reserved, 0, blob, offset, reserved.length); offset += reserved.length; System.arraycopy(timestamp, 0, blob, offset, timestamp.length); offset += timestamp.length; System.arraycopy(clientChallenge, 0, blob, offset, 8); offset += 8; System.arraycopy(unknown1, 0, blob, offset, unknown1.length); offset += unknown1.length; System.arraycopy(targetInformation, 0, blob, offset, targetInformation.length); return blob; } /** * Creates a DES encryption key from the given key material. * * @param bytes * A byte array containing the DES key material. * @param offset * The offset in the given byte array at which the 7-byte key * material starts. * * @return A DES encryption key created from the key material starting at * the specified offset in the given byte array. */ private static Key createDESKey(byte[] bytes, int offset) { byte[] keyBytes = new byte[7]; System.arraycopy(bytes, offset, keyBytes, 0, 7); byte[] material = new byte[8]; material[0] = keyBytes[0]; material[1] = (byte) (keyBytes[0] << 7 | (keyBytes[1] & 0xff) >>> 1); material[2] = (byte) (keyBytes[1] << 6 | (keyBytes[2] & 0xff) >>> 2); material[3] = (byte) (keyBytes[2] << 5 | (keyBytes[3] & 0xff) >>> 3); material[4] = (byte) (keyBytes[3] << 4 | (keyBytes[4] & 0xff) >>> 4); material[5] = (byte) (keyBytes[4] << 3 | (keyBytes[5] & 0xff) >>> 5); material[6] = (byte) (keyBytes[5] << 2 | (keyBytes[6] & 0xff) >>> 6); material[7] = (byte) (keyBytes[6] << 1); oddParity(material); return new SecretKeySpec(material, "DES"); } /** * Applies odd parity to the given byte array. * * @param bytes * The data whose parity bits are to be adjusted for odd parity. */ private static void oddParity(byte[] bytes) { for (int i = 0; i < bytes.length; i++) { byte b = bytes[i]; boolean needsParity = (((b >>> 7) ^ (b >>> 6) ^ (b >>> 5) ^ (b >>> 4) ^ (b >>> 3) ^ (b >>> 2) ^ (b >>> 1)) & 0x01) == 0; if (needsParity) { bytes[i] |= (byte) 0x01; } else { bytes[i] &= (byte) 0xfe; } } } /** NTLM message generation, base class */ static class NTLMMessage { /** The current response */ private byte[] messageContents = null; /** The current output position */ private int currentOutputPosition = 0; /** Constructor to use when message contents are not yet known */ NTLMMessage() { } /** Constructor to use when message contents are known */ NTLMMessage(String messageBody, int expectedType) throws NTLMEngineException { messageContents = Base64.decode(messageBody); // Look for NTLM message if (messageContents.length < SIGNATURE.length) throw new NTLMEngineException("NTLM message decoding error - packet too short"); int i = 0; while (i < SIGNATURE.length) { if (messageContents[i] != SIGNATURE[i]) throw new NTLMEngineException( "NTLM message expected - instead got unrecognized bytes"); i++; } // Check to be sure there's a type 2 message indicator next int type = readULong(SIGNATURE.length); if (type != expectedType) throw new NTLMEngineException("NTLM type " + Integer.toString(expectedType) + " message expected - instead got type " + Integer.toString(type)); currentOutputPosition = messageContents.length; } /** * Get the length of the signature and flags, so calculations can adjust * offsets accordingly. */ protected int getPreambleLength() { return SIGNATURE.length + 4; } /** Get the message length */ protected int getMessageLength() { return currentOutputPosition; } /** Read a byte from a position within the message buffer */ protected byte readByte(int position) throws NTLMEngineException { if (messageContents.length < position + 1) throw new NTLMEngineException("NTLM: Message too short"); return messageContents[position]; } /** Read a bunch of bytes from a position in the message buffer */ protected void readBytes(byte[] buffer, int position) throws NTLMEngineException { if (messageContents.length < position + buffer.length) throw new NTLMEngineException("NTLM: Message too short"); System.arraycopy(messageContents, position, buffer, 0, buffer.length); } /** Read a ushort from a position within the message buffer */ protected int readUShort(int position) throws NTLMEngineException { return NTLMEngine.readUShort(messageContents, position); } /** Read a ulong from a position within the message buffer */ protected int readULong(int position) throws NTLMEngineException { return NTLMEngine.readULong(messageContents, position); } /** Read a security buffer from a position within the message buffer */ protected byte[] readSecurityBuffer(int position) throws NTLMEngineException { return NTLMEngine.readSecurityBuffer(messageContents, position); } /** * Prepares the object to create a response of the given length. * * @param maxlength * the maximum length of the response to prepare, not * including the type and the signature (which this method * adds). */ protected void prepareResponse(int maxlength, int messageType) { messageContents = new byte[maxlength]; currentOutputPosition = 0; addBytes(SIGNATURE); addULong(messageType); } /** * Adds the given byte to the response. * * @param b * the byte to add. */ protected void addByte(byte b) { messageContents[currentOutputPosition] = b; currentOutputPosition++; } /** * Adds the given bytes to the response. * * @param bytes * the bytes to add. */ protected void addBytes(byte[] bytes) { for (int i = 0; i < bytes.length; i++) { messageContents[currentOutputPosition] = bytes[i]; currentOutputPosition++; } } /** Adds a USHORT to the response */ protected void addUShort(int value) { addByte((byte) (value & 0xff)); addByte((byte) (value >> 8 & 0xff)); } /** Adds a ULong to the response */ protected void addULong(int value) { addByte((byte) (value & 0xff)); addByte((byte) (value >> 8 & 0xff)); addByte((byte) (value >> 16 & 0xff)); addByte((byte) (value >> 24 & 0xff)); } /** * Returns the response that has been generated after shrinking the * array if required and base64 encodes the response. * * @return The response as above. */ String getResponse() throws UnsupportedEncodingException { byte[] resp; if (messageContents.length > currentOutputPosition) { byte[] tmp = new byte[currentOutputPosition]; for (int i = 0; i < currentOutputPosition; i++) { tmp[i] = messageContents[i]; } resp = tmp; } else { resp = messageContents; } return new String(Base64.encode(resp)); } } /** Type 1 message assembly class */ static class Type1Message extends NTLMMessage { protected byte[] hostBytes; protected byte[] domainBytes; /** Constructor. Include the arguments the message will need */ Type1Message(String domain, String host) throws NTLMEngineException { super(); try { // Strip off domain name from the host! host = convertHost(host); // Use only the base domain name! domain = convertDomain(domain); hostBytes = host.getBytes("UnicodeLittleUnmarked"); domainBytes = domain.toUpperCase(Locale.ENGLISH).getBytes("UnicodeLittleUnmarked"); } catch (java.io.UnsupportedEncodingException e) { throw new NTLMEngineException("Unicode unsupported: " + e.getMessage(), e); } } /** * Getting the response involves building the message before returning * it */ @Override String getResponse() throws UnsupportedEncodingException { // Now, build the message. Calculate its length first, including // signature or type. int finalLength = 32 + hostBytes.length + domainBytes.length; // Set up the response. This will initialize the signature, message // type, and flags. prepareResponse(finalLength, 1); // Flags. These are the complete set of flags we support. addULong(FLAG_NEGOTIATE_NTLM | FLAG_NEGOTIATE_NTLM2 | FLAG_NEGOTIATE_SIGN | FLAG_NEGOTIATE_SEAL | /* * FLAG_NEGOTIATE_ALWAYS_SIGN | FLAG_NEGOTIATE_KEY_EXCH | */ FLAG_UNICODE_ENCODING | FLAG_TARGET_DESIRED | FLAG_NEGOTIATE_128); // Domain length (two times). addUShort(domainBytes.length); addUShort(domainBytes.length); // Domain offset. addULong(hostBytes.length + 32); // Host length (two times). addUShort(hostBytes.length); addUShort(hostBytes.length); // Host offset (always 32). addULong(32); // Host String. addBytes(hostBytes); // Domain String. addBytes(domainBytes); return super.getResponse(); } } /** Type 2 message class */ static class Type2Message extends NTLMMessage { protected byte[] challenge; protected String target; protected byte[] targetInfo; protected int flags; Type2Message(String message) throws NTLMEngineException { super(message, 2); // Parse out the rest of the info we need from the message // The nonce is the 8 bytes starting from the byte in position 24. challenge = new byte[8]; readBytes(challenge, 24); flags = readULong(20); if ((flags & FLAG_UNICODE_ENCODING) == 0) throw new NTLMEngineException( "NTLM type 2 message has flags that make no sense: " + Integer.toString(flags)); // Do the target! target = null; // The TARGET_DESIRED flag is said to not have understood semantics // in Type2 messages, so use the length of the packet to decide // how to proceed instead if (getMessageLength() >= 12 + 8) { byte[] bytes = readSecurityBuffer(12); if (bytes.length != 0) { try { target = new String(bytes, "UnicodeLittleUnmarked"); } catch (java.io.UnsupportedEncodingException e) { throw new NTLMEngineException(e.getMessage(), e); } } } // Do the target info! targetInfo = null; // TARGET_DESIRED flag cannot be relied on, so use packet length if (getMessageLength() >= 40 + 8) { byte[] bytes = readSecurityBuffer(40); if (bytes.length != 0) { targetInfo = bytes; } } } /** Retrieve the challenge */ byte[] getChallenge() { return challenge; } /** Retrieve the target */ String getTarget() { return target; } /** Retrieve the target info */ byte[] getTargetInfo() { return targetInfo; } /** Retrieve the response flags */ int getFlags() { return flags; } } /** Type 3 message assembly class */ static class Type3Message extends NTLMMessage { // Response flags from the type2 message protected int type2Flags; protected byte[] domainBytes; protected byte[] hostBytes; protected byte[] userBytes; protected byte[] lmResp; protected byte[] ntResp; /** Constructor. Pass the arguments we will need */ Type3Message(String domain, String host, String user, String password, byte[] nonce, int type2Flags, String target, byte[] targetInformation) throws NTLMEngineException { // Save the flags this.type2Flags = type2Flags; // Strip off domain name from the host! host = convertHost(host); // Use only the base domain name! domain = convertDomain(domain); // Use the new code to calculate the responses, including v2 if that // seems warranted. try { if (targetInformation != null && target != null) { byte[] clientChallenge = makeRandomChallenge(); ntResp = getNTLMv2Response(target, user, password, nonce, clientChallenge, targetInformation); lmResp = getLMv2Response(target, user, password, nonce, clientChallenge); } else { if ((type2Flags & FLAG_NEGOTIATE_NTLM2) != 0) { // NTLM2 session stuff is requested byte[] clientChallenge = makeNTLM2RandomChallenge(); ntResp = getNTLM2SessionResponse(password, nonce, clientChallenge); lmResp = clientChallenge; // All the other flags we send (signing, sealing, key // exchange) are supported, but they don't do anything // at all in an // NTLM2 context! So we're done at this point. } else { ntResp = getNTLMResponse(password, nonce); lmResp = getLMResponse(password, nonce); } } } catch (NTLMEngineException e) { // This likely means we couldn't find the MD4 hash algorithm - // fail back to just using LM ntResp = new byte[0]; lmResp = getLMResponse(password, nonce); } try { domainBytes = domain.toUpperCase(Locale.ENGLISH).getBytes("UnicodeLittleUnmarked"); hostBytes = host.getBytes("UnicodeLittleUnmarked"); userBytes = user.getBytes("UnicodeLittleUnmarked"); } catch (java.io.UnsupportedEncodingException e) { throw new NTLMEngineException("Unicode not supported: " + e.getMessage(), e); } } /** Assemble the response */ @Override String getResponse() throws UnsupportedEncodingException { int ntRespLen = ntResp.length; int lmRespLen = lmResp.length; int domainLen = domainBytes.length; int hostLen = hostBytes.length; int userLen = userBytes.length; // Calculate the layout within the packet int lmRespOffset = 64; int ntRespOffset = lmRespOffset + lmRespLen; int domainOffset = ntRespOffset + ntRespLen; int userOffset = domainOffset + domainLen; int hostOffset = userOffset + userLen; int sessionKeyOffset = hostOffset + hostLen; int finalLength = sessionKeyOffset + 0; // Start the response. Length includes signature and type prepareResponse(finalLength, 3); // LM Resp Length (twice) addUShort(lmRespLen); addUShort(lmRespLen); // LM Resp Offset addULong(lmRespOffset); // NT Resp Length (twice) addUShort(ntRespLen); addUShort(ntRespLen); // NT Resp Offset addULong(ntRespOffset); // Domain length (twice) addUShort(domainLen); addUShort(domainLen); // Domain offset. addULong(domainOffset); // User Length (twice) addUShort(userLen); addUShort(userLen); // User offset addULong(userOffset); // Host length (twice) addUShort(hostLen); addUShort(hostLen); // Host offset addULong(hostOffset); // 4 bytes of zeros - not sure what this is addULong(0); // Message length addULong(finalLength); // Flags. Currently: NEGOTIATE_NTLM + UNICODE_ENCODING + // TARGET_DESIRED + NEGOTIATE_128 addULong(FLAG_NEGOTIATE_NTLM | FLAG_UNICODE_ENCODING | FLAG_TARGET_DESIRED | FLAG_NEGOTIATE_128 | (type2Flags & FLAG_NEGOTIATE_NTLM2) | (type2Flags & FLAG_NEGOTIATE_SIGN) | (type2Flags & FLAG_NEGOTIATE_SEAL) | (type2Flags & FLAG_NEGOTIATE_KEY_EXCH) | (type2Flags & FLAG_NEGOTIATE_ALWAYS_SIGN)); // Add the actual data addBytes(lmResp); addBytes(ntResp); addBytes(domainBytes); addBytes(userBytes); addBytes(hostBytes); return super.getResponse(); } } static void writeULong(byte[] buffer, int value, int offset) { buffer[offset] = (byte) (value & 0xff); buffer[offset + 1] = (byte) (value >> 8 & 0xff); buffer[offset + 2] = (byte) (value >> 16 & 0xff); buffer[offset + 3] = (byte) (value >> 24 & 0xff); } static int F(int x, int y, int z) { return ((x & y) | (~x & z)); } static int G(int x, int y, int z) { return ((x & y) | (x & z) | (y & z)); } static int H(int x, int y, int z) { return (x ^ y ^ z); } static int rotintlft(int val, int numbits) { return ((val << numbits) | (val >>> (32 - numbits))); } /** * Cryptography support - MD4. The following class was based loosely on the * RFC and on code found at http://www.cs.umd.edu/~harry/jotp/src/md.java. * Code correctness was verified by looking at MD4.java from the jcifs * library (http://jcifs.samba.org). It was massaged extensively to the * final form found here by Karl Wright (kwright@metacarta.com). */ static class MD4 { protected int A = 0x67452301; protected int B = 0xefcdab89; protected int C = 0x98badcfe; protected int D = 0x10325476; protected long count = 0L; protected byte[] dataBuffer = new byte[64]; MD4() { } void update(byte[] input) { // We always deal with 512 bits at a time. Correspondingly, there is // a buffer 64 bytes long that we write data into until it gets // full. int curBufferPos = (int) (count & 63L); int inputIndex = 0; while (input.length - inputIndex + curBufferPos >= dataBuffer.length) { // We have enough data to do the next step. Do a partial copy // and a transform, updating inputIndex and curBufferPos // accordingly int transferAmt = dataBuffer.length - curBufferPos; System.arraycopy(input, inputIndex, dataBuffer, curBufferPos, transferAmt); count += transferAmt; curBufferPos = 0; inputIndex += transferAmt; processBuffer(); } // If there's anything left, copy it into the buffer and leave it. // We know there's not enough left to process. if (inputIndex < input.length) { int transferAmt = input.length - inputIndex; System.arraycopy(input, inputIndex, dataBuffer, curBufferPos, transferAmt); count += transferAmt; curBufferPos += transferAmt; } } byte[] getOutput() { // Feed pad/length data into engine. This must round out the input // to a multiple of 512 bits. int bufferIndex = (int) (count & 63L); int padLen = (bufferIndex < 56) ? (56 - bufferIndex) : (120 - bufferIndex); byte[] postBytes = new byte[padLen + 8]; // Leading 0x80, specified amount of zero padding, then length in // bits. postBytes[0] = (byte) 0x80; // Fill out the last 8 bytes with the length for (int i = 0; i < 8; i++) { postBytes[padLen + i] = (byte) ((count * 8) >>> (8 * i)); } // Update the engine update(postBytes); // Calculate final result byte[] result = new byte[16]; writeULong(result, A, 0); writeULong(result, B, 4); writeULong(result, C, 8); writeULong(result, D, 12); return result; } protected void processBuffer() { // Convert current buffer to 16 ulongs int[] d = new int[16]; for (int i = 0; i < 16; i++) { d[i] = (dataBuffer[i * 4] & 0xff) + ((dataBuffer[i * 4 + 1] & 0xff) << 8) + ((dataBuffer[i * 4 + 2] & 0xff) << 16) + ((dataBuffer[i * 4 + 3] & 0xff) << 24); } // Do a round of processing int AA = A; int BB = B; int CC = C; int DD = D; round1(d); round2(d); round3(d); A += AA; B += BB; C += CC; D += DD; } protected void round1(int[] d) { A = rotintlft((A + F(B, C, D) + d[0]), 3); D = rotintlft((D + F(A, B, C) + d[1]), 7); C = rotintlft((C + F(D, A, B) + d[2]), 11); B = rotintlft((B + F(C, D, A) + d[3]), 19); A = rotintlft((A + F(B, C, D) + d[4]), 3); D = rotintlft((D + F(A, B, C) + d[5]), 7); C = rotintlft((C + F(D, A, B) + d[6]), 11); B = rotintlft((B + F(C, D, A) + d[7]), 19); A = rotintlft((A + F(B, C, D) + d[8]), 3); D = rotintlft((D + F(A, B, C) + d[9]), 7); C = rotintlft((C + F(D, A, B) + d[10]), 11); B = rotintlft((B + F(C, D, A) + d[11]), 19); A = rotintlft((A + F(B, C, D) + d[12]), 3); D = rotintlft((D + F(A, B, C) + d[13]), 7); C = rotintlft((C + F(D, A, B) + d[14]), 11); B = rotintlft((B + F(C, D, A) + d[15]), 19); } protected void round2(int[] d) { A = rotintlft((A + G(B, C, D) + d[0] + 0x5a827999), 3); D = rotintlft((D + G(A, B, C) + d[4] + 0x5a827999), 5); C = rotintlft((C + G(D, A, B) + d[8] + 0x5a827999), 9); B = rotintlft((B + G(C, D, A) + d[12] + 0x5a827999), 13); A = rotintlft((A + G(B, C, D) + d[1] + 0x5a827999), 3); D = rotintlft((D + G(A, B, C) + d[5] + 0x5a827999), 5); C = rotintlft((C + G(D, A, B) + d[9] + 0x5a827999), 9); B = rotintlft((B + G(C, D, A) + d[13] + 0x5a827999), 13); A = rotintlft((A + G(B, C, D) + d[2] + 0x5a827999), 3); D = rotintlft((D + G(A, B, C) + d[6] + 0x5a827999), 5); C = rotintlft((C + G(D, A, B) + d[10] + 0x5a827999), 9); B = rotintlft((B + G(C, D, A) + d[14] + 0x5a827999), 13); A = rotintlft((A + G(B, C, D) + d[3] + 0x5a827999), 3); D = rotintlft((D + G(A, B, C) + d[7] + 0x5a827999), 5); C = rotintlft((C + G(D, A, B) + d[11] + 0x5a827999), 9); B = rotintlft((B + G(C, D, A) + d[15] + 0x5a827999), 13); } protected void round3(int[] d) { A = rotintlft((A + H(B, C, D) + d[0] + 0x6ed9eba1), 3); D = rotintlft((D + H(A, B, C) + d[8] + 0x6ed9eba1), 9); C = rotintlft((C + H(D, A, B) + d[4] + 0x6ed9eba1), 11); B = rotintlft((B + H(C, D, A) + d[12] + 0x6ed9eba1), 15); A = rotintlft((A + H(B, C, D) + d[2] + 0x6ed9eba1), 3); D = rotintlft((D + H(A, B, C) + d[10] + 0x6ed9eba1), 9); C = rotintlft((C + H(D, A, B) + d[6] + 0x6ed9eba1), 11); B = rotintlft((B + H(C, D, A) + d[14] + 0x6ed9eba1), 15); A = rotintlft((A + H(B, C, D) + d[1] + 0x6ed9eba1), 3); D = rotintlft((D + H(A, B, C) + d[9] + 0x6ed9eba1), 9); C = rotintlft((C + H(D, A, B) + d[5] + 0x6ed9eba1), 11); B = rotintlft((B + H(C, D, A) + d[13] + 0x6ed9eba1), 15); A = rotintlft((A + H(B, C, D) + d[3] + 0x6ed9eba1), 3); D = rotintlft((D + H(A, B, C) + d[11] + 0x6ed9eba1), 9); C = rotintlft((C + H(D, A, B) + d[7] + 0x6ed9eba1), 11); B = rotintlft((B + H(C, D, A) + d[15] + 0x6ed9eba1), 15); } } /** * Cryptography support - HMACMD5 - algorithmically based on various web * resources by Karl Wright */ static class HMACMD5 { protected byte[] ipad; protected byte[] opad; protected MessageDigest md5; HMACMD5(byte[] key) throws NTLMEngineException { try { md5 = MessageDigest.getInstance("MD5"); } catch (Exception ex) { // Umm, the algorithm doesn't exist - throw an // NTLMEngineException! throw new NTLMEngineException( "Error getting md5 message digest implementation: " + ex.getMessage(), ex); } // Initialize the pad buffers with the key ipad = new byte[64]; opad = new byte[64]; int keyLength = key.length; if (keyLength > 64) { // Use MD5 of the key instead, as described in RFC 2104 md5.update(key); key = md5.digest(); keyLength = key.length; } int i = 0; while (i < keyLength) { ipad[i] = (byte) (key[i] ^ (byte) 0x36); opad[i] = (byte) (key[i] ^ (byte) 0x5c); i++; } while (i < 64) { ipad[i] = (byte) 0x36; opad[i] = (byte) 0x5c; i++; } // Very important: update the digest with the ipad buffer md5.reset(); md5.update(ipad); } /** Grab the current digest. This is the "answer". */ byte[] getOutput() { byte[] digest = md5.digest(); md5.update(opad); return md5.digest(digest); } /** Update by adding a complete array */ void update(byte[] input) { md5.update(input); } /** Update the algorithm */ void update(byte[] input, int offset, int length) { md5.update(input, offset, length); } } public String generateType1Msg( final String domain, final String workstation) throws NTLMEngineException { return getType1Message(workstation, domain); } public String generateType3Msg( final String username, final String password, final String domain, final String workstation, final String challenge) throws NTLMEngineException { Type2Message t2m = new Type2Message(challenge); return getType3Message( username, password, workstation, domain, t2m.getChallenge(), t2m.getFlags(), t2m.getTarget(), t2m.getTargetInfo()); } } async-http-client-1.6.5/src/main/java/com/ning/http/client/ntlm/NTLMEngineException.java000066400000000000000000000054071166553056000311040ustar00rootroot00000000000000/* * Copyright (c) 2010-2011 Sonatype, Inc. All rights reserved. * * This program is licensed to you under the Apache License Version 2.0, * and you may not use this file except in compliance with the Apache License Version 2.0. * You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0. * * Unless required by applicable law or agreed to in writing, * software distributed under the Apache License Version 2.0 is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. */ /* * ==================================================================== * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Software Foundation. For more * information on the Apache Software Foundation, please see * . * */ package com.ning.http.client.ntlm; /** * Signals NTLM protocol failure. * * * @since 4.0 */ public class NTLMEngineException extends Exception { private static final long serialVersionUID = 6027981323731768824L; public NTLMEngineException() { super(); } /** * Creates a new NTLMEngineException with the specified message. * * @param message the exception detail message */ public NTLMEngineException(String message) { super(message); } /** * Creates a new NTLMEngineException with the specified detail message and cause. * * @param message the exception detail message * @param cause the Throwable that caused this exception, or null * if the cause is unavailable, unknown, or not a Throwable */ public NTLMEngineException(String message, Throwable cause) { super(message, cause); } } async-http-client-1.6.5/src/main/java/com/ning/http/client/oauth/000077500000000000000000000000001166553056000246225ustar00rootroot00000000000000async-http-client-1.6.5/src/main/java/com/ning/http/client/oauth/ConsumerKey.java000066400000000000000000000035761166553056000277440ustar00rootroot00000000000000/* * Copyright 2010 Ning, Inc. * * Ning licenses this file to you 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. * */ package com.ning.http.client.oauth; /** * Value class for OAuth consumer keys. */ public class ConsumerKey { private final String key; private final String secret; public ConsumerKey(String key, String secret) { this.key = key; this.secret = secret; } public String getKey() { return key; } public String getSecret() { return secret; } @Override public String toString() { StringBuilder sb = new StringBuilder("{Consumer key, key="); appendValue(sb, key); sb.append(", secret="); appendValue(sb, secret); sb.append("}"); return sb.toString(); } private void appendValue(StringBuilder sb, String value) { if (value == null) { sb.append("null"); } else { sb.append('"'); sb.append(value); sb.append('"'); } } @Override public int hashCode() { return key.hashCode() + secret.hashCode(); } @Override public boolean equals(Object o) { if (o == this) return true; if (o == null || o.getClass() != getClass()) return false; ConsumerKey other = (ConsumerKey) o; return key.equals(other.key) && secret.equals(other.secret); } } async-http-client-1.6.5/src/main/java/com/ning/http/client/oauth/OAuthSignatureCalculator.java000066400000000000000000000242071166553056000324060ustar00rootroot00000000000000/* * Copyright 2010 Ning, Inc. * * Ning licenses this file to you 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. * */ package com.ning.http.client.oauth; import com.ning.http.client.FluentStringsMap; import com.ning.http.client.Request; import com.ning.http.client.RequestBuilderBase; import com.ning.http.client.SignatureCalculator; import com.ning.http.util.Base64; import com.ning.http.util.UTF8Codec; import com.ning.http.util.UTF8UrlEncoder; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Map; import java.util.Random; /** * Simple OAuth signature calculator that can used for constructing client signatures * for accessing services that use OAuth for authorization. *

* Supports most common signature inclusion and calculation methods: HMAC-SHA1 for * calculation, and Header inclusion as inclusion method. Nonce generation uses * simple random numbers with base64 encoding. * * @author tatu (tatu.saloranta@iki.fi) */ public class OAuthSignatureCalculator implements SignatureCalculator { public final static String HEADER_AUTHORIZATION = "Authorization"; private final String KEY_OAUTH_CONSUMER_KEY = "oauth_consumer_key"; private final String KEY_OAUTH_NONCE = "oauth_nonce"; private final String KEY_OAUTH_SIGNATURE = "oauth_signature"; private final String KEY_OAUTH_SIGNATURE_METHOD = "oauth_signature_method"; private final String KEY_OAUTH_TIMESTAMP = "oauth_timestamp"; private final String KEY_OAUTH_TOKEN = "oauth_token"; private final String KEY_OAUTH_VERSION = "oauth_version"; private final String OAUTH_VERSION_1_0 = "1.0"; private final String OAUTH_SIGNATURE_METHOD = "HMAC-SHA1"; /** * To generate Nonce, need some (pseudo)randomness; no need for * secure variant here. */ protected final Random random; protected final byte[] nonceBuffer = new byte[16]; protected final ThreadSafeHMAC mac; protected final ConsumerKey consumerAuth; protected final RequestToken userAuth; /** * @param consumerAuth Consumer key to use for signature calculation * @param userAuth Request/access token to use for signature calculation */ public OAuthSignatureCalculator(ConsumerKey consumerAuth, RequestToken userAuth) { mac = new ThreadSafeHMAC(consumerAuth, userAuth); this.consumerAuth = consumerAuth; this.userAuth = userAuth; random = new Random(System.identityHashCode(this) + System.currentTimeMillis()); } //@Override // silly 1.5; doesn't allow this for interfaces public void calculateAndAddSignature(String baseURL, Request request, RequestBuilderBase requestBuilder) { String method = request.getMethod().toString(); // POST etc String nonce = generateNonce(); long timestamp = System.currentTimeMillis() / 1000L; String signature = calculateSignature(method, baseURL, timestamp, nonce, request.getParams(), request.getQueryParams()); String headerValue = constructAuthHeader(signature, nonce, timestamp); requestBuilder = requestBuilder.setHeader(HEADER_AUTHORIZATION, headerValue); } /** * Method for calculating OAuth signature using HMAC/SHA-1 method. */ public String calculateSignature(String method, String baseURL, long oauthTimestamp, String nonce, FluentStringsMap formParams, FluentStringsMap queryParams) { StringBuilder signedText = new StringBuilder(100); signedText.append(method); // POST / GET etc (nothing to URL encode) signedText.append('&'); /* 07-Oct-2010, tatu: URL may contain default port number; if so, need to extract * from base URL. */ if (baseURL.startsWith("http:")) { int i = baseURL.indexOf(":80/", 4); if (i > 0) { baseURL = baseURL.substring(0, i) + baseURL.substring(i + 3); } } else if (baseURL.startsWith("https:")) { int i = baseURL.indexOf(":443/", 5); if (i > 0) { baseURL = baseURL.substring(0, i) + baseURL.substring(i + 4); } } signedText.append(UTF8UrlEncoder.encode(baseURL)); /** * List of all query and form parameters added to this request; needed * for calculating request signature */ OAuthParameterSet allParameters = new OAuthParameterSet(); // start with standard OAuth parameters we need allParameters.add(KEY_OAUTH_CONSUMER_KEY, consumerAuth.getKey()); allParameters.add(KEY_OAUTH_NONCE, nonce); allParameters.add(KEY_OAUTH_SIGNATURE_METHOD, OAUTH_SIGNATURE_METHOD); allParameters.add(KEY_OAUTH_TIMESTAMP, String.valueOf(oauthTimestamp)); allParameters.add(KEY_OAUTH_TOKEN, userAuth.getKey()); allParameters.add(KEY_OAUTH_VERSION, OAUTH_VERSION_1_0); if (formParams != null) { for (Map.Entry> entry : formParams) { String key = entry.getKey(); for (String value : entry.getValue()) { allParameters.add(key, value); } } } if (queryParams != null) { for (Map.Entry> entry : queryParams) { String key = entry.getKey(); for (String value : entry.getValue()) { allParameters.add(key, value); } } } String encodedParams = allParameters.sortAndConcat(); // and all that needs to be URL encoded (... again!) signedText.append('&'); UTF8UrlEncoder.appendEncoded(signedText, encodedParams); byte[] rawBase = UTF8Codec.toUTF8(signedText.toString()); byte[] rawSignature = mac.digest(rawBase); // and finally, base64 encoded... phew! return Base64.encode(rawSignature); } /** * Method used for constructing */ public String constructAuthHeader(String signature, String nonce, long oauthTimestamp) { StringBuilder sb = new StringBuilder(200); sb.append("OAuth "); sb.append(KEY_OAUTH_CONSUMER_KEY).append("=\"").append(consumerAuth.getKey()).append("\", "); sb.append(KEY_OAUTH_TOKEN).append("=\"").append(userAuth.getKey()).append("\", "); sb.append(KEY_OAUTH_SIGNATURE_METHOD).append("=\"").append(OAUTH_SIGNATURE_METHOD).append("\", "); // careful: base64 has chars that need URL encoding: sb.append(KEY_OAUTH_SIGNATURE).append("=\""); UTF8UrlEncoder.appendEncoded(sb, signature).append("\", "); sb.append(KEY_OAUTH_TIMESTAMP).append("=\"").append(oauthTimestamp).append("\", "); // also: nonce may contain things that need URL encoding (esp. when using base64): sb.append(KEY_OAUTH_NONCE).append("=\""); UTF8UrlEncoder.appendEncoded(sb, nonce); sb.append("\", "); sb.append(KEY_OAUTH_VERSION).append("=\"").append(OAUTH_VERSION_1_0).append("\""); return sb.toString(); } private synchronized String generateNonce() { random.nextBytes(nonceBuffer); // let's use base64 encoding over hex, slightly more compact than hex or decimals return Base64.encode(nonceBuffer); // return String.valueOf(Math.abs(random.nextLong())); } /** * Container for parameters used for calculating OAuth signature. * About the only confusing aspect is that of whether entries are to be sorted * before encoded or vice versa: if my reading is correct, encoding is to occur * first, then sorting; although this should rarely matter (since sorting is primary * by key, which usually has nothing to encode)... of course, rarely means that * when it would occur it'd be harder to track down. */ final static class OAuthParameterSet { final private ArrayList allParameters = new ArrayList(); public OAuthParameterSet() { } public OAuthParameterSet add(String key, String value) { Parameter p = new Parameter(UTF8UrlEncoder.encode(key), UTF8UrlEncoder.encode(value)); allParameters.add(p); return this; } public String sortAndConcat() { // then sort them (AFTER encoding, important) Parameter[] params = allParameters.toArray(new Parameter[allParameters.size()]); Arrays.sort(params); // and build parameter section using pre-encoded pieces: StringBuilder encodedParams = new StringBuilder(100); for (Parameter param : params) { if (encodedParams.length() > 0) { encodedParams.append('&'); } encodedParams.append(param.key()).append('=').append(param.value()); } return encodedParams.toString(); } } /** * Helper class for sorting query and form parameters that we need */ final static class Parameter implements Comparable { private final String key, value; public Parameter(String key, String value) { this.key = key; this.value = value; } public String key() { return key; } public String value() { return value; } //@Override // silly 1.5; doesn't allow this for interfaces public int compareTo(Parameter other) { int diff = key.compareTo(other.key); if (diff == 0) { diff = value.compareTo(other.value); } return diff; } @Override public String toString() { return key + "=" + value; } } } async-http-client-1.6.5/src/main/java/com/ning/http/client/oauth/RequestToken.java000066400000000000000000000037611166553056000301250ustar00rootroot00000000000000/* * Copyright 2010 Ning, Inc. * * Ning licenses this file to you 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. * */ package com.ning.http.client.oauth; /** * Value class used for OAuth tokens (request secret, access secret); * simple container with two parts, public id part ("key") and * confidential ("secret") part. */ public class RequestToken { private final String key; private final String secret; public RequestToken(String key, String token) { this.key = key; this.secret = token; } public String getKey() { return key; } public String getSecret() { return secret; } @Override public String toString() { StringBuilder sb = new StringBuilder("{ key="); appendValue(sb, key); sb.append(", secret="); appendValue(sb, secret); sb.append("}"); return sb.toString(); } private void appendValue(StringBuilder sb, String value) { if (value == null) { sb.append("null"); } else { sb.append('"'); sb.append(value); sb.append('"'); } } @Override public int hashCode() { return key.hashCode() + secret.hashCode(); } @Override public boolean equals(Object o) { if (o == this) return true; if (o == null || o.getClass() != getClass()) return false; RequestToken other = (RequestToken) o; return key.equals(other.key) && secret.equals(other.secret); } } async-http-client-1.6.5/src/main/java/com/ning/http/client/oauth/ThreadSafeHMAC.java000066400000000000000000000037601166553056000301320ustar00rootroot00000000000000/* * Copyright 2010 Ning, Inc. * * Ning licenses this file to you 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. * */ package com.ning.http.client.oauth; import javax.crypto.Mac; import javax.crypto.spec.SecretKeySpec; import com.ning.http.util.UTF8Codec; /** * Since cloning (of MAC instances) is not necessarily supported on all platforms * (and specifically seems to fail on MacOS), let's wrap synchronization/reuse details here. * Assumption is that this is bit more efficient (even considering synchronization) * than locating and reconstructing instance each time. * In future we may want to use soft references and thread local instance. * * @author tatu (tatu.saloranta@iki.fi) */ public class ThreadSafeHMAC { private static final String HMAC_SHA1_ALGORITHM = "HmacSHA1"; private final Mac mac; public ThreadSafeHMAC(ConsumerKey consumerAuth, RequestToken userAuth) { byte[] keyBytes = UTF8Codec.toUTF8(consumerAuth.getSecret() + "&" + userAuth.getSecret()); SecretKeySpec signingKey = new SecretKeySpec(keyBytes, HMAC_SHA1_ALGORITHM); // Get an hmac_sha1 instance and initialize with the signing key try { mac = Mac.getInstance(HMAC_SHA1_ALGORITHM); mac.init(signingKey); } catch (Exception e) { throw new IllegalArgumentException(e); } } public synchronized byte[] digest(byte[] message) { mac.reset(); return mac.doFinal(message); } } async-http-client-1.6.5/src/main/java/com/ning/http/client/providers/000077500000000000000000000000001166553056000255175ustar00rootroot00000000000000async-http-client-1.6.5/src/main/java/com/ning/http/client/providers/apache/000077500000000000000000000000001166553056000267405ustar00rootroot00000000000000ApacheAsyncHttpProvider.java000066400000000000000000001144131166553056000342620ustar00rootroot00000000000000async-http-client-1.6.5/src/main/java/com/ning/http/client/providers/apache/* * Copyright (c) 2010-2011 Sonatype, Inc. All rights reserved. * * This program is licensed to you under the Apache License Version 2.0, * and you may not use this file except in compliance with the Apache License Version 2.0. * You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0. * * Unless required by applicable law or agreed to in writing, * software distributed under the Apache License Version 2.0 is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. */ package com.ning.http.client.providers.apache; import com.ning.http.client.AsyncHandler; import com.ning.http.client.AsyncHttpClientConfig; import com.ning.http.client.AsyncHttpProvider; import com.ning.http.client.AsyncHttpProviderConfig; import com.ning.http.client.Body; import com.ning.http.client.ByteArrayPart; import com.ning.http.client.Cookie; import com.ning.http.client.FilePart; import com.ning.http.client.HttpResponseBodyPart; import com.ning.http.client.HttpResponseHeaders; import com.ning.http.client.HttpResponseStatus; import com.ning.http.client.ListenableFuture; import com.ning.http.client.MaxRedirectException; import com.ning.http.client.Part; import com.ning.http.client.PerRequestConfig; import com.ning.http.client.ProgressAsyncHandler; import com.ning.http.client.ProxyServer; import com.ning.http.client.Realm; import com.ning.http.client.Request; import com.ning.http.client.RequestBuilder; import com.ning.http.client.Response; import com.ning.http.client.StringPart; import com.ning.http.client.filter.FilterContext; import com.ning.http.client.filter.FilterException; import com.ning.http.client.filter.IOExceptionFilter; import com.ning.http.client.filter.ResponseFilter; import com.ning.http.client.listener.TransferCompletionHandler; import com.ning.http.client.providers.netty.NettyAsyncHttpProvider; import com.ning.http.client.resumable.ResumableAsyncHandler; import com.ning.http.util.AsyncHttpProviderUtils; import com.ning.http.util.ProxyUtils; import com.ning.http.util.UTF8UrlEncoder; import org.apache.commons.httpclient.CircularRedirectException; import org.apache.commons.httpclient.Credentials; import org.apache.commons.httpclient.DefaultHttpMethodRetryHandler; import org.apache.commons.httpclient.Header; import org.apache.commons.httpclient.HttpClient; import org.apache.commons.httpclient.HttpMethodBase; import org.apache.commons.httpclient.MultiThreadedHttpConnectionManager; import org.apache.commons.httpclient.NoHttpResponseException; import org.apache.commons.httpclient.ProxyHost; import org.apache.commons.httpclient.UsernamePasswordCredentials; import org.apache.commons.httpclient.auth.AuthScope; import org.apache.commons.httpclient.cookie.CookiePolicy; import org.apache.commons.httpclient.methods.ByteArrayRequestEntity; import org.apache.commons.httpclient.methods.DeleteMethod; import org.apache.commons.httpclient.methods.EntityEnclosingMethod; import org.apache.commons.httpclient.methods.GetMethod; import org.apache.commons.httpclient.methods.HeadMethod; import org.apache.commons.httpclient.methods.InputStreamRequestEntity; import org.apache.commons.httpclient.methods.OptionsMethod; import org.apache.commons.httpclient.methods.PostMethod; import org.apache.commons.httpclient.methods.PutMethod; import org.apache.commons.httpclient.methods.StringRequestEntity; import org.apache.commons.httpclient.methods.multipart.ByteArrayPartSource; import org.apache.commons.httpclient.methods.multipart.MultipartRequestEntity; import org.apache.commons.httpclient.methods.multipart.PartSource; import org.apache.commons.httpclient.params.HttpClientParams; import org.apache.commons.httpclient.params.HttpConnectionParams; import org.apache.commons.httpclient.params.HttpMethodParams; import org.apache.commons.httpclient.protocol.Protocol; import org.apache.commons.httpclient.protocol.ProtocolSocketFactory; import org.apache.commons.httpclient.util.IdleConnectionTimeoutThread; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.net.SocketFactory; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLHandshakeException; import javax.net.ssl.SSLSocketFactory; import javax.net.ssl.TrustManager; import javax.net.ssl.X509TrustManager; import java.io.ByteArrayInputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.ConnectException; import java.net.InetAddress; import java.net.Socket; import java.net.URI; import java.net.UnknownHostException; import java.nio.ByteBuffer; import java.security.KeyManagementException; import java.security.NoSuchAlgorithmException; import java.security.SecureRandom; import java.security.cert.CertificateException; import java.security.cert.X509Certificate; import java.util.Collection; import java.util.List; import java.util.Map; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; import java.util.zip.GZIPInputStream; import static com.ning.http.util.AsyncHttpProviderUtils.DEFAULT_CHARSET; /** * An {@link com.ning.http.client.AsyncHttpProvider} for Apache Http Client 3.1 */ public class ApacheAsyncHttpProvider implements AsyncHttpProvider { private final static Logger logger = LoggerFactory.getLogger(ApacheAsyncHttpProvider.class); private final AsyncHttpClientConfig config; private final AtomicBoolean isClose = new AtomicBoolean(false); private IdleConnectionTimeoutThread idleConnectionTimeoutThread; private final AtomicInteger maxConnections = new AtomicInteger(); private final MultiThreadedHttpConnectionManager connectionManager; private final HttpClientParams params; static { final SocketFactory factory = new TrustingSSLSocketFactory(); Protocol.registerProtocol("https", new Protocol("https", new ProtocolSocketFactory() { public Socket createSocket(String string, int i, InetAddress inetAddress, int i1) throws IOException { return factory.createSocket(string, i, inetAddress, i1); } public Socket createSocket(String string, int i, InetAddress inetAddress, int i1, HttpConnectionParams httpConnectionParams) throws IOException { return factory.createSocket(string, i, inetAddress, i1); } public Socket createSocket(String string, int i) throws IOException { return factory.createSocket(string, i); } }, 443)); } public ApacheAsyncHttpProvider(AsyncHttpClientConfig config) { this.config = config; connectionManager = new MultiThreadedHttpConnectionManager(); params = new HttpClientParams(); params.setParameter(HttpMethodParams.SINGLE_COOKIE_HEADER, Boolean.TRUE); params.setCookiePolicy(CookiePolicy.BROWSER_COMPATIBILITY); params.setParameter(HttpMethodParams.RETRY_HANDLER, new DefaultHttpMethodRetryHandler()); AsyncHttpProviderConfig providerConfig = config.getAsyncHttpProviderConfig(); if (providerConfig != null && ApacheAsyncHttpProvider.class.isAssignableFrom(providerConfig.getClass())) { configure(ApacheAsyncHttpProviderConfig.class.cast(providerConfig)); } } private void configure(ApacheAsyncHttpProviderConfig config) { } public ListenableFuture execute(Request request, AsyncHandler handler) throws IOException { if (isClose.get()) { throw new IOException("Closed"); } if (ResumableAsyncHandler.class.isAssignableFrom(handler.getClass())) { request = ResumableAsyncHandler.class.cast(handler).adjustRequestRange(request); } if (config.getMaxTotalConnections() > -1 && (maxConnections.get() + 1) > config.getMaxTotalConnections()) { throw new IOException(String.format("Too many connections %s", config.getMaxTotalConnections())); } if (idleConnectionTimeoutThread != null) { idleConnectionTimeoutThread.shutdown(); idleConnectionTimeoutThread = null; } int requestTimeout = requestTimeout(config, request.getPerRequestConfig()); if (config.getIdleConnectionTimeoutInMs() > 0 && requestTimeout != -1 && requestTimeout < config.getIdleConnectionTimeoutInMs()) { idleConnectionTimeoutThread = new IdleConnectionTimeoutThread(); idleConnectionTimeoutThread.setConnectionTimeout(config.getIdleConnectionTimeoutInMs()); idleConnectionTimeoutThread.addConnectionManager(connectionManager); idleConnectionTimeoutThread.start(); } HttpClient httpClient = new HttpClient(params, connectionManager); Realm realm = request.getRealm() != null ? request.getRealm() : config.getRealm(); if (realm != null) { httpClient.getParams().setAuthenticationPreemptive(realm.getUsePreemptiveAuth()); Credentials defaultcreds = new UsernamePasswordCredentials(realm.getPrincipal(), realm.getPassword()); httpClient.getState().setCredentials(new AuthScope(null, -1, AuthScope.ANY_REALM), defaultcreds); } HttpMethodBase method = createMethod(httpClient, request); ApacheResponseFuture f = new ApacheResponseFuture(handler, requestTimeout, request, method); f.touch(); f.setInnerFuture(config.executorService().submit(new ApacheClientRunnable(request, handler, method, f, httpClient))); maxConnections.incrementAndGet(); return f; } public void close() { if (idleConnectionTimeoutThread != null) { idleConnectionTimeoutThread.shutdown(); idleConnectionTimeoutThread = null; } if (connectionManager != null) { try { connectionManager.shutdown(); } catch (Exception e) { logger.error("Error shutting down connection manager", e); } } } public Response prepareResponse(HttpResponseStatus status, HttpResponseHeaders headers, Collection bodyParts) { return new ApacheResponse(status, headers, bodyParts); } private HttpMethodBase createMethod(HttpClient client, Request request) throws IOException, FileNotFoundException { String methodName = request.getMethod(); HttpMethodBase method = null; if (methodName.equalsIgnoreCase("POST") || methodName.equalsIgnoreCase("PUT")) { EntityEnclosingMethod post = methodName.equalsIgnoreCase("POST") ? new PostMethod(request.getUrl()) : new PutMethod(request.getUrl()); String bodyCharset = request.getBodyEncoding() == null ? DEFAULT_CHARSET : request.getBodyEncoding(); post.getParams().setContentCharset("ISO-8859-1"); if (request.getByteData() != null) { post.setRequestEntity(new ByteArrayRequestEntity(request.getByteData())); post.setRequestHeader("Content-Length", String.valueOf(request.getByteData().length)); } else if (request.getStringData() != null) { post.setRequestEntity(new StringRequestEntity(request.getStringData(), "text/xml", bodyCharset)); post.setRequestHeader("Content-Length", String.valueOf(request.getStringData().getBytes(bodyCharset).length)); } else if (request.getStreamData() != null) { InputStreamRequestEntity r = new InputStreamRequestEntity(request.getStreamData()); post.setRequestEntity(r); post.setRequestHeader("Content-Length", String.valueOf(r.getContentLength())); } else if (request.getParams() != null) { StringBuilder sb = new StringBuilder(); for (final Map.Entry> paramEntry : request.getParams()) { final String key = paramEntry.getKey(); for (final String value : paramEntry.getValue()) { if (sb.length() > 0) { sb.append("&"); } UTF8UrlEncoder.appendEncoded(sb, key); sb.append("="); UTF8UrlEncoder.appendEncoded(sb, value); } } post.setRequestHeader("Content-Length", String.valueOf(sb.length())); post.setRequestEntity(new StringRequestEntity(sb.toString(), "text/xml", "ISO-8859-1")); if (!request.getHeaders().containsKey("Content-Type")) { post.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); } } else if (request.getParts() != null) { MultipartRequestEntity mre = createMultipartRequestEntity(bodyCharset, request.getParts(), post.getParams()); post.setRequestEntity(mre); post.setRequestHeader("Content-Type", mre.getContentType()); post.setRequestHeader("Content-Length", String.valueOf(mre.getContentLength())); } else if (request.getEntityWriter() != null) { post.setRequestEntity(new EntityWriterRequestEntity(request.getEntityWriter(), computeAndSetContentLength(request, post))); } else if (request.getFile() != null) { File file = request.getFile(); if (!file.isFile()) { throw new IOException(String.format(Thread.currentThread() + "File %s is not a file or doesn't exist", file.getAbsolutePath())); } post.setRequestHeader("Content-Length", String.valueOf(file.length())); FileInputStream fis = new FileInputStream(file); try { InputStreamRequestEntity r = new InputStreamRequestEntity(fis); post.setRequestEntity(r); post.setRequestHeader("Content-Length", String.valueOf(r.getContentLength())); } finally { fis.close(); } } else if (request.getBodyGenerator() != null) { Body body = request.getBodyGenerator().createBody(); try { int length = (int) body.getContentLength(); if (length < 0) { length = (int) request.getContentLength(); } // TODO: This is suboptimal if (length >= 0) { post.setRequestHeader("Content-Length", String.valueOf(length)); // This is totally sub optimal byte[] bytes = new byte[length]; ByteBuffer buffer = ByteBuffer.wrap(bytes); for (; ;) { buffer.clear(); if (body.read(buffer) < 0) { break; } } post.setRequestEntity(new ByteArrayRequestEntity(bytes)); } } finally { try { body.close(); } catch (IOException e) { logger.warn("Failed to close request body: {}", e.getMessage(), e); } } } if (request.getHeaders().getFirstValue("Expect") != null && request.getHeaders().getFirstValue("Expect").equalsIgnoreCase("100-Continue")) { post.setUseExpectHeader(true); } method = post; } else if (methodName.equalsIgnoreCase("DELETE")) { method = new DeleteMethod(request.getUrl()); } else if (methodName.equalsIgnoreCase("HEAD")) { method = new HeadMethod(request.getUrl()); } else if (methodName.equalsIgnoreCase("GET")) { method = new GetMethod(request.getUrl()); } else if (methodName.equalsIgnoreCase("OPTIONS")) { method = new OptionsMethod(request.getUrl()); } else { throw new IllegalStateException(String.format("Invalid Method", methodName)); } ProxyServer proxyServer = request.getProxyServer() != null ? request.getProxyServer() : config.getProxyServer(); boolean avoidProxy = ProxyUtils.avoidProxy( proxyServer, request ); if (!avoidProxy) { if (proxyServer.getPrincipal() != null) { Credentials defaultcreds = new UsernamePasswordCredentials(proxyServer.getPrincipal(), proxyServer.getPassword()); client.getState().setCredentials(new AuthScope(null, -1, AuthScope.ANY_REALM), defaultcreds); } ProxyHost proxyHost = proxyServer == null ? null : new ProxyHost(proxyServer.getHost(), proxyServer.getPort()); client.getHostConfiguration().setProxyHost(proxyHost); } method.setFollowRedirects(false); if ((request.getCookies() != null) && !request.getCookies().isEmpty()) { for (Cookie cookie : request.getCookies()) { method.setRequestHeader("Cookie", AsyncHttpProviderUtils.encodeCookies(request.getCookies())); } } if (request.getHeaders() != null) { for (String name : request.getHeaders().keySet()) { if (!"host".equalsIgnoreCase(name)) { for (String value : request.getHeaders().get(name)) { method.setRequestHeader(name, value); } } } } if (request.getHeaders().getFirstValue("User-Agent") != null) { method.setRequestHeader("User-Agent", request.getHeaders().getFirstValue("User-Agent")); } else if (config.getUserAgent() != null) { method.setRequestHeader("User-Agent", config.getUserAgent()); } else { method.setRequestHeader("User-Agent", AsyncHttpProviderUtils.constructUserAgent(ApacheAsyncHttpProvider.class)); } if (config.isCompressionEnabled()) { Header acceptableEncodingHeader = method.getRequestHeader("Accept-Encoding"); if (acceptableEncodingHeader != null) { String acceptableEncodings = acceptableEncodingHeader.getValue(); if (acceptableEncodings.indexOf("gzip") == -1) { StringBuilder buf = new StringBuilder(acceptableEncodings); if (buf.length() > 1) { buf.append(","); } buf.append("gzip"); method.setRequestHeader("Accept-Encoding", buf.toString()); } } else { method.setRequestHeader("Accept-Encoding", "gzip"); } } if (request.getVirtualHost() != null) { String vs = request.getVirtualHost(); int index = vs.indexOf(":"); if (index > 0) { vs = vs.substring(0,index); } method.getParams().setVirtualHost(vs); } return method; } private final static int computeAndSetContentLength(Request request, HttpMethodBase m) { int lenght = (int) request.getContentLength(); if (lenght == -1 && m.getRequestHeader("Content-Length") != null) { lenght = Integer.valueOf(m.getRequestHeader("Content-Length").getValue()); } if (lenght != -1) { m.setRequestHeader("Content-Length", String.valueOf(lenght)); } return lenght; } public class ApacheClientRunnable implements Callable { private final AsyncHandler asyncHandler; private HttpMethodBase method; private final ApacheResponseFuture future; private Request request; private final HttpClient httpClient; private int currentRedirectCount; private AtomicBoolean isAuth = new AtomicBoolean(false); private boolean terminate = true; public ApacheClientRunnable(Request request, AsyncHandler asyncHandler, HttpMethodBase method, ApacheResponseFuture future, HttpClient httpClient) { this.asyncHandler = asyncHandler; this.method = method; this.future = future; this.request = request; this.httpClient = httpClient; } public T call() { terminate = true; AsyncHandler.STATE state = AsyncHandler.STATE.ABORT; try { URI uri = null; try { uri = AsyncHttpProviderUtils.createUri(request.getRawUrl()); } catch (IllegalArgumentException u) { uri = AsyncHttpProviderUtils.createUri(request.getUrl()); } int delay = requestTimeout(config, future.getRequest().getPerRequestConfig()); if (delay != -1) { ReaperFuture reaperFuture = new ReaperFuture(future); Future scheduledFuture = config.reaper().scheduleAtFixedRate(reaperFuture, delay, 500, TimeUnit.MILLISECONDS); reaperFuture.setScheduledFuture(scheduledFuture); future.setReaperFuture(reaperFuture); } if (TransferCompletionHandler.class.isAssignableFrom(asyncHandler.getClass())) { throw new IllegalStateException(TransferCompletionHandler.class.getName() + "not supported by this provider"); } int statusCode = 200; try { statusCode = httpClient.executeMethod(method); } catch (CircularRedirectException ex) { // Quite ugly, but this is needed to unify statusCode = 302; currentRedirectCount = config.getMaxRedirects(); } ApacheResponseStatus status = new ApacheResponseStatus(uri, method, ApacheAsyncHttpProvider.this); FilterContext fc = new FilterContext.FilterContextBuilder().asyncHandler(asyncHandler).request(request).responseStatus(status).build(); for (ResponseFilter asyncFilter : config.getResponseFilters()) { fc = asyncFilter.filter(fc); if (fc == null) { throw new NullPointerException("FilterContext is null"); } } // The request has changed if (fc.replayRequest()) { request = fc.getRequest(); method = createMethod(httpClient, request); terminate = false; return call(); } logger.debug("\n\nRequest {}\n\nResponse {}\n", request, method); boolean redirectEnabled = (request.isRedirectEnabled() || config.isRedirectEnabled()); if (redirectEnabled && (statusCode == 302 || statusCode == 301)) { isAuth.set(false); if (currentRedirectCount++ < config.getMaxRedirects()) { String location = method.getResponseHeader("Location").getValue(); URI rediUri = AsyncHttpProviderUtils.getRedirectUri(uri, location); String newUrl = rediUri.toString(); if (!newUrl.equals(uri.toString())) { RequestBuilder builder = new RequestBuilder(request); logger.debug("Redirecting to {}", newUrl); request = builder.setUrl(newUrl).build(); method = createMethod(httpClient, request); terminate = false; return call(); } } else { throw new MaxRedirectException("Maximum redirect reached: " + config.getMaxRedirects()); } } state = asyncHandler.onStatusReceived(status); if (state == AsyncHandler.STATE.CONTINUE) { state = asyncHandler.onHeadersReceived(new ApacheResponseHeaders(uri, method, ApacheAsyncHttpProvider.this)); } if (state == AsyncHandler.STATE.CONTINUE) { InputStream is = method.getResponseBodyAsStream(); if (is != null) { Header h = method.getResponseHeader("Content-Encoding"); if (h != null) { String contentEncoding = h.getValue(); boolean isGZipped = contentEncoding == null ? false : "gzip".equalsIgnoreCase(contentEncoding); if (isGZipped) { is = new GZIPInputStream(is); } } int byteToRead = (int) method.getResponseContentLength(); InputStream stream = is; if (byteToRead <= 0) { int[] lengthWrapper = new int[1]; byte[] bytes = AsyncHttpProviderUtils.readFully(is, lengthWrapper); stream = new ByteArrayInputStream(bytes, 0, lengthWrapper[0]); byteToRead = lengthWrapper[0]; } if (byteToRead > 0) { int minBytes = Math.min(8192, byteToRead); byte[] bytes = new byte[minBytes]; int leftBytes = minBytes < 8192 ? minBytes : byteToRead; int read = 0; while (leftBytes > -1) { try { read = stream.read(bytes); } catch (IOException ex) { logger.warn("Connection closed", ex); read = -1; } if (read == -1) { break; } future.touch(); byte[] b = new byte[read]; System.arraycopy(bytes, 0, b, 0, read); asyncHandler.onBodyPartReceived(new ApacheResponseBodyPart(uri, b, ApacheAsyncHttpProvider.this)); leftBytes -= read; } } } if (method.getName().equalsIgnoreCase("HEAD")) { asyncHandler.onBodyPartReceived(new ApacheResponseBodyPart(uri, "".getBytes(), ApacheAsyncHttpProvider.this)); } } if (ProgressAsyncHandler.class.isAssignableFrom(asyncHandler.getClass())) { ProgressAsyncHandler.class.cast(asyncHandler).onHeaderWriteCompleted(); ProgressAsyncHandler.class.cast(asyncHandler).onContentWriteCompleted(); } try { return asyncHandler.onCompleted(); } catch (Throwable t) { RuntimeException ex = new RuntimeException(); ex.initCause(t); throw ex; } } catch (Throwable t) { if (IOException.class.isAssignableFrom(t.getClass()) && config.getIOExceptionFilters().size() > 0) { FilterContext fc = new FilterContext.FilterContextBuilder().asyncHandler(asyncHandler) .request(future.getRequest()).ioException(IOException.class.cast(t)).build(); try { fc = handleIoException(fc); } catch (FilterException e) { if (config.getMaxTotalConnections() != -1) { maxConnections.decrementAndGet(); } future.done(null); method.releaseConnection(); } if (fc.replayRequest()) { request = fc.getRequest(); return call(); } } if (method.isAborted()) { return null; } logger.debug(t.getMessage(), t); try { future.abort(filterException(t)); } catch (Throwable t2) { logger.error(t2.getMessage(), t2); } } finally { if (terminate) { if (config.getMaxTotalConnections() != -1) { maxConnections.decrementAndGet(); } future.done(null); // Crappy Apache HttpClient who blocks forever here with large files. config.executorService().submit(new Runnable() { public void run() { method.releaseConnection(); } }); } } return null; } private Throwable filterException(Throwable t) { if (UnknownHostException.class.isAssignableFrom(t.getClass())) { t = new ConnectException(t.getMessage()); } if (NoHttpResponseException.class.isAssignableFrom(t.getClass())) { int responseTimeoutInMs = config.getRequestTimeoutInMs(); if (request.getPerRequestConfig() != null && request.getPerRequestConfig().getRequestTimeoutInMs() != -1) { responseTimeoutInMs = request.getPerRequestConfig().getRequestTimeoutInMs(); } t = new TimeoutException(String.format("No response received after %s", responseTimeoutInMs)); } if (SSLHandshakeException.class.isAssignableFrom(t.getClass())) { Throwable t2 = new ConnectException(); t2.initCause(t); t = t2; } return t; } private FilterContext handleIoException(FilterContext fc) throws FilterException { for (IOExceptionFilter asyncFilter : config.getIOExceptionFilters()) { fc = asyncFilter.filter(fc); if (fc == null) { throw new NullPointerException("FilterContext is null"); } } return fc; } } private MultipartRequestEntity createMultipartRequestEntity(String charset, List params, HttpMethodParams methodParams) throws FileNotFoundException { org.apache.commons.httpclient.methods.multipart.Part[] parts = new org.apache.commons.httpclient.methods.multipart.Part[params.size()]; int i = 0; for (Part part : params) { if (part instanceof StringPart) { parts[i] = new org.apache.commons.httpclient.methods.multipart.StringPart(part.getName(), ((StringPart) part).getValue(), charset); } else if (part instanceof FilePart) { parts[i] = new org.apache.commons.httpclient.methods.multipart.FilePart(part.getName(), ((FilePart) part).getFile(), ((FilePart) part).getMimeType(), ((FilePart) part).getCharSet()); } else if (part instanceof ByteArrayPart) { PartSource source = new ByteArrayPartSource(((ByteArrayPart) part).getFileName(), ((ByteArrayPart) part).getData()); parts[i] = new org.apache.commons.httpclient.methods.multipart.FilePart(part.getName(), source, ((ByteArrayPart) part).getMimeType(), ((ByteArrayPart) part).getCharSet()); } else if (part == null) { throw new NullPointerException("Part cannot be null"); } else { throw new IllegalArgumentException(String.format("Unsupported part type for multipart parameter %s", part.getName())); } ++i; } return new MultipartRequestEntity(parts, methodParams); } public class EntityWriterRequestEntity implements org.apache.commons.httpclient.methods.RequestEntity { private Request.EntityWriter entityWriter; private long contentLength; public EntityWriterRequestEntity(Request.EntityWriter entityWriter, long contentLength) { this.entityWriter = entityWriter; this.contentLength = contentLength; } public long getContentLength() { return contentLength; } public String getContentType() { return null; } public boolean isRepeatable() { return false; } public void writeRequest(OutputStream out) throws IOException { entityWriter.writeEntity(out); } } private static class TrustingSSLSocketFactory extends SSLSocketFactory { private SSLSocketFactory delegate; private TrustingSSLSocketFactory() { try { SSLContext sslcontext = SSLContext.getInstance("SSL"); sslcontext.init(null, new TrustManager[]{new TrustEveryoneTrustManager()}, new SecureRandom()); delegate = sslcontext.getSocketFactory(); } catch (KeyManagementException e) { throw new IllegalStateException(); } catch (NoSuchAlgorithmException e) { throw new IllegalStateException(); } } @Override public Socket createSocket(String s, int i) throws IOException, UnknownHostException { return delegate.createSocket(s, i); } @Override public Socket createSocket(String s, int i, InetAddress inetAddress, int i1) throws IOException, UnknownHostException { return delegate.createSocket(s, i, inetAddress, i1); } @Override public Socket createSocket(InetAddress inetAddress, int i) throws IOException { return delegate.createSocket(inetAddress, i); } @Override public Socket createSocket(InetAddress inetAddress, int i, InetAddress inetAddress1, int i1) throws IOException { return delegate.createSocket(inetAddress, i, inetAddress1, i1); } @Override public String[] getDefaultCipherSuites() { return delegate.getDefaultCipherSuites(); } @Override public String[] getSupportedCipherSuites() { return delegate.getSupportedCipherSuites(); } @Override public Socket createSocket(Socket socket, String s, int i, boolean b) throws IOException { return delegate.createSocket(socket, s, i, b); } } private static class TrustEveryoneTrustManager implements X509TrustManager { public void checkClientTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException { // do nothing } public void checkServerTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException { // do nothing } public X509Certificate[] getAcceptedIssuers() { return new X509Certificate[0]; } } private final class ReaperFuture implements Future, Runnable { private Future scheduledFuture; private ApacheResponseFuture apacheResponseFuture; public ReaperFuture(ApacheResponseFuture apacheResponseFuture) { this.apacheResponseFuture = apacheResponseFuture; } public void setScheduledFuture(Future scheduledFuture) { this.scheduledFuture = scheduledFuture; } /** * @Override */ public synchronized boolean cancel(boolean mayInterruptIfRunning) { //cleanup references to allow gc to reclaim memory independently //of this Future lifecycle this.apacheResponseFuture = null; return this.scheduledFuture.cancel(mayInterruptIfRunning); } /** * @Override */ public Object get() throws InterruptedException, ExecutionException { return this.scheduledFuture.get(); } /** * @Override */ public Object get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException { return this.scheduledFuture.get(timeout, unit); } /** * @Override */ public boolean isCancelled() { return this.scheduledFuture.isCancelled(); } /** * @Override */ public boolean isDone() { return this.scheduledFuture.isDone(); } /** * @Override */ public synchronized void run() { if (this.apacheResponseFuture != null && this.apacheResponseFuture.hasExpired()) { logger.debug("Request Timeout expired for " + this.apacheResponseFuture); int requestTimeout = config.getRequestTimeoutInMs(); PerRequestConfig p = this.apacheResponseFuture.getRequest().getPerRequestConfig(); if (p != null && p.getRequestTimeoutInMs() != -1) { requestTimeout = p.getRequestTimeoutInMs(); } apacheResponseFuture.abort(new TimeoutException(String.format("No response received after %s", requestTimeout))); this.apacheResponseFuture = null; } } } protected static int requestTimeout(AsyncHttpClientConfig config, PerRequestConfig perRequestConfig) { int result; if (perRequestConfig != null) { int prRequestTimeout = perRequestConfig.getRequestTimeoutInMs(); result = (prRequestTimeout != 0 ? prRequestTimeout : config.getRequestTimeoutInMs()); } else { result = config.getRequestTimeoutInMs(); } return result; } } ApacheAsyncHttpProviderConfig.java000066400000000000000000000027651166553056000354160ustar00rootroot00000000000000async-http-client-1.6.5/src/main/java/com/ning/http/client/providers/apache/* * Copyright (c) 2010-2011 Sonatype, Inc. All rights reserved. * * This program is licensed to you under the Apache License Version 2.0, * and you may not use this file except in compliance with the Apache License Version 2.0. * You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0. * * Unless required by applicable law or agreed to in writing, * software distributed under the Apache License Version 2.0 is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. */ package com.ning.http.client.providers.apache; import com.ning.http.client.AsyncHttpProviderConfig; import java.util.Map; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; public class ApacheAsyncHttpProviderConfig implements AsyncHttpProviderConfig { private final ConcurrentHashMap properties = new ConcurrentHashMap(); public AsyncHttpProviderConfig addProperty(String name, String value) { properties.put(name, value); return this; } public String getProperty(String name) { return properties.get(name); } public String removeProperty(String name) { return properties.remove(name); } public Set> propertiesSet() { return properties.entrySet(); } } async-http-client-1.6.5/src/main/java/com/ning/http/client/providers/apache/ApacheResponse.java000066400000000000000000000151231166553056000325050ustar00rootroot00000000000000/* * Copyright (c) 2010-2011 Sonatype, Inc. All rights reserved. * * This program is licensed to you under the Apache License Version 2.0, * and you may not use this file except in compliance with the Apache License Version 2.0. * You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0. * * Unless required by applicable law or agreed to in writing, * software distributed under the Apache License Version 2.0 is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. */ package com.ning.http.client.providers.apache; import com.ning.http.client.Cookie; import com.ning.http.client.FluentCaseInsensitiveStringsMap; import com.ning.http.client.HttpResponseBodyPart; import com.ning.http.client.HttpResponseHeaders; import com.ning.http.client.HttpResponseStatus; import com.ning.http.client.Response; import com.ning.http.util.AsyncHttpProviderUtils; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import java.io.UnsupportedEncodingException; import java.net.MalformedURLException; import java.net.URI; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.Map; public class ApacheResponse implements Response { private final static String DEFAULT_CHARSET = "ISO-8859-1"; private final static String HEADERS_NOT_COMPUTED = "Response's headers hasn't been computed by your AsyncHandler."; private final URI uri; private final Collection bodyParts; private final HttpResponseHeaders headers; private final HttpResponseStatus status; private final List cookies = new ArrayList(); public ApacheResponse(HttpResponseStatus status, HttpResponseHeaders headers, Collection bodyParts) { this.bodyParts = bodyParts; this.headers = headers; this.status = status; uri = this.status.getUrl(); } /* @Override */ public int getStatusCode() { return status.getStatusCode(); } /* @Override */ public String getStatusText() { return status.getStatusText(); } /* @Override */ public String getResponseBody() throws IOException { return getResponseBody(DEFAULT_CHARSET); } public String getResponseBody(String charset) throws IOException { String contentType = getContentType(); if (contentType != null && charset == null) { charset = AsyncHttpProviderUtils.parseCharset(contentType); } if (charset == null) { charset = DEFAULT_CHARSET; } return contentToString(charset); } String contentToString(String charset) throws UnsupportedEncodingException { StringBuilder b = new StringBuilder(); for (HttpResponseBodyPart bp : bodyParts) { b.append(new String(bp.getBodyPartBytes(), charset)); } return b.toString(); } /* @Override */ public InputStream getResponseBodyAsStream() throws IOException { if (bodyParts.size() > 0) { return new ByteArrayInputStream(bodyParts.toArray(new HttpResponseBodyPart[bodyParts.size()])[0].getBodyPartBytes()); } else { return new ByteArrayInputStream("".getBytes()); } } /* @Override */ public String getResponseBodyExcerpt(int maxLength) throws IOException { return getResponseBodyExcerpt(maxLength, DEFAULT_CHARSET); } /* @Override */ public String getResponseBodyExcerpt(int maxLength, String charset) throws IOException { String contentType = getContentType(); if (contentType != null && charset == null) { charset = AsyncHttpProviderUtils.parseCharset(contentType); } if (charset == null) { charset = DEFAULT_CHARSET; } String response = contentToString(charset); return response.length() <= maxLength ? response : response.substring(0, maxLength); } /* @Override */ public URI getUri() throws MalformedURLException { return uri; } /* @Override */ public String getContentType() { if (headers == null) { throw new IllegalStateException(HEADERS_NOT_COMPUTED); } return headers.getHeaders().getFirstValue("Content-Type"); } /* @Override */ public String getHeader(String name) { if (headers == null) { throw new IllegalStateException(); } return headers.getHeaders().getFirstValue(name); } /* @Override */ public List getHeaders(String name) { if (headers == null) { throw new IllegalStateException(HEADERS_NOT_COMPUTED); } return headers.getHeaders().get(name); } /* @Override */ public FluentCaseInsensitiveStringsMap getHeaders() { if (headers == null) { throw new IllegalStateException(HEADERS_NOT_COMPUTED); } return headers.getHeaders(); } /* @Override */ public boolean isRedirected() { return (status.getStatusCode() >= 300) && (status.getStatusCode() <= 399); } /* @Override */ public List getCookies() { if (headers == null) { throw new IllegalStateException(HEADERS_NOT_COMPUTED); } if (cookies.isEmpty()) { for (Map.Entry> header : headers.getHeaders().entrySet()) { if (header.getKey().equalsIgnoreCase("Set-Cookie")) { // TODO: ask for parsed header List v = header.getValue(); for (String value : v) { Cookie cookie = AsyncHttpProviderUtils.parseCookie(value); cookies.add(cookie); } } } } return Collections.unmodifiableList(cookies); } /** * {@inheritDoc} */ /* @Override */ public boolean hasResponseStatus() { return (bodyParts != null ? true : false); } /** * {@inheritDoc} */ /* @Override */ public boolean hasResponseHeaders() { return (headers != null ? true : false); } /** * {@inheritDoc} */ /* @Override */ public boolean hasResponseBody() { return (bodyParts != null && bodyParts.size() > 0 ? true : false); } } ApacheResponseBodyPart.java000066400000000000000000000033111166553056000340670ustar00rootroot00000000000000async-http-client-1.6.5/src/main/java/com/ning/http/client/providers/apache/* * Copyright (c) 2010-2011 Sonatype, Inc. All rights reserved. * * This program is licensed to you under the Apache License Version 2.0, * and you may not use this file except in compliance with the Apache License Version 2.0. * You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0. * * Unless required by applicable law or agreed to in writing, * software distributed under the Apache License Version 2.0 is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. */ package com.ning.http.client.providers.apache; import com.ning.http.client.AsyncHttpProvider; import com.ning.http.client.HttpResponseBodyPart; import java.io.IOException; import java.io.OutputStream; import java.net.URI; import java.nio.ByteBuffer; /** * A callback class used when an HTTP response body is received. */ public class ApacheResponseBodyPart extends HttpResponseBodyPart { private final byte[] chunk; public ApacheResponseBodyPart(URI uri, byte[] chunk, AsyncHttpProvider provider) { super(uri, provider); this.chunk = chunk; } /** * Return the response body's part bytes received. * * @return the response body's part bytes received. */ public byte[] getBodyPartBytes() { return chunk; } @Override public int writeTo(OutputStream outputStream) throws IOException { outputStream.write(chunk); return chunk.length; } @Override public ByteBuffer getBodyByteBuffer() { return ByteBuffer.wrap(chunk); } }ApacheResponseFuture.java000066400000000000000000000166451166553056000336330ustar00rootroot00000000000000async-http-client-1.6.5/src/main/java/com/ning/http/client/providers/apache/* * Copyright (c) 2010-2011 Sonatype, Inc. All rights reserved. * * This program is licensed to you under the Apache License Version 2.0, * and you may not use this file except in compliance with the Apache License Version 2.0. * You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0. * * Unless required by applicable law or agreed to in writing, * software distributed under the Apache License Version 2.0 is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. */ package com.ning.http.client.providers.apache; import com.ning.http.client.AsyncHandler; import com.ning.http.client.Request; import com.ning.http.client.listenable.AbstractListenableFuture; import org.apache.commons.httpclient.HttpMethodBase; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.concurrent.Callable; import java.util.concurrent.CancellationException; import java.util.concurrent.ExecutionException; import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.atomic.AtomicReference; public class ApacheResponseFuture extends AbstractListenableFuture { private final static Logger logger = LoggerFactory.getLogger(ApacheResponseFuture.class); private Future innerFuture; private final AsyncHandler asyncHandler; private final int responseTimeoutInMs; private final AtomicBoolean cancelled = new AtomicBoolean(false); private final AtomicBoolean timedOut = new AtomicBoolean(false); private final AtomicBoolean isDone = new AtomicBoolean(false); private final AtomicReference exception = new AtomicReference(); private final AtomicLong touch = new AtomicLong(System.currentTimeMillis()); private final AtomicBoolean contentProcessed = new AtomicBoolean(false); private final Request request; private final HttpMethodBase method; private Future reaperFuture; private boolean writeHeaders; private boolean writeBody; public ApacheResponseFuture(AsyncHandler asyncHandler, int responseTimeoutInMs, Request request, HttpMethodBase method) { this.asyncHandler = asyncHandler; this.responseTimeoutInMs = responseTimeoutInMs == -1 ? Integer.MAX_VALUE : responseTimeoutInMs; this.request = request; this.method = method; writeHeaders = true; writeBody = true; } protected void setInnerFuture(Future innerFuture) { this.innerFuture = innerFuture; } public void done(Callable callable) { isDone.set(true); if (reaperFuture != null) { reaperFuture.cancel(true); } super.done(); } /** * TODO. * * @param v The new content */ public void content(V v) { } protected void setReaperFuture(Future reaperFuture) { if (this.reaperFuture != null) { this.reaperFuture.cancel(true); } this.reaperFuture = reaperFuture; } @Override public String toString() { return "ApacheResponseFuture{" + "innerFuture=" + innerFuture + ", asyncHandler=" + asyncHandler + ", responseTimeoutInMs=" + responseTimeoutInMs + ", cancelled=" + cancelled + ", timedOut=" + timedOut + ", isDone=" + isDone + ", exception=" + exception + ", touch=" + touch + ", contentProcessed=" + contentProcessed + ", request=" + request + ", method=" + method + ", reaperFuture=" + reaperFuture + '}'; } public void abort(Throwable t) { exception.set(t); if (innerFuture != null) { innerFuture.cancel(true); } if (method != null) { method.abort(); } if (reaperFuture != null) { reaperFuture.cancel(true); } if (!timedOut.get() && !cancelled.get()) { try { asyncHandler.onThrowable(t); } catch (Throwable t2) { logger.debug("asyncHandler.onThrowable", t2); } } super.done(); } public boolean cancel(boolean mayInterruptIfRunning) { if (!cancelled.get() && innerFuture != null) { method.abort(); try { asyncHandler.onThrowable(new CancellationException()); } catch (Throwable t) { logger.debug("asyncHandler.onThrowable", t); } cancelled.set(true); if (reaperFuture != null) { reaperFuture.cancel(true); } super.done(); return innerFuture.cancel(mayInterruptIfRunning); } else { super.done(); return false; } } public boolean isCancelled() { if (innerFuture != null) { return innerFuture.isCancelled(); } else { return false; } } public boolean isDone() { contentProcessed.set(true); return innerFuture.isDone(); } public V get() throws InterruptedException, ExecutionException { try { return get(responseTimeoutInMs, TimeUnit.MILLISECONDS); } catch (TimeoutException e) { throw new ExecutionException(e); } } public V get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException { V content = null; try { if (innerFuture != null) { content = innerFuture.get(timeout, unit); } } catch (TimeoutException t) { if (!contentProcessed.get() && timeout != -1 && ((System.currentTimeMillis() - touch.get()) <= responseTimeoutInMs)) { return get(timeout, unit); } if (exception.get() == null) { timedOut.set(true); throw new ExecutionException(new TimeoutException(String.format("No response received after %s", responseTimeoutInMs))); } } catch (CancellationException ce) { } if (exception.get() != null) { throw new ExecutionException(exception.get()); } return content; } /** * Is the Future still valid * * @return true if response has expired and should be terminated. */ public boolean hasExpired() { return responseTimeoutInMs != -1 && ((System.currentTimeMillis() - touch.get()) >= responseTimeoutInMs); } public void touch() { touch.set(System.currentTimeMillis()); } public Request getRequest() { return request; } /** * {@inheritDoc} */ /* @Override */ public boolean getAndSetWriteHeaders(boolean writeHeaders) { boolean b = this.writeHeaders; this.writeHeaders = writeHeaders; return b; } /** * {@inheritDoc} */ /* @Override */ public boolean getAndSetWriteBody(boolean writeBody) { boolean b = this.writeBody; this.writeBody = writeBody; return b; } } ApacheResponseHeaders.java000066400000000000000000000042751166553056000337300ustar00rootroot00000000000000async-http-client-1.6.5/src/main/java/com/ning/http/client/providers/apache/* * Copyright (c) 2010-2011 Sonatype, Inc. All rights reserved. * * This program is licensed to you under the Apache License Version 2.0, * and you may not use this file except in compliance with the Apache License Version 2.0. * You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0. * * Unless required by applicable law or agreed to in writing, * software distributed under the Apache License Version 2.0 is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. */ package com.ning.http.client.providers.apache; import com.ning.http.client.AsyncHttpProvider; import com.ning.http.client.FluentCaseInsensitiveStringsMap; import com.ning.http.client.HttpResponseHeaders; import org.apache.commons.httpclient.Header; import org.apache.commons.httpclient.HttpMethodBase; import java.net.URI; /** * A class that represent the HTTP headers. */ public class ApacheResponseHeaders extends HttpResponseHeaders { private final HttpMethodBase method; private final FluentCaseInsensitiveStringsMap headers; public ApacheResponseHeaders(URI uri, HttpMethodBase method, AsyncHttpProvider provider) { super(uri, provider, false); this.method = method; headers = computerHeaders(); } private FluentCaseInsensitiveStringsMap computerHeaders() { FluentCaseInsensitiveStringsMap h = new FluentCaseInsensitiveStringsMap(); Header[] uh = method.getResponseHeaders(); for (Header e : uh) { if (e.getName() != null) { h.add(e.getName(), e.getValue()); } } uh = method.getResponseFooters(); for (Header e : uh) { if (e.getName() != null) { h.add(e.getName(), e.getValue()); } } return h; } /** * Return the HTTP header * * @return an {@link com.ning.http.client.FluentCaseInsensitiveStringsMap} */ @Override public FluentCaseInsensitiveStringsMap getHeaders() { return headers; } }ApacheResponseStatus.java000066400000000000000000000037251166553056000336370ustar00rootroot00000000000000async-http-client-1.6.5/src/main/java/com/ning/http/client/providers/apache/* * Copyright (c) 2010-2011 Sonatype, Inc. All rights reserved. * * This program is licensed to you under the Apache License Version 2.0, * and you may not use this file except in compliance with the Apache License Version 2.0. * You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0. * * Unless required by applicable law or agreed to in writing, * software distributed under the Apache License Version 2.0 is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. */ package com.ning.http.client.providers.apache; import com.ning.http.client.AsyncHttpProvider; import com.ning.http.client.HttpResponseStatus; import org.apache.commons.httpclient.HttpMethodBase; import java.net.URI; /** * A class that represent the HTTP response' status line (code + text) */ public class ApacheResponseStatus extends HttpResponseStatus { private final HttpMethodBase method; public ApacheResponseStatus(URI uri, HttpMethodBase method, AsyncHttpProvider provider) { super(uri, provider); this.method = method; } /** * Return the response status code * * @return the response status code */ public int getStatusCode() { return method.getStatusCode(); } /** * Return the response status text * * @return the response status text */ public String getStatusText() { return method.getStatusText(); } @Override public String getProtocolName() { return method.getStatusLine().getHttpVersion(); } @Override public int getProtocolMajorVersion() { return 1; //TODO } @Override public int getProtocolMinorVersion() { return 1; //TODO } @Override public String getProtocolText() { return ""; //TODO } }async-http-client-1.6.5/src/main/java/com/ning/http/client/providers/jdk/000077500000000000000000000000001166553056000262675ustar00rootroot00000000000000async-http-client-1.6.5/src/main/java/com/ning/http/client/providers/jdk/JDKAsyncHttpProvider.java000066400000000000000000001044611166553056000331210ustar00rootroot00000000000000/* * Copyright (c) 2010-2011 Sonatype, Inc. All rights reserved. * * This program is licensed to you under the Apache License Version 2.0, * and you may not use this file except in compliance with the Apache License Version 2.0. * You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0. * * Unless required by applicable law or agreed to in writing, * software distributed under the Apache License Version 2.0 is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. */ package com.ning.http.client.providers.jdk; import com.ning.http.client.AsyncHandler; import com.ning.http.client.AsyncHttpClientConfig; import com.ning.http.client.AsyncHttpProvider; import com.ning.http.client.AsyncHttpProviderConfig; import com.ning.http.client.Body; import com.ning.http.client.FluentCaseInsensitiveStringsMap; import com.ning.http.client.HttpResponseBodyPart; import com.ning.http.client.HttpResponseHeaders; import com.ning.http.client.HttpResponseStatus; import com.ning.http.client.ListenableFuture; import com.ning.http.client.MaxRedirectException; import com.ning.http.client.PerRequestConfig; import com.ning.http.client.ProgressAsyncHandler; import com.ning.http.client.ProxyServer; import com.ning.http.client.Realm; import com.ning.http.client.Request; import com.ning.http.client.RequestBuilder; import com.ning.http.client.Response; import com.ning.http.client.filter.FilterContext; import com.ning.http.client.filter.FilterException; import com.ning.http.client.filter.IOExceptionFilter; import com.ning.http.client.filter.ResponseFilter; import com.ning.http.client.listener.TransferCompletionHandler; import com.ning.http.client.providers.netty.NettyAsyncHttpProvider; import com.ning.http.multipart.MultipartRequestEntity; import com.ning.http.util.AsyncHttpProviderUtils; import com.ning.http.util.AuthenticatorUtils; import com.ning.http.util.ProxyUtils; import com.ning.http.util.SslUtils; import com.ning.http.util.UTF8UrlEncoder; import org.jboss.netty.buffer.ChannelBuffer; import org.jboss.netty.buffer.ChannelBuffers; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.naming.AuthenticationException; import javax.net.ssl.HttpsURLConnection; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLHandshakeException; import java.io.ByteArrayInputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.lang.reflect.Field; import java.net.Authenticator; import java.net.ConnectException; import java.net.HttpURLConnection; import java.net.InetSocketAddress; import java.net.PasswordAuthentication; import java.net.Proxy; import java.net.SocketAddress; import java.net.SocketTimeoutException; import java.net.URI; import java.net.UnknownHostException; import java.nio.ByteBuffer; import java.security.GeneralSecurityException; import java.security.NoSuchAlgorithmException; import java.util.Collection; import java.util.List; import java.util.Map; import java.util.concurrent.Callable; import java.util.concurrent.TimeoutException; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; import java.util.zip.GZIPInputStream; import static com.ning.http.util.AsyncHttpProviderUtils.DEFAULT_CHARSET; public class JDKAsyncHttpProvider implements AsyncHttpProvider { private final static Logger logger = LoggerFactory.getLogger(JDKAsyncHttpProvider.class); private final static String NTLM_DOMAIN = "http.auth.ntlm.domain"; private final AsyncHttpClientConfig config; private final AtomicBoolean isClose = new AtomicBoolean(false); private final static int MAX_BUFFERED_BYTES = 8192; private final AtomicInteger maxConnections = new AtomicInteger(); private String jdkNtlmDomain; private Authenticator jdkAuthenticator; private boolean bufferResponseInMemory = false; public JDKAsyncHttpProvider(AsyncHttpClientConfig config) { this.config = config; AsyncHttpProviderConfig providerConfig = config.getAsyncHttpProviderConfig(); if (providerConfig != null && JDKAsyncHttpProviderConfig.class.isAssignableFrom(providerConfig.getClass())) { configure(JDKAsyncHttpProviderConfig.class.cast(providerConfig)); } } private void configure(JDKAsyncHttpProviderConfig config) { for(Map.Entry e: config.propertiesSet()) { System.setProperty(e.getKey(), e.getValue()); } if (config.getProperty(JDKAsyncHttpProviderConfig.FORCE_RESPONSE_BUFFERING) != null) { bufferResponseInMemory = true; } } public ListenableFuture execute(Request request, AsyncHandler handler) throws IOException { return execute(request, handler, null); } public ListenableFuture execute(Request request, AsyncHandler handler, ListenableFuture future) throws IOException { if (isClose.get()) { throw new IOException("Closed"); } if (config.getMaxTotalConnections() > -1 && (maxConnections.get() + 1) > config.getMaxTotalConnections()) { throw new IOException(String.format("Too many connections %s", config.getMaxTotalConnections())); } ProxyServer proxyServer = request.getProxyServer() != null ? request.getProxyServer() : config.getProxyServer(); Realm realm = request.getRealm() != null ? request.getRealm() : config.getRealm(); boolean avoidProxy = ProxyUtils.avoidProxy( proxyServer, request ); Proxy proxy = null; if (!avoidProxy && (proxyServer != null || realm != null)) { try { proxy = configureProxyAndAuth(proxyServer, realm); } catch (AuthenticationException e) { throw new IOException(e.getMessage()); } } HttpURLConnection urlConnection = createUrlConnection(request); PerRequestConfig conf = request.getPerRequestConfig(); int requestTimeout = (conf != null && conf.getRequestTimeoutInMs() != 0) ? conf.getRequestTimeoutInMs() : config.getRequestTimeoutInMs(); JDKDelegateFuture delegate = null; if (future != null) { delegate = new JDKDelegateFuture(handler, requestTimeout, future, urlConnection); } JDKFuture f = delegate == null ? new JDKFuture(handler, requestTimeout, urlConnection) : delegate; f.touch(); f.setInnerFuture(config.executorService().submit(new AsyncHttpUrlConnection(urlConnection, request, handler, f))); maxConnections.incrementAndGet(); return f; } private HttpURLConnection createUrlConnection(Request request) throws IOException { ProxyServer proxyServer = request.getProxyServer() != null ? request.getProxyServer() : config.getProxyServer(); Realm realm = request.getRealm() != null ? request.getRealm() : config.getRealm(); boolean avoidProxy = ProxyUtils.avoidProxy( proxyServer, request ); Proxy proxy = null; if (!avoidProxy && proxyServer != null || realm != null) { try { proxy = configureProxyAndAuth(proxyServer, realm); } catch (AuthenticationException e) { throw new IOException(e.getMessage()); } } HttpURLConnection urlConnection = null; if (proxy == null) { urlConnection = (HttpURLConnection) AsyncHttpProviderUtils.createUri( request.getUrl() ).toURL().openConnection( Proxy.NO_PROXY ); } else { urlConnection = (HttpURLConnection) AsyncHttpProviderUtils.createUri(request.getUrl()).toURL().openConnection(proxy); } if (request.getUrl().startsWith("https")) { HttpsURLConnection secure = (HttpsURLConnection) urlConnection; SSLContext sslContext = config.getSSLContext(); if (sslContext == null) { try { sslContext = SslUtils.getSSLContext(); } catch (NoSuchAlgorithmException e) { throw new IOException(e.getMessage()); } catch (GeneralSecurityException e) { throw new IOException(e.getMessage()); } } secure.setSSLSocketFactory(sslContext.getSocketFactory()); secure.setHostnameVerifier(config.getHostnameVerifier()); } return urlConnection; } public void close() { isClose.set(true); } public Response prepareResponse(HttpResponseStatus status, HttpResponseHeaders headers, Collection bodyParts) { return new JDKResponse(status, headers, bodyParts); } private final class AsyncHttpUrlConnection implements Callable { private HttpURLConnection urlConnection; private Request request; private final AsyncHandler asyncHandler; private final ListenableFuture future; private int currentRedirectCount; private AtomicBoolean isAuth = new AtomicBoolean(false); private byte[] cachedBytes; private int cachedBytesLenght; private boolean terminate = true; public AsyncHttpUrlConnection(HttpURLConnection urlConnection, Request request, AsyncHandler asyncHandler, ListenableFuture future) { this.urlConnection = urlConnection; this.request = request; this.asyncHandler = asyncHandler; this.future = future; this.request = request; } public T call() throws Exception { AsyncHandler.STATE state = AsyncHandler.STATE.ABORT; try { URI uri = null; // Encoding with URLConnection is a bit bogus so we need to try both way before setting it try { uri = AsyncHttpProviderUtils.createUri(request.getRawUrl()); } catch (IllegalArgumentException u) { uri = AsyncHttpProviderUtils.createUri(request.getUrl()); } configure(uri, urlConnection, request); urlConnection.connect(); if (TransferCompletionHandler.class.isAssignableFrom(asyncHandler.getClass())) { throw new IllegalStateException(TransferCompletionHandler.class.getName() + "not supported by this provider"); } int statusCode = urlConnection.getResponseCode(); logger.debug("\n\nRequest {}\n\nResponse {}\n", request, statusCode); ResponseStatus status = new ResponseStatus(uri, urlConnection, JDKAsyncHttpProvider.this); FilterContext fc = new FilterContext.FilterContextBuilder().asyncHandler(asyncHandler).request(request).responseStatus(status).build(); for (ResponseFilter asyncFilter : config.getResponseFilters()) { fc = asyncFilter.filter(fc); if (fc == null) { throw new NullPointerException("FilterContext is null"); } } // The request has changed if (fc.replayRequest()) { request = fc.getRequest(); urlConnection = createUrlConnection(request); terminate = false; return call(); } boolean redirectEnabled = (request.isRedirectEnabled() || config.isRedirectEnabled()); if (redirectEnabled && (statusCode == 302 || statusCode == 301)) { if (currentRedirectCount++ < config.getMaxRedirects()) { String location = urlConnection.getHeaderField("Location"); URI redirUri = AsyncHttpProviderUtils.getRedirectUri(uri, location); String newUrl = redirUri.toString(); if (!newUrl.equals(uri.toString())) { RequestBuilder builder = new RequestBuilder(request); logger.debug("Redirecting to {}", newUrl); request = builder.setUrl(newUrl).build(); urlConnection = createUrlConnection(request); terminate = false; return call(); } } else { throw new MaxRedirectException("Maximum redirect reached: " + config.getMaxRedirects()); } } Realm realm = request.getRealm() != null ? request.getRealm() : config.getRealm(); if (statusCode == 401 && !isAuth.getAndSet(true) && realm != null ) { String wwwAuth = urlConnection.getHeaderField("WWW-Authenticate"); logger.debug("Sending authentication to {}", request.getUrl()); Realm nr = new Realm.RealmBuilder().clone(realm) .parseWWWAuthenticateHeader(wwwAuth) .setUri(URI.create(request.getUrl()).getPath()) .setMethodName(request.getMethod()) .setUsePreemptiveAuth(true) .build(); RequestBuilder builder = new RequestBuilder(request); request = builder.setRealm(nr).build(); urlConnection = createUrlConnection(request); terminate = false; return call(); } state = asyncHandler.onStatusReceived(status); if (state == AsyncHandler.STATE.CONTINUE) { state = asyncHandler.onHeadersReceived(new ResponseHeaders(uri, urlConnection, JDKAsyncHttpProvider.this)); } if (state == AsyncHandler.STATE.CONTINUE) { InputStream is = getInputStream(urlConnection); String contentEncoding = urlConnection.getHeaderField("Content-Encoding"); boolean isGZipped = contentEncoding == null ? false : "gzip".equalsIgnoreCase(contentEncoding); if (isGZipped) { is = new GZIPInputStream(is); } int byteToRead = urlConnection.getContentLength(); InputStream stream = is; if (bufferResponseInMemory || byteToRead <= 0) { int[] lengthWrapper = new int[1]; byte[] bytes = AsyncHttpProviderUtils.readFully(is, lengthWrapper); stream = new ByteArrayInputStream(bytes, 0, lengthWrapper[0]); byteToRead = lengthWrapper[0]; } if (byteToRead > 0) { int minBytes = Math.min(8192, byteToRead); byte[] bytes = new byte[minBytes]; int leftBytes = minBytes < 8192 ? minBytes : byteToRead; int read = 0; while (leftBytes > -1) { read = stream.read(bytes); if (read == -1) { break; } future.touch(); byte[] b = new byte[read]; System.arraycopy(bytes, 0, b, 0, read); asyncHandler.onBodyPartReceived(new ResponseBodyPart(uri, b, JDKAsyncHttpProvider.this)); leftBytes -= read; } } if (request.getMethod().equalsIgnoreCase("HEAD")) { asyncHandler.onBodyPartReceived(new ResponseBodyPart(uri, "".getBytes(), JDKAsyncHttpProvider.this)); } } if (ProgressAsyncHandler.class.isAssignableFrom(asyncHandler.getClass())) { ProgressAsyncHandler.class.cast(asyncHandler).onHeaderWriteCompleted(); ProgressAsyncHandler.class.cast(asyncHandler).onContentWriteCompleted(); } try { T t = asyncHandler.onCompleted(); future.content(t); future.done(null); return t; } catch (Throwable t) { RuntimeException ex = new RuntimeException(); ex.initCause(t); throw ex; } } catch (Throwable t) { logger.debug(t.getMessage(), t); if (IOException.class.isAssignableFrom(t.getClass()) && config.getIOExceptionFilters().size() > 0) { FilterContext fc = new FilterContext.FilterContextBuilder().asyncHandler(asyncHandler) .request(request).ioException(IOException.class.cast(t)).build(); try { fc = handleIoException(fc); } catch (FilterException e) { if (config.getMaxTotalConnections() != -1) { maxConnections.decrementAndGet(); } future.done(null); } if (fc.replayRequest()) { request = fc.getRequest(); urlConnection = createUrlConnection(request); return call(); } } try { future.abort(filterException(t)); } catch (Throwable t2) { logger.error(t2.getMessage(), t2); } } finally { if (terminate) { if (config.getMaxTotalConnections() != -1) { maxConnections.decrementAndGet(); } urlConnection.disconnect(); if (jdkNtlmDomain != null) { System.setProperty(NTLM_DOMAIN, jdkNtlmDomain); } Authenticator.setDefault(jdkAuthenticator); } } return null; } private FilterContext handleIoException(FilterContext fc) throws FilterException { for (IOExceptionFilter asyncFilter : config.getIOExceptionFilters()) { fc = asyncFilter.filter(fc); if (fc == null) { throw new NullPointerException("FilterContext is null"); } } return fc; } private Throwable filterException(Throwable t) { if (UnknownHostException.class.isAssignableFrom(t.getClass())) { t = new ConnectException(t.getMessage()); } if (SocketTimeoutException.class.isAssignableFrom(t.getClass())) { int responseTimeoutInMs = config.getRequestTimeoutInMs(); if (request.getPerRequestConfig() != null && request.getPerRequestConfig().getRequestTimeoutInMs() != -1) { responseTimeoutInMs = request.getPerRequestConfig().getRequestTimeoutInMs(); } t = new TimeoutException(String.format("No response received after %s", responseTimeoutInMs)); } if (SSLHandshakeException.class.isAssignableFrom(t.getClass())) { Throwable t2 = new ConnectException(); t2.initCause(t); t = t2; } return t; } private void configure(URI uri, HttpURLConnection urlConnection, Request request) throws IOException, AuthenticationException { PerRequestConfig conf = request.getPerRequestConfig(); int requestTimeout = (conf != null && conf.getRequestTimeoutInMs() != 0) ? conf.getRequestTimeoutInMs() : config.getRequestTimeoutInMs(); urlConnection.setConnectTimeout(config.getConnectionTimeoutInMs()); if (requestTimeout != -1) urlConnection.setReadTimeout(requestTimeout); urlConnection.setInstanceFollowRedirects(false); String host = uri.getHost(); String method = request.getMethod(); if (request.getVirtualHost() != null) { host = request.getVirtualHost(); } if (uri.getPort() == -1 || request.getVirtualHost() != null) { urlConnection.setRequestProperty("Host", host); } else { urlConnection.setRequestProperty("Host", host + ":" + uri.getPort()); } if (config.isCompressionEnabled()) { urlConnection.setRequestProperty("Accept-Encoding", "gzip"); } if (!method.equalsIgnoreCase("CONNECT")) { FluentCaseInsensitiveStringsMap h = request.getHeaders(); if (h != null) { for (String name : h.keySet()) { if (!"host".equalsIgnoreCase(name)) { for (String value : h.get(name)) { urlConnection.setRequestProperty(name, value); if (name.equalsIgnoreCase("Expect")) { throw new IllegalStateException("Expect: 100-Continue not supported"); } } } } } } String ka = config.getAllowPoolingConnection() ? "keep-alive" : "close"; urlConnection.setRequestProperty("Connection", ka); ProxyServer proxyServer = request.getProxyServer() != null ? request.getProxyServer() : config.getProxyServer(); boolean avoidProxy = ProxyUtils.avoidProxy( proxyServer, uri.getHost() ); if (!avoidProxy) { urlConnection.setRequestProperty("Proxy-Connection", ka); if (proxyServer.getPrincipal() != null) { urlConnection.setRequestProperty("Proxy-Authorization", AuthenticatorUtils.computeBasicAuthentication(proxyServer)); } if (proxyServer.getProtocol().equals(ProxyServer.Protocol.NTLM)) { jdkNtlmDomain = System.getProperty(NTLM_DOMAIN); System.setProperty(NTLM_DOMAIN, proxyServer.getNtlmDomain()); } } Realm realm = request.getRealm() != null ? request.getRealm() : config.getRealm(); if (realm != null && realm.getUsePreemptiveAuth() ) { switch (realm.getAuthScheme()) { case BASIC: urlConnection.setRequestProperty("Authorization", AuthenticatorUtils.computeBasicAuthentication(realm)); break; case DIGEST: if (realm.getNonce() != null && !realm.getNonce().equals("")) { try { urlConnection.setRequestProperty("Authorization", AuthenticatorUtils.computeDigestAuthentication(realm)); } catch (NoSuchAlgorithmException e) { throw new SecurityException(e); } } break; case NTLM: jdkNtlmDomain = System.getProperty(NTLM_DOMAIN); System.setProperty(NTLM_DOMAIN, realm.getDomain()); break; case NONE: break; default: throw new IllegalStateException(String.format("Invalid Authentication %s", realm.toString())); } } // Add default accept headers. if (request.getHeaders().getFirstValue("Accept") == null) { urlConnection.setRequestProperty("Accept", "*/*"); } if (request.getHeaders().getFirstValue("User-Agent") != null) { urlConnection.setRequestProperty("User-Agent", request.getHeaders().getFirstValue("User-Agent")); } else if (config.getUserAgent() != null) { urlConnection.setRequestProperty("User-Agent", config.getUserAgent()); } else { urlConnection.setRequestProperty("User-Agent", AsyncHttpProviderUtils.constructUserAgent(JDKAsyncHttpProvider.class)); } if (request.getCookies() != null && !request.getCookies().isEmpty()) { urlConnection.setRequestProperty("Cookie", AsyncHttpProviderUtils.encodeCookies(request.getCookies())); } String reqType = request.getMethod(); urlConnection.setRequestMethod(reqType); if ("POST".equals(reqType) || "PUT".equals(reqType)) { urlConnection.setRequestProperty("Content-Length", "0"); urlConnection.setDoOutput(true); String bodyCharset = request.getBodyEncoding() == null ? DEFAULT_CHARSET : request.getBodyEncoding(); if (cachedBytes != null) { urlConnection.setRequestProperty("Content-Length", String.valueOf(cachedBytesLenght)); urlConnection.setFixedLengthStreamingMode(cachedBytesLenght); urlConnection.getOutputStream().write(cachedBytes, 0, cachedBytesLenght); } else if (request.getByteData() != null) { urlConnection.setRequestProperty("Content-Length", String.valueOf(request.getByteData().length)); urlConnection.setFixedLengthStreamingMode(request.getByteData().length); urlConnection.getOutputStream().write(request.getByteData()); } else if (request.getStringData() != null) { if (!request.getHeaders().containsKey("Content-Type")) { urlConnection.setRequestProperty("Content-Type", "text/html;" + bodyCharset); } byte[] b = request.getStringData().getBytes(bodyCharset); urlConnection.setRequestProperty("Content-Length", String.valueOf(b.length)); urlConnection.getOutputStream().write(b); } else if (request.getStreamData() != null) { int[] lengthWrapper = new int[1]; cachedBytes = AsyncHttpProviderUtils.readFully(request.getStreamData(), lengthWrapper); cachedBytesLenght = lengthWrapper[0]; urlConnection.setRequestProperty("Content-Length", String.valueOf(cachedBytesLenght)); urlConnection.setFixedLengthStreamingMode(cachedBytesLenght); urlConnection.getOutputStream().write(cachedBytes, 0, cachedBytesLenght); } else if (request.getParams() != null) { StringBuilder sb = new StringBuilder(); for (final Map.Entry> paramEntry : request.getParams()) { final String key = paramEntry.getKey(); for (final String value : paramEntry.getValue()) { if (sb.length() > 0) { sb.append("&"); } UTF8UrlEncoder.appendEncoded(sb, key); sb.append("="); UTF8UrlEncoder.appendEncoded(sb, value); } } urlConnection.setRequestProperty("Content-Length", String.valueOf(sb.length())); urlConnection.setFixedLengthStreamingMode(sb.length()); if (!request.getHeaders().containsKey("Content-Type")) { urlConnection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); } urlConnection.getOutputStream().write(sb.toString().getBytes(bodyCharset)); } else if (request.getParts() != null) { int lenght = (int) request.getContentLength(); if (lenght != -1) { urlConnection.setRequestProperty("Content-Length", String.valueOf(lenght)); urlConnection.setFixedLengthStreamingMode(lenght); } if (lenght == -1) { lenght = MAX_BUFFERED_BYTES; } MultipartRequestEntity mre = AsyncHttpProviderUtils.createMultipartRequestEntity(request.getParts(), request.getParams()); urlConnection.setRequestProperty("Content-Type", mre.getContentType()); urlConnection.setRequestProperty("Content-Length", String.valueOf(mre.getContentLength())); ChannelBuffer b = ChannelBuffers.dynamicBuffer(lenght); mre.writeRequest(urlConnection.getOutputStream()); } else if (request.getEntityWriter() != null) { int lenght = (int) request.getContentLength(); if (lenght != -1) { urlConnection.setRequestProperty("Content-Length", String.valueOf(lenght)); urlConnection.setFixedLengthStreamingMode(lenght); } request.getEntityWriter().writeEntity(urlConnection.getOutputStream()); } else if (request.getFile() != null) { File file = request.getFile(); if (!file.isFile()) { throw new IOException(String.format(Thread.currentThread() + "File %s is not a file or doesn't exist", file.getAbsolutePath())); } urlConnection.setRequestProperty("Content-Length", String.valueOf(file.length())); urlConnection.setFixedLengthStreamingMode((int) file.length()); FileInputStream fis = new FileInputStream(file); try { OutputStream os = urlConnection.getOutputStream(); for (final byte[] buffer = new byte[1024 * 16];;) { int read = fis.read(buffer); if (read < 0) { break; } os.write(buffer, 0, read); } } finally { fis.close(); } } else if (request.getBodyGenerator() != null) { Body body = request.getBodyGenerator().createBody(); try { int length = (int) body.getContentLength(); if (length < 0) { length = (int) request.getContentLength(); } if (length >= 0) { urlConnection.setRequestProperty("Content-Length", String.valueOf(length)); urlConnection.setFixedLengthStreamingMode(length); } OutputStream os = urlConnection.getOutputStream(); for (ByteBuffer buffer = ByteBuffer.allocate( 1024 * 8 );;) { buffer.clear(); if (body.read(buffer) < 0) { break; } os.write( buffer.array(), buffer.arrayOffset(), buffer.position() ); } } finally { try { body.close(); } catch (IOException e) { logger.warn("Failed to close request body: {}", e.getMessage(), e); } } } } } } private Proxy configureProxyAndAuth(final ProxyServer proxyServer, final Realm realm) throws AuthenticationException { Proxy proxy = null; if (proxyServer != null) { String proxyHost = proxyServer.getHost().startsWith("http://") ? proxyServer.getHost().substring("http://".length()) : proxyServer.getHost(); SocketAddress addr = new InetSocketAddress(proxyHost, proxyServer.getPort()); proxy = new Proxy(Proxy.Type.HTTP, addr); } final boolean hasProxy = (proxyServer != null && proxyServer.getPrincipal() != null); final boolean hasAuthentication = (realm != null && realm.getPrincipal() != null); if (hasProxy || hasAuthentication) { Field f = null; try { f = Authenticator.class.getDeclaredField("theAuthenticator"); f.setAccessible(true); jdkAuthenticator = (Authenticator) f.get(Authenticator.class); } catch (NoSuchFieldException e) { } catch (IllegalAccessException e) { } Authenticator.setDefault(new Authenticator() { protected PasswordAuthentication getPasswordAuthentication() { if (hasProxy && getRequestingHost().equals(proxyServer.getHost()) && getRequestingPort() == proxyServer.getPort()) { String password = ""; if (proxyServer.getPassword() != null) { password = proxyServer.getPassword(); } return new PasswordAuthentication(proxyServer.getPrincipal(), password.toCharArray()); } if (hasAuthentication) { return new PasswordAuthentication(realm.getPrincipal(), realm.getPassword().toCharArray()); } return super.getPasswordAuthentication(); } }); } else { Authenticator.setDefault(null); } return proxy; } private InputStream getInputStream(HttpURLConnection urlConnection) throws IOException { if (urlConnection.getResponseCode() < 400) { return urlConnection.getInputStream(); } else { InputStream ein = urlConnection.getErrorStream(); return (ein != null) ? ein : new ByteArrayInputStream(new byte[0]); } } } JDKAsyncHttpProviderConfig.java000066400000000000000000000031031166553056000341570ustar00rootroot00000000000000async-http-client-1.6.5/src/main/java/com/ning/http/client/providers/jdk/* * Copyright (c) 2010-2011 Sonatype, Inc. All rights reserved. * * This program is licensed to you under the Apache License Version 2.0, * and you may not use this file except in compliance with the Apache License Version 2.0. * You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0. * * Unless required by applicable law or agreed to in writing, * software distributed under the Apache License Version 2.0 is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. */ package com.ning.http.client.providers.jdk; import com.ning.http.client.AsyncHttpProviderConfig; import java.util.Map; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; public class JDKAsyncHttpProviderConfig implements AsyncHttpProviderConfig { public static final String FORCE_RESPONSE_BUFFERING = "bufferResponseInMemory"; private final ConcurrentHashMap properties = new ConcurrentHashMap(); public AsyncHttpProviderConfig addProperty(String name, String value) { properties.put(name, value); return this; } public String getProperty(String name) { return properties.get(name); } public String removeProperty(String name) { return properties.remove(name); } public Set> propertiesSet() { return properties.entrySet(); } } async-http-client-1.6.5/src/main/java/com/ning/http/client/providers/jdk/JDKDelegateFuture.java000066400000000000000000000056071166553056000324000ustar00rootroot00000000000000/* * Copyright (c) 2010-2011 Sonatype, Inc. All rights reserved. * * This program is licensed to you under the Apache License Version 2.0, * and you may not use this file except in compliance with the Apache License Version 2.0. * You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0. * * Unless required by applicable law or agreed to in writing, * software distributed under the Apache License Version 2.0 is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. */ package com.ning.http.client.providers.jdk; import com.ning.http.client.AsyncHandler; import com.ning.http.client.ListenableFuture; import java.net.HttpURLConnection; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; public class JDKDelegateFuture extends JDKFuture { private final ListenableFuture delegateFuture; public JDKDelegateFuture(AsyncHandler asyncHandler, int responseTimeoutInMs, ListenableFuture delegateFuture, HttpURLConnection urlConnection) { super(asyncHandler, responseTimeoutInMs, urlConnection); this.delegateFuture = delegateFuture; } public void done(Callable callable) { delegateFuture.done(callable); super.done(callable); } public void abort(Throwable t) { if (innerFuture != null) { innerFuture.cancel(true); } delegateFuture.abort(t); } public boolean cancel(boolean mayInterruptIfRunning) { delegateFuture.cancel(mayInterruptIfRunning); if (innerFuture != null) { return innerFuture.cancel(mayInterruptIfRunning); } else { return false; } } public boolean isCancelled() { if (innerFuture != null) { return innerFuture.isCancelled(); } else { return false; } } public V get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException { V content = null; try { if (innerFuture != null) { content = innerFuture.get(timeout, unit); } } catch (Throwable t) { if (!contentProcessed.get() && timeout != -1 && ((System.currentTimeMillis() - touch.get()) <= responseTimeoutInMs)) { return get(timeout, unit); } timedOut.set(true); delegateFuture.abort(t); } if (exception.get() != null) { delegateFuture.abort(new ExecutionException(exception.get())); } delegateFuture.content(content); delegateFuture.done(null); return content; } } async-http-client-1.6.5/src/main/java/com/ning/http/client/providers/jdk/JDKFuture.java000066400000000000000000000137041166553056000307420ustar00rootroot00000000000000/* * Copyright (c) 2010-2011 Sonatype, Inc. All rights reserved. * * This program is licensed to you under the Apache License Version 2.0, * and you may not use this file except in compliance with the Apache License Version 2.0. * You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0. * * Unless required by applicable law or agreed to in writing, * software distributed under the Apache License Version 2.0 is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. */ package com.ning.http.client.providers.jdk; import com.ning.http.client.AsyncHandler; import com.ning.http.client.listenable.AbstractListenableFuture; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.net.HttpURLConnection; import java.util.concurrent.Callable; import java.util.concurrent.CancellationException; import java.util.concurrent.ExecutionException; import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.atomic.AtomicReference; public class JDKFuture extends AbstractListenableFuture { private final static Logger logger = LoggerFactory.getLogger(JDKFuture.class); protected Future innerFuture; protected final AsyncHandler asyncHandler; protected final int responseTimeoutInMs; protected final AtomicBoolean cancelled = new AtomicBoolean(false); protected final AtomicBoolean timedOut = new AtomicBoolean(false); protected final AtomicBoolean isDone = new AtomicBoolean(false); protected final AtomicReference exception = new AtomicReference(); protected final AtomicLong touch = new AtomicLong(System.currentTimeMillis()); protected final AtomicBoolean contentProcessed = new AtomicBoolean(false); protected final HttpURLConnection urlConnection; private boolean writeHeaders; private boolean writeBody; public JDKFuture(AsyncHandler asyncHandler, int responseTimeoutInMs, HttpURLConnection urlConnection) { this.asyncHandler = asyncHandler; this.responseTimeoutInMs = responseTimeoutInMs; this.urlConnection = urlConnection; writeHeaders = true; writeBody = true; } protected void setInnerFuture(Future innerFuture) { this.innerFuture = innerFuture; } public void done(Callable callable) { isDone.set(true); super.done(); } public void abort(Throwable t) { exception.set(t); if (innerFuture != null) { innerFuture.cancel(true); } if (!timedOut.get() && !cancelled.get()) { try { asyncHandler.onThrowable(t); } catch (Throwable te) { logger.debug("asyncHandler.onThrowable", te); } } super.done(); } public void content(V v) { } public boolean cancel(boolean mayInterruptIfRunning) { if (!cancelled.get() && innerFuture != null) { urlConnection.disconnect(); try { asyncHandler.onThrowable(new CancellationException()); } catch (Throwable te) { logger.debug("asyncHandler.onThrowable", te); } cancelled.set(true); super.done(); return innerFuture.cancel(mayInterruptIfRunning); } else { super.done(); return false; } } public boolean isCancelled() { if (innerFuture != null) { return innerFuture.isCancelled(); } else { return false; } } public boolean isDone() { contentProcessed.set(true); return innerFuture.isDone(); } public V get() throws InterruptedException, ExecutionException { try { return get(responseTimeoutInMs, TimeUnit.MILLISECONDS); } catch (TimeoutException e) { throw new ExecutionException(e); } } public V get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException { V content = null; try { if (innerFuture != null) { content = innerFuture.get(timeout, unit); } } catch (TimeoutException t) { if (!contentProcessed.get() && timeout != -1 && ((System.currentTimeMillis() - touch.get()) <= responseTimeoutInMs)) { return get(timeout, unit); } if (exception.get() == null) { timedOut.set(true); throw new ExecutionException(new TimeoutException(String.format("No response received after %s", responseTimeoutInMs))); } } catch (CancellationException ce) { } if (exception.get() != null) { throw new ExecutionException(exception.get()); } return content; } /** * Is the Future still valid * * @return true if response has expired and should be terminated. */ public boolean hasExpired() { return responseTimeoutInMs != -1 && ((System.currentTimeMillis() - touch.get()) > responseTimeoutInMs); } /** * {@inheritDoc} */ /* @Override */ public void touch() { touch.set(System.currentTimeMillis()); } /** * {@inheritDoc} */ /* @Override */ public boolean getAndSetWriteHeaders(boolean writeHeaders) { boolean b = this.writeHeaders; this.writeHeaders = writeHeaders; return b; } /** * {@inheritDoc} */ /* @Override */ public boolean getAndSetWriteBody(boolean writeBody) { boolean b = this.writeBody; this.writeBody = writeBody; return b; } } async-http-client-1.6.5/src/main/java/com/ning/http/client/providers/jdk/JDKResponse.java000066400000000000000000000203151166553056000312620ustar00rootroot00000000000000/* * Copyright (c) 2010-2011 Sonatype, Inc. All rights reserved. * * This program is licensed to you under the Apache License Version 2.0, * and you may not use this file except in compliance with the Apache License Version 2.0. * You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0. * * Unless required by applicable law or agreed to in writing, * software distributed under the Apache License Version 2.0 is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. */ package com.ning.http.client.providers.jdk; import com.ning.http.client.Cookie; import com.ning.http.client.FluentCaseInsensitiveStringsMap; import com.ning.http.client.HttpResponseBodyPart; import com.ning.http.client.HttpResponseHeaders; import com.ning.http.client.HttpResponseStatus; import com.ning.http.client.Response; import com.ning.http.util.AsyncHttpProviderUtils; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import java.io.UnsupportedEncodingException; import java.net.MalformedURLException; import java.net.URI; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.Map; import java.util.concurrent.atomic.AtomicBoolean; public class JDKResponse implements Response { private final static String DEFAULT_CHARSET = "ISO-8859-1"; private final static String HEADERS_NOT_COMPUTED = "Response's headers hasn't been computed by your AsyncHandler."; private final URI uri; private final Collection bodyParts; private final HttpResponseHeaders headers; private final HttpResponseStatus status; private final List cookies = new ArrayList(); private AtomicBoolean contentComputed = new AtomicBoolean(false); private String content; public JDKResponse(HttpResponseStatus status, HttpResponseHeaders headers, Collection bodyParts) { this.bodyParts = bodyParts; this.headers = headers; this.status = status; uri = this.status.getUrl(); } /* @Override */ public int getStatusCode() { return status.getStatusCode(); } /* @Override */ public String getStatusText() { return status.getStatusText(); } /* @Override */ public String getResponseBody() throws IOException { return getResponseBody(DEFAULT_CHARSET); } public String getResponseBody(String charset) throws IOException { String contentType = getContentType(); if (contentType != null && charset == null) { charset = AsyncHttpProviderUtils.parseCharset(contentType); } if (charset == null) { charset = DEFAULT_CHARSET; } if (!contentComputed.get()) { contentToString(charset); } return content; } String contentToString(String charset) throws UnsupportedEncodingException { StringBuilder b = new StringBuilder(); for (HttpResponseBodyPart bp : bodyParts) { b.append(new String(bp.getBodyPartBytes(), charset)); } content = b.toString(); return content; } /* @Override */ public InputStream getResponseBodyAsStream() throws IOException { if (contentComputed.get()) { return new ByteArrayInputStream(content.getBytes(DEFAULT_CHARSET)); } if (bodyParts.size() > 0) { return new ByteArrayCollectionInputStream(bodyParts.toArray(new HttpResponseBodyPart[bodyParts.size()])); } else { return new ByteArrayInputStream("".getBytes()); } } private static class ByteArrayCollectionInputStream extends InputStream { private final HttpResponseBodyPart[] parts; private int currentPos = 0; private int bytePos = -1; private byte[] active; private int available = 0; public ByteArrayCollectionInputStream(HttpResponseBodyPart[] parts) { this.parts = parts; active = parts[0].getBodyPartBytes(); computeLength(parts); } private void computeLength(HttpResponseBodyPart[] parts){ if (available == 0) { for (HttpResponseBodyPart p : parts) { available += p.getBodyPartBytes().length; } } } @Override public int available() throws IOException { return available; } @Override public int read() throws IOException { if (++bytePos >= active.length) { // No more bytes, so step to the next array. if (++currentPos >= parts.length) { return -1; } bytePos = 0; active = parts[currentPos].getBodyPartBytes(); } return active[bytePos] & 0xFF; } } /* @Override */ public String getResponseBodyExcerpt(int maxLength) throws IOException { return getResponseBodyExcerpt(maxLength, DEFAULT_CHARSET); } public String getResponseBodyExcerpt(int maxLength, String charset) throws IOException { String contentType = getContentType(); if (contentType != null && charset == null) { charset = AsyncHttpProviderUtils.parseCharset(contentType); } if (charset == null) { charset = DEFAULT_CHARSET; } if (!contentComputed.get()) { contentToString(charset == null ? DEFAULT_CHARSET : charset); } return content.length() <= maxLength ? content : content.substring(0, maxLength); } /* @Override */ public URI getUri() throws MalformedURLException { return uri; } /* @Override */ public String getContentType() { if (headers == null) { throw new IllegalStateException(HEADERS_NOT_COMPUTED); } return headers.getHeaders().getFirstValue("Content-Type"); } /* @Override */ public String getHeader(String name) { if (headers == null) { throw new IllegalStateException(); } return headers.getHeaders().getFirstValue(name); } /* @Override */ public List getHeaders(String name) { if (headers == null) { throw new IllegalStateException(HEADERS_NOT_COMPUTED); } return headers.getHeaders().get(name); } /* @Override */ public FluentCaseInsensitiveStringsMap getHeaders() { if (headers == null) { throw new IllegalStateException(HEADERS_NOT_COMPUTED); } return headers.getHeaders(); } /* @Override */ public boolean isRedirected() { return (status.getStatusCode() >= 300) && (status.getStatusCode() <= 399); } /* @Override */ public List getCookies() { if (headers == null) { throw new IllegalStateException(HEADERS_NOT_COMPUTED); } if (cookies.isEmpty()) { for (Map.Entry> header : headers.getHeaders().entrySet()) { if (header.getKey().equalsIgnoreCase("Set-Cookie")) { // TODO: ask for parsed header List v = header.getValue(); for (String value : v) { Cookie cookie = AsyncHttpProviderUtils.parseCookie(value); cookies.add(cookie); } } } } return Collections.unmodifiableList(cookies); } /** * {@inheritDoc} */ /* @Override */ public boolean hasResponseStatus() { return (bodyParts != null ? true : false); } /** * {@inheritDoc} */ /* @Override */ public boolean hasResponseHeaders() { return (headers != null ? true : false); } /** * {@inheritDoc} */ /* @Override */ public boolean hasResponseBody() { return (bodyParts != null && bodyParts.size() > 0 ? true : false); } } async-http-client-1.6.5/src/main/java/com/ning/http/client/providers/jdk/ResponseBodyPart.java000066400000000000000000000032721166553056000324010ustar00rootroot00000000000000/* * Copyright (c) 2010-2011 Sonatype, Inc. All rights reserved. * * This program is licensed to you under the Apache License Version 2.0, * and you may not use this file except in compliance with the Apache License Version 2.0. * You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0. * * Unless required by applicable law or agreed to in writing, * software distributed under the Apache License Version 2.0 is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. */ package com.ning.http.client.providers.jdk; import com.ning.http.client.AsyncHttpProvider; import com.ning.http.client.HttpResponseBodyPart; import java.io.IOException; import java.io.OutputStream; import java.net.URI; import java.nio.ByteBuffer; /** * A callback class used when an HTTP response body is received. */ public class ResponseBodyPart extends HttpResponseBodyPart { private final byte[] chunk; public ResponseBodyPart(URI uri, byte[] chunk, AsyncHttpProvider provider) { super(uri, provider); this.chunk = chunk; } /** * Return the response body's part bytes received. * * @return the response body's part bytes received. */ public byte[] getBodyPartBytes() { return chunk; } @Override public int writeTo(OutputStream outputStream) throws IOException { outputStream.write(chunk); return chunk.length; } @Override public ByteBuffer getBodyByteBuffer() { return ByteBuffer.wrap(chunk); } }async-http-client-1.6.5/src/main/java/com/ning/http/client/providers/jdk/ResponseHeaders.java000066400000000000000000000040721166553056000322270ustar00rootroot00000000000000/* * Copyright (c) 2010-2011 Sonatype, Inc. All rights reserved. * * This program is licensed to you under the Apache License Version 2.0, * and you may not use this file except in compliance with the Apache License Version 2.0. * You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0. * * Unless required by applicable law or agreed to in writing, * software distributed under the Apache License Version 2.0 is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. */ package com.ning.http.client.providers.jdk; import com.ning.http.client.AsyncHttpProvider; import com.ning.http.client.FluentCaseInsensitiveStringsMap; import com.ning.http.client.HttpResponseHeaders; import java.net.HttpURLConnection; import java.net.URI; import java.util.List; import java.util.Map; /** * A class that represent the HTTP headers. */ public class ResponseHeaders extends HttpResponseHeaders { private final HttpURLConnection urlConnection; private final FluentCaseInsensitiveStringsMap headers; public ResponseHeaders(URI uri, HttpURLConnection urlConnection, AsyncHttpProvider provider) { super(uri, provider, false); this.urlConnection = urlConnection; headers = computerHeaders(); } private FluentCaseInsensitiveStringsMap computerHeaders() { FluentCaseInsensitiveStringsMap h = new FluentCaseInsensitiveStringsMap(); Map> uh = urlConnection.getHeaderFields(); for (Map.Entry> e : uh.entrySet()) { if (e.getKey() != null) { h.add(e.getKey(), e.getValue()); } } return h; } /** * Return the HTTP header * * @return an {@link com.ning.http.client.FluentCaseInsensitiveStringsMap} */ @Override public FluentCaseInsensitiveStringsMap getHeaders() { return headers; } }async-http-client-1.6.5/src/main/java/com/ning/http/client/providers/jdk/ResponseStatus.java000066400000000000000000000042121166553056000321330ustar00rootroot00000000000000/* * Copyright (c) 2010-2011 Sonatype, Inc. All rights reserved. * * This program is licensed to you under the Apache License Version 2.0, * and you may not use this file except in compliance with the Apache License Version 2.0. * You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0. * * Unless required by applicable law or agreed to in writing, * software distributed under the Apache License Version 2.0 is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. */ package com.ning.http.client.providers.jdk; import com.ning.http.client.AsyncHttpProvider; import com.ning.http.client.HttpResponseStatus; import java.io.IOException; import java.net.HttpURLConnection; import java.net.URI; /** * A class that represent the HTTP response' status line (code + text) */ public class ResponseStatus extends HttpResponseStatus { private final HttpURLConnection urlConnection; public ResponseStatus(URI uri, HttpURLConnection urlConnection, AsyncHttpProvider provider) { super(uri, provider); this.urlConnection = urlConnection; } /** * Return the response status code * @return the response status code */ public int getStatusCode() { try { return urlConnection.getResponseCode(); } catch (IOException e) { return 500; } } /** * Return the response status text * @return the response status text */ public String getStatusText() { try { return urlConnection.getResponseMessage(); } catch (IOException e) { return "Internal Error"; } } @Override public String getProtocolName() { return "http"; } @Override public int getProtocolMajorVersion() { return 1; } @Override public int getProtocolMinorVersion() { return 1; //TODO } @Override public String getProtocolText() { return ""; //TODO } }async-http-client-1.6.5/src/main/java/com/ning/http/client/providers/netty/000077500000000000000000000000001166553056000266625ustar00rootroot00000000000000async-http-client-1.6.5/src/main/java/com/ning/http/client/providers/netty/BodyChunkedInput.java000066400000000000000000000045011166553056000327440ustar00rootroot00000000000000/* * Copyright (c) 2010-2011 Sonatype, Inc. All rights reserved. * * This program is licensed to you under the Apache License Version 2.0, * and you may not use this file except in compliance with the Apache License Version 2.0. * You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0. * * Unless required by applicable law or agreed to in writing, * software distributed under the Apache License Version 2.0 is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. */ package com.ning.http.client.providers.netty; import com.ning.http.client.Body; import org.jboss.netty.buffer.ChannelBuffers; import org.jboss.netty.handler.stream.ChunkedInput; import java.io.IOException; import java.nio.ByteBuffer; /** * Adapts a {@link Body} to Netty's {@link ChunkedInput}. */ class BodyChunkedInput implements ChunkedInput { private final Body body; private final int chunkSize = 1024 * 8; private ByteBuffer nextChunk; private static final ByteBuffer EOF = ByteBuffer.allocate(0); public BodyChunkedInput(Body body) { if (body == null) { throw new IllegalArgumentException("no body specified"); } this.body = body; } private ByteBuffer peekNextChuck() throws IOException { if (nextChunk == null) { ByteBuffer buffer = ByteBuffer.allocate(chunkSize); if (body.read(buffer) < 0) { nextChunk = EOF; } else { buffer.flip(); nextChunk = buffer; } } return nextChunk; } public boolean hasNextChunk() throws Exception { return !isEndOfInput(); } public Object nextChunk() throws Exception { ByteBuffer buffer = peekNextChuck(); if (buffer == EOF) { return null; } nextChunk = null; return ChannelBuffers.wrappedBuffer(buffer); } public boolean isEndOfInput() throws Exception { return peekNextChuck() == EOF; } public void close() throws Exception { body.close(); } } async-http-client-1.6.5/src/main/java/com/ning/http/client/providers/netty/BodyFileRegion.java000066400000000000000000000033261166553056000323720ustar00rootroot00000000000000/* * Copyright (c) 2010-2011 Sonatype, Inc. All rights reserved. * * This program is licensed to you under the Apache License Version 2.0, * and you may not use this file except in compliance with the Apache License Version 2.0. * You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0. * * Unless required by applicable law or agreed to in writing, * software distributed under the Apache License Version 2.0 is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. */ package com.ning.http.client.providers.netty; import com.ning.http.client.RandomAccessBody; import org.jboss.netty.channel.FileRegion; import java.io.IOException; import java.nio.channels.WritableByteChannel; /** * Adapts a {@link RandomAccessBody} to Netty's {@link FileRegion}. */ class BodyFileRegion implements FileRegion { private final RandomAccessBody body; public BodyFileRegion(RandomAccessBody body) { if (body == null) { throw new IllegalArgumentException("no body specified"); } this.body = body; } public long getPosition() { return 0; } public long getCount() { return body.getContentLength(); } public long transferTo(WritableByteChannel target, long position) throws IOException { return body.transferTo(position, Long.MAX_VALUE, target); } public void releaseExternalResources() { try { body.close(); } catch (IOException e) { // we tried } } } NettyAsyncHttpProvider.java000066400000000000000000002551471166553056000341400ustar00rootroot00000000000000async-http-client-1.6.5/src/main/java/com/ning/http/client/providers/netty/* * Copyright 2010 Ning, Inc. * * Ning licenses this file to you 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. */ package com.ning.http.client.providers.netty; import com.ning.http.client.AsyncHandler; import com.ning.http.client.AsyncHandler.STATE; import com.ning.http.client.AsyncHttpClientConfig; import com.ning.http.client.AsyncHttpProvider; import com.ning.http.client.Body; import com.ning.http.client.ConnectionsPool; import com.ning.http.client.Cookie; import com.ning.http.client.FluentCaseInsensitiveStringsMap; import com.ning.http.client.HttpResponseBodyPart; import com.ning.http.client.HttpResponseHeaders; import com.ning.http.client.HttpResponseStatus; import com.ning.http.client.ListenableFuture; import com.ning.http.client.MaxRedirectException; import com.ning.http.client.PerRequestConfig; import com.ning.http.client.ProgressAsyncHandler; import com.ning.http.client.ProxyServer; import com.ning.http.client.RandomAccessBody; import com.ning.http.client.Realm; import com.ning.http.client.Request; import com.ning.http.client.RequestBuilder; import com.ning.http.client.Response; import com.ning.http.client.filter.FilterContext; import com.ning.http.client.filter.FilterException; import com.ning.http.client.filter.IOExceptionFilter; import com.ning.http.client.filter.ResponseFilter; import com.ning.http.client.listener.TransferCompletionHandler; import com.ning.http.client.ntlm.NTLMEngine; import com.ning.http.client.ntlm.NTLMEngineException; import com.ning.http.client.providers.netty.spnego.SpnegoEngine; import com.ning.http.multipart.MultipartBody; import com.ning.http.multipart.MultipartRequestEntity; import com.ning.http.util.AsyncHttpProviderUtils; import com.ning.http.util.AuthenticatorUtils; import com.ning.http.util.CleanupChannelGroup; import com.ning.http.util.ProxyUtils; import com.ning.http.util.SslUtils; import com.ning.http.util.UTF8UrlEncoder; import org.jboss.netty.bootstrap.ClientBootstrap; import org.jboss.netty.buffer.ChannelBuffer; import org.jboss.netty.buffer.ChannelBufferOutputStream; import org.jboss.netty.buffer.ChannelBuffers; import org.jboss.netty.channel.Channel; import org.jboss.netty.channel.ChannelFuture; import org.jboss.netty.channel.ChannelFutureProgressListener; import org.jboss.netty.channel.ChannelHandlerContext; import org.jboss.netty.channel.ChannelPipeline; import org.jboss.netty.channel.ChannelPipelineFactory; import org.jboss.netty.channel.ChannelStateEvent; import org.jboss.netty.channel.DefaultChannelFuture; import org.jboss.netty.channel.ExceptionEvent; import org.jboss.netty.channel.FileRegion; import org.jboss.netty.channel.MessageEvent; import org.jboss.netty.channel.SimpleChannelUpstreamHandler; import org.jboss.netty.channel.group.ChannelGroup; import org.jboss.netty.channel.socket.ClientSocketChannelFactory; import org.jboss.netty.channel.socket.nio.NioClientSocketChannelFactory; import org.jboss.netty.channel.socket.oio.OioClientSocketChannelFactory; import org.jboss.netty.handler.codec.http.CookieEncoder; import org.jboss.netty.handler.codec.http.DefaultCookie; import org.jboss.netty.handler.codec.http.DefaultHttpChunkTrailer; import org.jboss.netty.handler.codec.http.DefaultHttpRequest; import org.jboss.netty.handler.codec.http.HttpChunk; import org.jboss.netty.handler.codec.http.HttpChunkTrailer; import org.jboss.netty.handler.codec.http.HttpClientCodec; import org.jboss.netty.handler.codec.http.HttpContentCompressor; import org.jboss.netty.handler.codec.http.HttpContentDecompressor; import org.jboss.netty.handler.codec.http.HttpHeaders; import org.jboss.netty.handler.codec.http.HttpMethod; import org.jboss.netty.handler.codec.http.HttpRequest; import org.jboss.netty.handler.codec.http.HttpResponse; import org.jboss.netty.handler.codec.http.HttpVersion; import org.jboss.netty.handler.ssl.SslHandler; import org.jboss.netty.handler.stream.ChunkedFile; import org.jboss.netty.handler.stream.ChunkedWriteHandler; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.net.ssl.SSLEngine; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.RandomAccessFile; import java.net.ConnectException; import java.net.InetSocketAddress; import java.net.MalformedURLException; import java.net.URI; import java.nio.channels.ClosedChannelException; import java.nio.channels.FileChannel; import java.nio.channels.WritableByteChannel; import java.security.GeneralSecurityException; import java.security.NoSuchAlgorithmException; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; import java.util.List; import java.util.Map.Entry; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; import java.util.concurrent.RejectedExecutionException; import java.util.concurrent.Semaphore; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; import java.util.concurrent.atomic.AtomicBoolean; import static com.ning.http.util.AsyncHttpProviderUtils.DEFAULT_CHARSET; import static org.jboss.netty.channel.Channels.pipeline; public class NettyAsyncHttpProvider extends SimpleChannelUpstreamHandler implements AsyncHttpProvider { private final static String HTTP_HANDLER = "httpHandler"; final static String SSL_HANDLER = "sslHandler"; private final static String HTTPS = "https"; private final static String HTTP = "http"; private final static Logger log = LoggerFactory.getLogger(NettyAsyncHttpProvider.class); private final ClientBootstrap plainBootstrap; private final ClientBootstrap secureBootstrap; private final static int MAX_BUFFERED_BYTES = 8192; private final AsyncHttpClientConfig config; private final AtomicBoolean isClose = new AtomicBoolean(false); private final ClientSocketChannelFactory socketChannelFactory; private final ChannelGroup openChannels = new CleanupChannelGroup("asyncHttpClient") { @Override public boolean remove(Object o) { boolean removed = super.remove(o); if (removed && trackConnections) { freeConnections.release(); } return removed; } }; private final ConnectionsPool connectionsPool; private Semaphore freeConnections = null; private final NettyAsyncHttpProviderConfig asyncHttpProviderConfig; private boolean executeConnectAsync = true; public static final ThreadLocal IN_IO_THREAD = new ThreadLocalBoolean(); private final boolean trackConnections; private final boolean useRawUrl; private final static NTLMEngine ntlmEngine = new NTLMEngine(); private final static SpnegoEngine spnegoEngine = new SpnegoEngine(); public NettyAsyncHttpProvider(AsyncHttpClientConfig config) { if (config.getAsyncHttpProviderConfig() != null && NettyAsyncHttpProviderConfig.class.isAssignableFrom(config.getAsyncHttpProviderConfig().getClass())) { asyncHttpProviderConfig = NettyAsyncHttpProviderConfig.class.cast(config.getAsyncHttpProviderConfig()); } else { asyncHttpProviderConfig = new NettyAsyncHttpProviderConfig(); } if (asyncHttpProviderConfig.getProperty(NettyAsyncHttpProviderConfig.USE_BLOCKING_IO) != null) { socketChannelFactory = new OioClientSocketChannelFactory(config.executorService()); } else { ExecutorService e; Object o = asyncHttpProviderConfig.getProperty(NettyAsyncHttpProviderConfig.BOSS_EXECUTOR_SERVICE); if (o != null && ExecutorService.class.isAssignableFrom(o.getClass())) { e = ExecutorService.class.cast(o); } else { e = Executors.newCachedThreadPool(); } int numWorkers = config.getIoThreadMultiplier() * Runtime.getRuntime().availableProcessors(); log.info("Number of application's worked threads is {}", numWorkers); socketChannelFactory = new NioClientSocketChannelFactory(e, config.executorService(), numWorkers); } plainBootstrap = new ClientBootstrap(socketChannelFactory); secureBootstrap = new ClientBootstrap(socketChannelFactory); configureNetty(); this.config = config; // This is dangerous as we can't catch a wrong typed ConnectionsPool ConnectionsPool cp = (ConnectionsPool) config.getConnectionsPool(); if (cp == null && config.getAllowPoolingConnection()) { cp = new NettyConnectionsPool(this); } else if (cp == null) { cp = new NonConnectionsPool(); } this.connectionsPool = cp; if (config.getMaxTotalConnections() != -1) { trackConnections = true; freeConnections = new Semaphore(config.getMaxTotalConnections()); } else { trackConnections = false; } useRawUrl = config.isUseRawUrl(); } @Override public String toString() { return String.format("NettyAsyncHttpProvider:\n\t- maxConnections: %d\n\t- openChannels: %s\n\t- connectionPools: %s", config.getMaxTotalConnections() - freeConnections.availablePermits(), openChannels.toString(), connectionsPool.toString()); } void configureNetty() { if (asyncHttpProviderConfig != null) { for (Entry entry : asyncHttpProviderConfig.propertiesSet()) { plainBootstrap.setOption(entry.getKey(), entry.getValue()); } } plainBootstrap.setPipelineFactory(new ChannelPipelineFactory() { /* @Override */ public ChannelPipeline getPipeline() throws Exception { ChannelPipeline pipeline = pipeline(); pipeline.addLast(HTTP_HANDLER, new HttpClientCodec()); if (config.getRequestCompressionLevel() > 0) { pipeline.addLast("deflater", new HttpContentCompressor(config.getRequestCompressionLevel())); } if (config.isCompressionEnabled()) { pipeline.addLast("inflater", new HttpContentDecompressor()); } pipeline.addLast("chunkedWriter", new ChunkedWriteHandler()); pipeline.addLast("httpProcessor", NettyAsyncHttpProvider.this); return pipeline; } }); DefaultChannelFuture.setUseDeadLockChecker(false); if (asyncHttpProviderConfig != null) { Object value = asyncHttpProviderConfig.getProperty(NettyAsyncHttpProviderConfig.EXECUTE_ASYNC_CONNECT); if (value != null && Boolean.class.isAssignableFrom(value.getClass())) { executeConnectAsync = Boolean.class.cast(value); } else if (asyncHttpProviderConfig.getProperty(NettyAsyncHttpProviderConfig.DISABLE_NESTED_REQUEST) != null) { DefaultChannelFuture.setUseDeadLockChecker(true); } } } void constructSSLPipeline(final NettyConnectListener cl) { secureBootstrap.setPipelineFactory(new ChannelPipelineFactory() { /* @Override */ public ChannelPipeline getPipeline() throws Exception { ChannelPipeline pipeline = pipeline(); try { pipeline.addLast(SSL_HANDLER, new SslHandler(createSSLEngine())); } catch (Throwable ex) { abort(cl.future(), ex); } pipeline.addLast(HTTP_HANDLER, new HttpClientCodec()); if (config.isCompressionEnabled()) { pipeline.addLast("inflater", new HttpContentDecompressor()); } pipeline.addLast("chunkedWriter", new ChunkedWriteHandler()); pipeline.addLast("httpProcessor", NettyAsyncHttpProvider.this); return pipeline; } }); if (asyncHttpProviderConfig != null) { for (Entry entry : asyncHttpProviderConfig.propertiesSet()) { secureBootstrap.setOption(entry.getKey(), entry.getValue()); } } } private Channel lookupInCache(URI uri) { final Channel channel = connectionsPool.poll(AsyncHttpProviderUtils.getBaseUrl(uri)); if (channel != null) { log.debug("Using cached Channel {}\n for uri {}\n", channel, uri); try { // Always make sure the channel who got cached support the proper protocol. It could // only occurs when a HttpMethod.CONNECT is used agains a proxy that require upgrading from http to // https. return verifyChannelPipeline(channel, uri.getScheme()); } catch (Exception ex) { log.debug(ex.getMessage(), ex); } } return null; } private SSLEngine createSSLEngine() throws IOException, GeneralSecurityException { SSLEngine sslEngine = config.getSSLEngineFactory().newSSLEngine(); if (sslEngine == null) { sslEngine = SslUtils.getSSLEngine(); } return sslEngine; } private Channel verifyChannelPipeline(Channel channel, String scheme) throws IOException, GeneralSecurityException { if (channel.getPipeline().get(SSL_HANDLER) != null && HTTP.equalsIgnoreCase(scheme)) { channel.getPipeline().remove(SSL_HANDLER); } else if (channel.getPipeline().get(HTTP_HANDLER) != null && HTTP.equalsIgnoreCase(scheme)) { return channel; } else if (channel.getPipeline().get(SSL_HANDLER) == null && HTTPS.equalsIgnoreCase(scheme)) { channel.getPipeline().addFirst(SSL_HANDLER, new SslHandler(createSSLEngine())); } return channel; } protected final void writeRequest(final Channel channel, final AsyncHttpClientConfig config, final NettyResponseFuture future, final HttpRequest nettyRequest) { try { /** * If the channel is dead because it was pooled and the remote server decided to close it, * we just let it go and the closeChannel do it's work. */ if (!channel.isOpen() || !channel.isConnected()) { return; } Body body = null; if (!future.getNettyRequest().getMethod().equals(HttpMethod.CONNECT)) { if (future.getRequest().getBodyGenerator() != null) { try { body = future.getRequest().getBodyGenerator().createBody(); } catch (IOException ex) { throw new IllegalStateException(ex); } long length = body.getContentLength(); if (length >= 0) { nettyRequest.setHeader(HttpHeaders.Names.CONTENT_LENGTH, length); } else { nettyRequest.setHeader(HttpHeaders.Names.TRANSFER_ENCODING, HttpHeaders.Values.CHUNKED); } } else { body = null; } } if (TransferCompletionHandler.class.isAssignableFrom(future.getAsyncHandler().getClass())) { FluentCaseInsensitiveStringsMap h = new FluentCaseInsensitiveStringsMap(); for (String s : future.getNettyRequest().getHeaderNames()) { for (String header : future.getNettyRequest().getHeaders(s)) { h.add(s, header); } } TransferCompletionHandler.class.cast(future.getAsyncHandler()).transferAdapter( new NettyTransferAdapter(h, nettyRequest.getContent(), future.getRequest().getFile())); } // Leave it to true. if (future.getAndSetWriteHeaders(true)) { try { channel.write(nettyRequest).addListener(new ProgressListener(true, future.getAsyncHandler(), future)); } catch (Throwable cause) { log.debug(cause.getMessage(), cause); try { channel.close(); } catch (RuntimeException ex) { log.debug(ex.getMessage(), ex); } return; } } if (future.getAndSetWriteBody(true)) { if (!future.getNettyRequest().getMethod().equals(HttpMethod.CONNECT)) { if (future.getRequest().getFile() != null) { final File file = future.getRequest().getFile(); long fileLength = 0; final RandomAccessFile raf = new RandomAccessFile(file, "r"); try { fileLength = raf.length(); ChannelFuture writeFuture; if (channel.getPipeline().get(SslHandler.class) != null) { writeFuture = channel.write(new ChunkedFile(raf, 0, fileLength, 8192)); } else { final FileRegion region = new OptimizedFileRegion(raf, 0, fileLength); writeFuture = channel.write(region); } writeFuture.addListener(new ProgressListener(false, future.getAsyncHandler(), future)); } catch (IOException ex) { if (raf != null) { try { raf.close(); } catch (IOException e) { } } throw ex; } } else if (body != null || future.getRequest().getParts() != null) { /** * TODO: AHC-78: SSL + zero copy isn't supported by the MultiPart class and pretty complex to implements. */ if (future.getRequest().getParts() != null) { String boundary = future.getNettyRequest().getHeader("Content-Type"); String length = future.getNettyRequest().getHeader("Content-Length"); body = new MultipartBody(future.getRequest().getParts(), boundary, length); } ChannelFuture writeFuture; if (channel.getPipeline().get(SslHandler.class) == null && (body instanceof RandomAccessBody)) { BodyFileRegion bodyFileRegion = new BodyFileRegion((RandomAccessBody) body); writeFuture = channel.write(bodyFileRegion); } else { BodyChunkedInput bodyChunkedInput = new BodyChunkedInput(body); writeFuture = channel.write(bodyChunkedInput); } final Body b = body; writeFuture.addListener(new ProgressListener(false, future.getAsyncHandler(), future) { public void operationComplete(ChannelFuture cf) { try { b.close(); } catch (IOException e) { log.warn("Failed to close request body: {}", e.getMessage(), e); } super.operationComplete(cf); } }); } } } } catch (Throwable ioe) { try { channel.close(); } catch (RuntimeException ex) { log.debug(ex.getMessage(), ex); } } try { future.touch(); int delay = requestTimeout(config, future.getRequest().getPerRequestConfig()); if (delay != -1 && !future.isDone() && !future.isCancelled()) { ReaperFuture reaperFuture = new ReaperFuture(channel, future); Future scheduledFuture = config.reaper().scheduleAtFixedRate(reaperFuture, 0, delay, TimeUnit.MILLISECONDS); reaperFuture.setScheduledFuture(scheduledFuture); future.setReaperFuture(reaperFuture); } } catch (RejectedExecutionException ex) { abort(future, ex); } } protected final static HttpRequest buildRequest(AsyncHttpClientConfig config, Request request, URI uri, boolean allowConnect, ChannelBuffer buffer) throws IOException { String method = request.getMethod(); if (allowConnect && ((request.getProxyServer() != null || config.getProxyServer() != null) && HTTPS.equalsIgnoreCase(uri.getScheme()))) { method = HttpMethod.CONNECT.toString(); } return construct(config, request, new HttpMethod(method), uri, buffer); } @SuppressWarnings("deprecation") private static HttpRequest construct(AsyncHttpClientConfig config, Request request, HttpMethod m, URI uri, ChannelBuffer buffer) throws IOException { String host = uri.getHost(); if (request.getVirtualHost() != null) { host = request.getVirtualHost(); } HttpRequest nettyRequest; if (m.equals(HttpMethod.CONNECT)) { nettyRequest = new DefaultHttpRequest(HttpVersion.HTTP_1_0, m, AsyncHttpProviderUtils.getAuthority(uri)); } else if (config.getProxyServer() != null || request.getProxyServer() != null) { nettyRequest = new DefaultHttpRequest(HttpVersion.HTTP_1_1, m, uri.toString()); } else { StringBuilder path = new StringBuilder(uri.getRawPath()); if (uri.getQuery() != null) { path.append("?").append(uri.getRawQuery()); } nettyRequest = new DefaultHttpRequest(HttpVersion.HTTP_1_1, m, path.toString()); } if (host != null) { if (uri.getPort() == -1) { nettyRequest.setHeader(HttpHeaders.Names.HOST, host); } else if (request.getVirtualHost() != null) { nettyRequest.setHeader(HttpHeaders.Names.HOST, host); } else { nettyRequest.setHeader(HttpHeaders.Names.HOST, host + ":" + uri.getPort()); } } else { host = "127.0.0.1"; } if (!m.equals(HttpMethod.CONNECT)) { FluentCaseInsensitiveStringsMap h = request.getHeaders(); if (h != null) { for (String name : h.keySet()) { if (!"host".equalsIgnoreCase(name)) { for (String value : h.get(name)) { nettyRequest.addHeader(name, value); } } } } if (config.isCompressionEnabled()) { nettyRequest.setHeader(HttpHeaders.Names.ACCEPT_ENCODING, HttpHeaders.Values.GZIP); } } ProxyServer proxyServer = request.getProxyServer() != null ? request.getProxyServer() : config.getProxyServer(); Realm realm = request.getRealm() != null ? request.getRealm() : config.getRealm(); if (realm != null && realm.getUsePreemptiveAuth()) { String domain = realm.getNtlmDomain(); if (proxyServer != null && proxyServer.getNtlmDomain() != null) { domain = proxyServer.getNtlmDomain(); } String authHost = realm.getNtlmHost(); if (proxyServer != null && proxyServer.getHost() != null) { host = proxyServer.getHost(); } switch (realm.getAuthScheme()) { case BASIC: nettyRequest.setHeader(HttpHeaders.Names.AUTHORIZATION, AuthenticatorUtils.computeBasicAuthentication(realm)); break; case DIGEST: if (realm.getNonce() != null && !realm.getNonce().equals("")) { try { nettyRequest.setHeader(HttpHeaders.Names.AUTHORIZATION, AuthenticatorUtils.computeDigestAuthentication(realm)); } catch (NoSuchAlgorithmException e) { throw new SecurityException(e); } } break; case NTLM: try { nettyRequest.setHeader(HttpHeaders.Names.AUTHORIZATION, ntlmEngine.generateType1Msg("NTLM " + domain, authHost)); } catch (NTLMEngineException e) { IOException ie = new IOException(); ie.initCause(e); throw ie; } break; case KERBEROS: case SPNEGO: String challengeHeader = null; String server = proxyServer == null ? host : proxyServer.getHost(); try { challengeHeader = spnegoEngine.generateToken(server); } catch (Throwable e) { IOException ie = new IOException(); ie.initCause(e); throw ie; } nettyRequest.setHeader(HttpHeaders.Names.AUTHORIZATION, "Negotiate " + challengeHeader); break; case NONE: break; default: throw new IllegalStateException(String.format("Invalid Authentication %s", realm.toString())); } } if (!request.getHeaders().containsKey(HttpHeaders.Names.CONNECTION)) { nettyRequest.setHeader(HttpHeaders.Names.CONNECTION, "keep-alive"); } boolean avoidProxy = ProxyUtils.avoidProxy(proxyServer, request); if (!avoidProxy) { if (!request.getHeaders().containsKey("Proxy-Connection")) { nettyRequest.setHeader("Proxy-Connection", "keep-alive"); } if (proxyServer.getPrincipal() != null) { nettyRequest.setHeader(HttpHeaders.Names.PROXY_AUTHORIZATION, AuthenticatorUtils.computeBasicAuthentication(proxyServer)); } } // Add default accept headers. if (request.getHeaders().getFirstValue("Accept") == null) { nettyRequest.setHeader(HttpHeaders.Names.ACCEPT, "*/*"); } if (request.getHeaders().getFirstValue("User-Agent") != null) { nettyRequest.setHeader("User-Agent", request.getHeaders().getFirstValue("User-Agent")); } else if (config.getUserAgent() != null) { nettyRequest.setHeader("User-Agent", config.getUserAgent()); } else { nettyRequest.setHeader("User-Agent", AsyncHttpProviderUtils.constructUserAgent(NettyAsyncHttpProvider.class)); } if (!m.equals(HttpMethod.CONNECT)) { if (request.getCookies() != null && !request.getCookies().isEmpty()) { CookieEncoder httpCookieEncoder = new CookieEncoder(false); Iterator ic = request.getCookies().iterator(); Cookie c; org.jboss.netty.handler.codec.http.Cookie cookie; while (ic.hasNext()) { c = ic.next(); cookie = new DefaultCookie(c.getName(), c.getValue()); cookie.setPath(c.getPath()); cookie.setMaxAge(c.getMaxAge()); cookie.setDomain(c.getDomain()); httpCookieEncoder.addCookie(cookie); } nettyRequest.setHeader(HttpHeaders.Names.COOKIE, httpCookieEncoder.encode()); } String reqType = request.getMethod(); if (!"GET".equals(reqType) && !"HEAD".equals(reqType) && !"OPTION".equals(reqType) && !"TRACE".equals(reqType)) { String bodyCharset = request.getBodyEncoding() == null ? DEFAULT_CHARSET : request.getBodyEncoding(); // We already have processed the body. if (buffer != null && buffer.writerIndex() != 0) { nettyRequest.setHeader(HttpHeaders.Names.CONTENT_LENGTH, buffer.writerIndex()); nettyRequest.setContent(buffer); } else if (request.getByteData() != null) { nettyRequest.setHeader(HttpHeaders.Names.CONTENT_LENGTH, String.valueOf(request.getByteData().length)); nettyRequest.setContent(ChannelBuffers.wrappedBuffer(request.getByteData())); } else if (request.getStringData() != null) { nettyRequest.setHeader(HttpHeaders.Names.CONTENT_LENGTH, String.valueOf(request.getStringData().getBytes(bodyCharset).length)); nettyRequest.setContent(ChannelBuffers.wrappedBuffer(request.getStringData().getBytes(bodyCharset))); } else if (request.getStreamData() != null) { int[] lengthWrapper = new int[1]; byte[] bytes = AsyncHttpProviderUtils.readFully(request.getStreamData(), lengthWrapper); int length = lengthWrapper[0]; nettyRequest.setHeader(HttpHeaders.Names.CONTENT_LENGTH, String.valueOf(length)); nettyRequest.setContent(ChannelBuffers.wrappedBuffer(bytes, 0, length)); } else if (request.getParams() != null) { StringBuilder sb = new StringBuilder(); for (final Entry> paramEntry : request.getParams()) { final String key = paramEntry.getKey(); for (final String value : paramEntry.getValue()) { if (sb.length() > 0) { sb.append("&"); } UTF8UrlEncoder.appendEncoded(sb, key); sb.append("="); UTF8UrlEncoder.appendEncoded(sb, value); } } nettyRequest.setHeader(HttpHeaders.Names.CONTENT_LENGTH, String.valueOf(sb.length())); nettyRequest.setContent(ChannelBuffers.wrappedBuffer(sb.toString().getBytes(bodyCharset))); if (!request.getHeaders().containsKey(HttpHeaders.Names.CONTENT_TYPE)) { nettyRequest.setHeader(HttpHeaders.Names.CONTENT_TYPE, "application/x-www-form-urlencoded"); } } else if (request.getParts() != null) { int lenght = computeAndSetContentLength(request, nettyRequest); if (lenght == -1) { lenght = MAX_BUFFERED_BYTES; } MultipartRequestEntity mre = AsyncHttpProviderUtils.createMultipartRequestEntity(request.getParts(), request.getParams()); nettyRequest.setHeader(HttpHeaders.Names.CONTENT_TYPE, mre.getContentType()); nettyRequest.setHeader(HttpHeaders.Names.CONTENT_LENGTH, String.valueOf(mre.getContentLength())); /** * TODO: AHC-78: SSL + zero copy isn't supported by the MultiPart class and pretty complex to implements. */ if (uri.toString().startsWith("https")) { ChannelBuffer b = ChannelBuffers.dynamicBuffer(lenght); mre.writeRequest(new ChannelBufferOutputStream(b)); nettyRequest.setContent(b); } } else if (request.getEntityWriter() != null) { int lenght = computeAndSetContentLength(request, nettyRequest); if (lenght == -1) { lenght = MAX_BUFFERED_BYTES; } ChannelBuffer b = ChannelBuffers.dynamicBuffer(lenght); request.getEntityWriter().writeEntity(new ChannelBufferOutputStream(b)); nettyRequest.setHeader(HttpHeaders.Names.CONTENT_LENGTH, b.writerIndex()); nettyRequest.setContent(b); } else if (request.getFile() != null) { File file = request.getFile(); if (!file.isFile()) { throw new IOException(String.format("File %s is not a file or doesn't exist", file.getAbsolutePath())); } nettyRequest.setHeader(HttpHeaders.Names.CONTENT_LENGTH, file.length()); } } } return nettyRequest; } public void close() { isClose.set(true); try { connectionsPool.destroy(); openChannels.close(); for (Channel channel : openChannels) { ChannelHandlerContext ctx = channel.getPipeline().getContext(NettyAsyncHttpProvider.class); if (ctx.getAttachment() instanceof NettyResponseFuture) { NettyResponseFuture future = (NettyResponseFuture) ctx.getAttachment(); future.setReaperFuture(null); } } config.executorService().shutdown(); config.reaper().shutdown(); socketChannelFactory.releaseExternalResources(); plainBootstrap.releaseExternalResources(); secureBootstrap.releaseExternalResources(); } catch (Throwable t) { log.warn("Unexpected error on close", t); } } /* @Override */ public Response prepareResponse(final HttpResponseStatus status, final HttpResponseHeaders headers, final Collection bodyParts) { return new NettyResponse(status, headers, bodyParts); } /* @Override */ public ListenableFuture execute(Request request, final AsyncHandler asyncHandler) throws IOException { return doConnect(request, asyncHandler, null, true, executeConnectAsync, false); } private void execute(final Request request, final NettyResponseFuture f, boolean useCache, boolean asyncConnect) throws IOException { doConnect(request, f.getAsyncHandler(), f, useCache, asyncConnect, false); } private void execute(final Request request, final NettyResponseFuture f, boolean useCache, boolean asyncConnect, boolean reclaimCache) throws IOException { doConnect(request, f.getAsyncHandler(), f, useCache, asyncConnect, reclaimCache); } private ListenableFuture doConnect(final Request request, final AsyncHandler asyncHandler, NettyResponseFuture f, boolean useCache, boolean asyncConnect, boolean reclaimCache) throws IOException { if (isClose.get()) { throw new IOException("Closed"); } ProxyServer proxyServer = request.getProxyServer() != null ? request.getProxyServer() : config.getProxyServer(); String requestUrl; if (useRawUrl) { requestUrl = request.getRawUrl(); } else { requestUrl = request.getUrl(); } URI uri = AsyncHttpProviderUtils.createUri(requestUrl); Channel channel = null; if (useCache) { if (f != null && f.reuseChannel() && f.channel() != null) { channel = f.channel(); } else { channel = lookupInCache(uri); } } ChannelBuffer bufferedBytes = null; if (f != null && f.getRequest().getFile() == null && !f.getNettyRequest().getMethod().getName().equals(HttpMethod.CONNECT.getName())) { bufferedBytes = f.getNettyRequest().getContent(); } boolean useSSl = uri.getScheme().compareToIgnoreCase(HTTPS) == 0 && proxyServer == null; if (channel != null && channel.isOpen() && channel.isConnected()) { HttpRequest nettyRequest = buildRequest(config, request, uri, false, bufferedBytes); if (f == null) { f = newFuture(uri, request, asyncHandler, nettyRequest, config, this); } else { f.setNettyRequest(nettyRequest); } f.setState(NettyResponseFuture.STATE.POOLED); f.attachChannel(channel, false); log.debug("\nUsing cached Channel {}\n for request \n{}\n", channel, nettyRequest); channel.getPipeline().getContext(NettyAsyncHttpProvider.class).setAttachment(f); try { writeRequest(channel, config, f, nettyRequest); } catch (Exception ex) { log.debug("writeRequest failure", ex); if (useSSl && ex.getMessage() != null && ex.getMessage().contains("SSLEngine")) { log.debug("SSLEngine failure", ex); f = null; } else { try { asyncHandler.onThrowable(ex); } catch (Throwable t) { log.warn("doConnect.writeRequest()", t); } IOException ioe = new IOException(ex.getMessage()); ioe.initCause(ex); throw ioe; } } return f; } // Do not throw an exception when we need an extra connection for a redirect. if (!reclaimCache && !connectionsPool.canCacheConnection()) { IOException ex = new IOException(String.format("Too many connections %s", config.getMaxTotalConnections())); try { asyncHandler.onThrowable(ex); } catch (Throwable t) { log.warn("!connectionsPool.canCacheConnection()", t); } throw ex; } boolean acquiredConnection = false; if (trackConnections) { if (!reclaimCache) { if (!freeConnections.tryAcquire()) { IOException ex = new IOException(String.format("Too many connections %s", config.getMaxTotalConnections())); try { asyncHandler.onThrowable(ex); } catch (Throwable t) { log.warn("!connectionsPool.canCacheConnection()", t); } throw ex; } else { acquiredConnection = true; } } } NettyConnectListener c = new NettyConnectListener.Builder(config, request, asyncHandler, f, this, bufferedBytes).build(uri); boolean avoidProxy = ProxyUtils.avoidProxy(proxyServer, uri.getHost()); if (useSSl) { constructSSLPipeline(c); } ChannelFuture channelFuture; ClientBootstrap bootstrap = useSSl ? secureBootstrap : plainBootstrap; bootstrap.setOption("connectTimeoutMillis", config.getConnectionTimeoutInMs()); // Do no enable this with win. if (System.getProperty("os.name").toLowerCase().indexOf("win") == -1) { bootstrap.setOption("reuseAddress", asyncHttpProviderConfig.getProperty(NettyAsyncHttpProviderConfig.REUSE_ADDRESS)); } try { if (proxyServer == null || avoidProxy) { channelFuture = bootstrap.connect(new InetSocketAddress(uri.getHost(), AsyncHttpProviderUtils.getPort(uri))); } else { channelFuture = bootstrap.connect(new InetSocketAddress(proxyServer.getHost(), proxyServer.getPort())); } } catch (Throwable t) { if (acquiredConnection) { freeConnections.release(); } abort(c.future(), t.getCause() == null ? t : t.getCause()); return c.future(); } boolean directInvokation = true; if (IN_IO_THREAD.get() && DefaultChannelFuture.isUseDeadLockChecker()) { directInvokation = false; } if (directInvokation && !asyncConnect && request.getFile() == null) { int timeOut = config.getConnectionTimeoutInMs() > 0 ? config.getConnectionTimeoutInMs() : Integer.MAX_VALUE; if (!channelFuture.awaitUninterruptibly(timeOut, TimeUnit.MILLISECONDS)) { if (acquiredConnection) { freeConnections.release(); } channelFuture.cancel(); abort(c.future(), new ConnectException(String.format("Connect operation to %s timeout %s", uri, timeOut))); } try { c.operationComplete(channelFuture); } catch (Exception e) { if (acquiredConnection) { freeConnections.release(); } IOException ioe = new IOException(e.getMessage()); ioe.initCause(e); try { asyncHandler.onThrowable(ioe); } catch (Throwable t) { log.warn("c.operationComplete()", t); } throw ioe; } } else { channelFuture.addListener(c); } log.debug("\nNon cached request \n{}\n\nusing Channel \n{}\n", c.future().getNettyRequest(), channelFuture.getChannel()); if (!c.future().isCancelled() || !c.future().isDone()) { openChannels.add(channelFuture.getChannel()); c.future().attachChannel(channelFuture.getChannel(), false); } return c.future(); } protected static int requestTimeout(AsyncHttpClientConfig config, PerRequestConfig perRequestConfig) { int result; if (perRequestConfig != null) { int prRequestTimeout = perRequestConfig.getRequestTimeoutInMs(); result = (prRequestTimeout != 0 ? prRequestTimeout : config.getRequestTimeoutInMs()); } else { result = config.getRequestTimeoutInMs(); } return result; } private void closeChannel(final ChannelHandlerContext ctx) { connectionsPool.removeAll(ctx.getChannel()); finishChannel(ctx); } private void finishChannel(final ChannelHandlerContext ctx) { ctx.setAttachment(new DiscardEvent()); // The channel may have already been removed if a timeout occurred, and this method may be called just after. if (ctx.getChannel() == null) { return; } log.debug("Closing Channel {} ", ctx.getChannel()); try { ctx.getChannel().close(); } catch (Throwable t) { log.debug("Error closing a connection", t); } if (ctx.getChannel() != null) { openChannels.remove(ctx.getChannel()); } } @Override public void messageReceived(final ChannelHandlerContext ctx, MessageEvent e) throws Exception { //call super to reset the read timeout super.messageReceived(ctx, e); IN_IO_THREAD.set(Boolean.TRUE); if (ctx.getAttachment() == null) { log.debug("ChannelHandlerContext wasn't having any attachment"); } if (ctx.getAttachment() instanceof DiscardEvent) { return; } else if (ctx.getAttachment() instanceof AsyncCallable) { if (e.getMessage() instanceof HttpChunk) { HttpChunk chunk = (HttpChunk) e.getMessage(); if (chunk.isLast()) { AsyncCallable ac = (AsyncCallable) ctx.getAttachment(); ac.call(); } else { return; } } else { AsyncCallable ac = (AsyncCallable) ctx.getAttachment(); ac.call(); } ctx.setAttachment(new DiscardEvent()); return; } else if (!(ctx.getAttachment() instanceof NettyResponseFuture)) { try { ctx.getChannel().close(); } catch (Throwable t) { log.trace("Closing an orphan channel {}", ctx.getChannel()); } return; } final NettyResponseFuture future = (NettyResponseFuture) ctx.getAttachment(); future.touch(); // The connect timeout occured. if (future.isCancelled() || future.isDone()) { finishChannel(ctx); return; } HttpRequest nettyRequest = future.getNettyRequest(); AsyncHandler handler = future.getAsyncHandler(); Request request = future.getRequest(); HttpResponse response = null; try { if (e.getMessage() instanceof HttpResponse) { response = (HttpResponse) e.getMessage(); log.debug("\n\nRequest {}\n\nResponse {}\n", nettyRequest, response); // Required if there is some trailing headers. future.setHttpResponse(response); int statusCode = response.getStatus().getCode(); String ka = response.getHeader(HttpHeaders.Names.CONNECTION); future.setKeepAlive(ka == null || ka.toLowerCase().equals("keep-alive")); List wwwAuth = getAuthorizationToken(response.getHeaders(), HttpHeaders.Names.WWW_AUTHENTICATE); Realm realm = request.getRealm() != null ? request.getRealm() : config.getRealm(); HttpResponseStatus status = new ResponseStatus(future.getURI(), response, this); FilterContext fc = new FilterContext.FilterContextBuilder().asyncHandler(handler).request(request).responseStatus(status).build(); for (ResponseFilter asyncFilter : config.getResponseFilters()) { try { fc = asyncFilter.filter(fc); if (fc == null) { throw new NullPointerException("FilterContext is null"); } } catch (FilterException efe) { abort(future, efe); } } // The request has changed if (fc.replayRequest()) { replayRequest(future, fc, response, ctx); return; } Realm newRealm = null; ProxyServer proxyServer = request.getProxyServer() != null ? request.getProxyServer() : config.getProxyServer(); final FluentCaseInsensitiveStringsMap headers = request.getHeaders(); final RequestBuilder builder = new RequestBuilder(future.getRequest()); if (realm != null && !future.getURI().getPath().equalsIgnoreCase(realm.getUri())) { builder.setUrl(future.getURI().toString()); } if (statusCode == 401 && wwwAuth.size() > 0 && !future.getAndSetAuth(true)) { future.setState(NettyResponseFuture.STATE.NEW); // NTLM if ( !wwwAuth.contains("Kerberos") && (wwwAuth.contains("NTLM") || (wwwAuth.contains("Negotiate"))) ) { newRealm = ntlmChallenge(wwwAuth, request, proxyServer, headers, realm, future); // SPNEGO KERBEROS } else if (wwwAuth.contains("Negotiate")) { newRealm = kerberosChallenge(wwwAuth, request, proxyServer, headers, realm, future ); if (newRealm == null) return; } else { Realm.RealmBuilder realmBuilder; if (realm != null) { realmBuilder = new Realm.RealmBuilder().clone(realm).setScheme(realm.getAuthScheme()) ; } else { realmBuilder = new Realm.RealmBuilder(); } newRealm = realmBuilder .setUri(URI.create(request.getUrl()).getPath()) .setMethodName(request.getMethod()) .setUsePreemptiveAuth(true) .parseWWWAuthenticateHeader(wwwAuth.get(0)) .build(); } final Realm nr = newRealm; log.debug("Sending authentication to {}", request.getUrl()); AsyncCallable ac = new AsyncCallable(future) { public Object call() throws Exception { drainChannel(ctx, future, future.getKeepAlive(), future.getURI()); nextRequest(builder.setHeaders(headers).setRealm(nr).build(), future); return null; } }; if (future.getKeepAlive() && response.isChunked()) { // We must make sure there is no bytes left before executing the next request. ctx.setAttachment(ac); } else { ac.call(); } return; } if (statusCode == 100) { future.getAndSetWriteHeaders(false); future.getAndSetWriteBody(true); writeRequest(ctx.getChannel(), config, future, nettyRequest); return; } List proxyAuth = getAuthorizationToken(response.getHeaders(), HttpHeaders.Names.PROXY_AUTHENTICATE); if (statusCode == 407 && proxyAuth.size() > 0 && !future.getAndSetAuth(true)) { log.debug("Sending proxy authentication to {}", request.getUrl()); future.setState(NettyResponseFuture.STATE.NEW); if (!proxyAuth.contains("Kerberos") && (proxyAuth.contains("NTLM") || (proxyAuth.contains("Negotiate")))) { newRealm = ntlmChallenge(proxyAuth, request, proxyServer, headers, realm, future); // SPNEGO KERBEROS } else if (proxyAuth.contains("Negotiate")) { newRealm = kerberosChallenge(proxyAuth, request, proxyServer, headers, realm, future); if (newRealm == null) return; } else { newRealm = future.getRequest().getRealm(); } nextRequest(builder.setHeaders(headers).setRealm(newRealm).build(), future); return; } if (future.getNettyRequest().getMethod().equals(HttpMethod.CONNECT) && statusCode == 200) { log.debug("Connected to {}:{}", proxyServer.getHost(), proxyServer.getPort()); if (future.getKeepAlive()) { future.attachChannel(ctx.getChannel(), true); } try { log.debug("Connecting to proxy {} for scheme {}", proxyServer, request.getUrl()); upgradeProtocol(ctx.getChannel().getPipeline(), request.getUrl()); } catch (Throwable ex) { abort(future, ex); } nextRequest(builder.build(), future); return; } boolean redirectEnabled = request.isRedirectEnabled() ? true : config.isRedirectEnabled(); if (redirectEnabled && (statusCode == 302 || statusCode == 301)) { if (future.incrementAndGetCurrentRedirectCount() < config.getMaxRedirects()) { // We must allow 401 handling again. future.getAndSetAuth(false); String location = response.getHeader(HttpHeaders.Names.LOCATION); URI uri = AsyncHttpProviderUtils.getRedirectUri(future.getURI(), location); boolean stripQueryString = config.isRemoveQueryParamOnRedirect(); if (!uri.toString().equalsIgnoreCase(future.getURI().toString())) { final RequestBuilder nBuilder = stripQueryString ? new RequestBuilder(future.getRequest()).setQueryParameters(null) : new RequestBuilder(future.getRequest()); final URI initialConnectionUri = future.getURI(); final boolean initialConnectionKeepAlive = future.getKeepAlive(); future.setURI(uri); final String newUrl = uri.toString(); log.debug("Redirecting to {}", newUrl); for(String cookieStr : future.getHttpResponse().getHeaders(HttpHeaders.Names.SET_COOKIE)){ Cookie c = AsyncHttpProviderUtils.parseCookie(cookieStr); nBuilder.addOrReplaceCookie(c); } for(String cookieStr : future.getHttpResponse().getHeaders(HttpHeaders.Names.SET_COOKIE2)){ Cookie c = AsyncHttpProviderUtils.parseCookie(cookieStr); nBuilder.addOrReplaceCookie(c); } AsyncCallable ac = new AsyncCallable(future) { public Object call() throws Exception { if (initialConnectionKeepAlive && ctx.getChannel().isReadable() && connectionsPool.offer(AsyncHttpProviderUtils.getBaseUrl(initialConnectionUri), ctx.getChannel())) { return null; } finishChannel(ctx); return null; } }; if (response.isChunked()) { // We must make sure there is no bytes left before executing the next request. ctx.setAttachment(ac); } else { ac.call(); } nextRequest(nBuilder.setUrl(newUrl).build(), future); return; } } else { throw new MaxRedirectException("Maximum redirect reached: " + config.getMaxRedirects()); } } if (!future.getAndSetStatusReceived(true) && updateStatusAndInterrupt(handler, status)) { finishUpdate(future, ctx, response.isChunked()); return; } else if (updateHeadersAndInterrupt(handler, new ResponseHeaders(future.getURI(), response, this))) { finishUpdate(future, ctx, response.isChunked()); return; } else if (!response.isChunked()) { if (response.getContent().readableBytes() != 0) { updateBodyAndInterrupt(handler, new ResponseBodyPart(future.getURI(), response, this)); } finishUpdate(future, ctx, false); return; } if (nettyRequest.getMethod().equals(HttpMethod.HEAD)) { updateBodyAndInterrupt(handler, new ResponseBodyPart(future.getURI(), response, this)); markAsDone(future, ctx); drainChannel(ctx, future, future.getKeepAlive(), future.getURI()); } } else if (e.getMessage() instanceof HttpChunk) { HttpChunk chunk = (HttpChunk) e.getMessage(); if (handler != null) { if (chunk.isLast() || updateBodyAndInterrupt(handler, new ResponseBodyPart(future.getURI(), null, this, chunk))) { if (chunk instanceof DefaultHttpChunkTrailer) { updateHeadersAndInterrupt(handler, new ResponseHeaders(future.getURI(), future.getHttpResponse(), this, (HttpChunkTrailer) chunk)); } finishUpdate(future, ctx, !chunk.isLast()); } } } } catch (Exception t) { if (IOException.class.isAssignableFrom(t.getClass()) && config.getIOExceptionFilters().size() > 0) { FilterContext fc = new FilterContext.FilterContextBuilder().asyncHandler(future.getAsyncHandler()) .request(future.getRequest()).ioException(IOException.class.cast(t)).build(); fc = handleIoException(fc, future); if (fc.replayRequest()) { replayRequest(future, fc, response, ctx); return; } } try { abort(future, t); } finally { finishUpdate(future, ctx, false); throw t; } } } private Realm kerberosChallenge(List proxyAuth, Request request, ProxyServer proxyServer, FluentCaseInsensitiveStringsMap headers, Realm realm, NettyResponseFuture future) throws NTLMEngineException { URI uri = URI.create(request.getUrl()); String host = request.getVirtualHost() == null ? uri.getHost() : request.getVirtualHost(); String server = proxyServer == null ? host : proxyServer.getHost(); try { String challengeHeader = spnegoEngine.generateToken(server); headers.remove(HttpHeaders.Names.AUTHORIZATION); headers.add(HttpHeaders.Names.AUTHORIZATION, "Negotiate " + challengeHeader); Realm.RealmBuilder realmBuilder; if (realm != null) { realmBuilder = new Realm.RealmBuilder().clone(realm); } else { realmBuilder = new Realm.RealmBuilder(); } return realmBuilder.setUri(uri.getPath()) .setMethodName(request.getMethod()) .setScheme(Realm.AuthScheme.KERBEROS) .build(); } catch (Throwable throwable) { if (proxyAuth.contains("NTLM")) { return ntlmChallenge(proxyAuth, request, proxyServer, headers, realm, future); } abort(future, throwable); return null; } } private Realm ntlmChallenge(List wwwAuth, Request request, ProxyServer proxyServer, FluentCaseInsensitiveStringsMap headers, Realm realm, NettyResponseFuture future) throws NTLMEngineException { boolean useRealm = (proxyServer == null && realm != null); String ntlmDomain = useRealm? realm.getNtlmDomain() : proxyServer.getNtlmDomain(); String ntlmHost = useRealm ? realm.getNtlmHost() : proxyServer.getHost(); String principal = useRealm ? realm.getPrincipal() : proxyServer.getPrincipal(); String password = useRealm ? realm.getPassword() : proxyServer.getPassword(); Realm newRealm; if (realm != null && !realm.isNtlmMessageType2Received()) { String challengeHeader = ntlmEngine.generateType1Msg(ntlmDomain, ntlmHost); headers.add(HttpHeaders.Names.AUTHORIZATION, "NTLM " + challengeHeader); newRealm = new Realm.RealmBuilder().clone(realm).setScheme(realm.getAuthScheme()) .setUri(URI.create(request.getUrl()).getPath()) .setMethodName(request.getMethod()) .setNtlmMessageType2Received(true) .build(); future.getAndSetAuth(false); } else { headers.remove(HttpHeaders.Names.AUTHORIZATION); if (wwwAuth.get(0).startsWith("NTLM ")) { String serverChallenge = wwwAuth.get(0).trim().substring("NTLM ".length()); String challengeHeader = ntlmEngine.generateType3Msg(principal, password, ntlmDomain, ntlmHost, serverChallenge); headers.add(HttpHeaders.Names.AUTHORIZATION, "NTLM " + challengeHeader); } Realm.RealmBuilder realmBuilder; if (realm != null) { realmBuilder = new Realm.RealmBuilder().clone(realm); } else { realmBuilder = new Realm.RealmBuilder(); } newRealm = realmBuilder.setScheme(realm.getAuthScheme()) .setUri(URI.create(request.getUrl()).getPath()) .setMethodName(request.getMethod()) .build(); } return newRealm; } private void drainChannel(final ChannelHandlerContext ctx, final NettyResponseFuture future, final boolean keepAlive, final URI uri) { ctx.setAttachment(new AsyncCallable(future) { public Object call() throws Exception { if (keepAlive && ctx.getChannel().isReadable() && connectionsPool.offer(AsyncHttpProviderUtils.getBaseUrl(uri), ctx.getChannel())) { return null; } finishChannel(ctx); return null; } @Override public String toString() { return String.format("Draining task for channel %s", ctx.getChannel()); } }); } private FilterContext handleIoException(FilterContext fc, NettyResponseFuture future) { for (IOExceptionFilter asyncFilter : config.getIOExceptionFilters()) { try { fc = asyncFilter.filter(fc); if (fc == null) { throw new NullPointerException("FilterContext is null"); } } catch (FilterException efe) { abort(future, efe); } } return fc; } private void replayRequest(final NettyResponseFuture future, FilterContext fc, HttpResponse response, ChannelHandlerContext ctx) throws IOException { final Request newRequest = fc.getRequest(); future.setAsyncHandler(fc.getAsyncHandler()); future.setState(NettyResponseFuture.STATE.NEW); future.touch(); log.debug("\n\nReplaying Request {}\n for Future {}\n", newRequest, future); drainChannel(ctx, future, future.getKeepAlive(), future.getURI()); nextRequest(newRequest, future); return; } private List getAuthorizationToken(List> list, String headerAuth) { ArrayList l = new ArrayList(); for (Entry e : list) { if (e.getKey().equalsIgnoreCase(headerAuth)) { l.add(e.getValue().trim()); } } return l; } private void nextRequest(final Request request, final NettyResponseFuture future) throws IOException { nextRequest(request, future, true); } private void nextRequest(final Request request, final NettyResponseFuture future, final boolean useCache) throws IOException { execute(request, future, useCache, true, true); } private void abort(NettyResponseFuture future, Throwable t) { Channel channel = future.channel(); if (channel != null && openChannels.contains(channel)) { closeChannel(channel.getPipeline().getContext(NettyAsyncHttpProvider.class)); openChannels.remove(channel); } if (!future.isCancelled() && !future.isDone()) { log.debug("Aborting Future {}\n", future); log.debug(t.getMessage(), t); } future.abort(t); } private void upgradeProtocol(ChannelPipeline p, String scheme) throws IOException, GeneralSecurityException { if (p.get(HTTP_HANDLER) != null) { p.remove(HTTP_HANDLER); } if (scheme.startsWith(HTTPS)) { if (p.get(SSL_HANDLER) == null) { p.addFirst(HTTP_HANDLER, new HttpClientCodec()); p.addFirst(SSL_HANDLER, new SslHandler(createSSLEngine())); } else { p.addAfter(SSL_HANDLER, HTTP_HANDLER, new HttpClientCodec()); } } else { p.addFirst(HTTP_HANDLER, new HttpClientCodec()); } } public void channelClosed(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception { if (isClose.get()) { return; } connectionsPool.removeAll(ctx.getChannel()); try { super.channelClosed(ctx, e); } catch (Exception ex) { log.trace("super.channelClosed", ex); } log.debug("Channel Closed: {} with attachment {}", e.getChannel(), ctx.getAttachment()); if (ctx.getAttachment() instanceof AsyncCallable) { AsyncCallable ac = (AsyncCallable) ctx.getAttachment(); ctx.setAttachment(ac.future()); ac.call(); return; } if (ctx.getAttachment() instanceof NettyResponseFuture) { NettyResponseFuture future = (NettyResponseFuture) ctx.getAttachment(); future.touch(); if (config.getIOExceptionFilters().size() > 0) { FilterContext fc = new FilterContext.FilterContextBuilder().asyncHandler(future.getAsyncHandler()) .request(future.getRequest()).ioException(new IOException("Channel Closed")).build(); fc = handleIoException(fc, future); if (fc.replayRequest() && !future.cannotBeReplay()) { replayRequest(future, fc, null, ctx); return; } } if (future != null && !future.isDone() && !future.isCancelled()) { if (!remotelyClosed(ctx.getChannel(), future)) { abort(future, new IOException("Remotely Closed " + ctx.getChannel())); } } else { closeChannel(ctx); } } } protected boolean remotelyClosed(Channel channel, NettyResponseFuture future) { if (isClose.get()) { return false; } connectionsPool.removeAll(channel); if (future == null && channel.getPipeline().getContext(NettyAsyncHttpProvider.class).getAttachment() != null && NettyResponseFuture.class.isAssignableFrom( channel.getPipeline().getContext(NettyAsyncHttpProvider.class).getAttachment().getClass())) { future = (NettyResponseFuture) channel.getPipeline().getContext(NettyAsyncHttpProvider.class).getAttachment(); } if (future == null || future.cannotBeReplay()) { log.debug("Unable to recover future {}\n", future); return false; } future.setState(NettyResponseFuture.STATE.RECONNECTED); log.debug("Trying to recover request {}\n", future.getNettyRequest()); try { nextRequest(future.getRequest(), future); return true; } catch (IOException iox) { future.setState(NettyResponseFuture.STATE.CLOSED); future.abort(iox); log.error("Remotely Closed, unable to recover", iox); } return false; } private void markAsDone(final NettyResponseFuture future, final ChannelHandlerContext ctx) throws MalformedURLException { // We need to make sure everything is OK before adding the connection back to the pool. try { future.done(null); } catch (Throwable t) { // Never propagate exception once we know we are done. log.debug(t.getMessage(), t); } if (!future.getKeepAlive() || !ctx.getChannel().isReadable()) { closeChannel(ctx); } } private void finishUpdate(final NettyResponseFuture future, final ChannelHandlerContext ctx, boolean lastValidChunk) throws IOException { if (lastValidChunk && future.getKeepAlive()) { drainChannel(ctx, future, future.getKeepAlive(), future.getURI()); } else { if (future.getKeepAlive() && ctx.getChannel().isReadable() && connectionsPool.offer(AsyncHttpProviderUtils.getBaseUrl(future.getURI()), ctx.getChannel())) { markAsDone(future, ctx); return; } finishChannel(ctx); } markAsDone(future, ctx); } @SuppressWarnings("unchecked") private final boolean updateStatusAndInterrupt(AsyncHandler handler, HttpResponseStatus c) throws Exception { return handler.onStatusReceived(c) != STATE.CONTINUE; } @SuppressWarnings("unchecked") private final boolean updateHeadersAndInterrupt(AsyncHandler handler, HttpResponseHeaders c) throws Exception { return handler.onHeadersReceived(c) != STATE.CONTINUE; } @SuppressWarnings("unchecked") private final boolean updateBodyAndInterrupt(AsyncHandler handler, HttpResponseBodyPart c) throws Exception { return handler.onBodyPartReceived(c) != STATE.CONTINUE; } //Simple marker for stopping publishing bytes. final static class DiscardEvent { } @Override public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) throws Exception { Channel channel = e.getChannel(); Throwable cause = e.getCause(); NettyResponseFuture future = null; if (log.isDebugEnabled()) { log.debug("Unexpected I/O exception on channel {}", channel, cause); } try { if (cause != null && ClosedChannelException.class.isAssignableFrom(cause.getClass())) { return; } if (ctx.getAttachment() instanceof NettyResponseFuture) { future = (NettyResponseFuture) ctx.getAttachment(); future.attachChannel(null, false); future.touch(); if (IOException.class.isAssignableFrom(cause.getClass())) { if (config.getIOExceptionFilters().size() > 0) { FilterContext fc = new FilterContext.FilterContextBuilder().asyncHandler(future.getAsyncHandler()) .request(future.getRequest()).ioException(new IOException("Channel Closed")).build(); fc = handleIoException(fc, future); if (fc.replayRequest()) { replayRequest(future, fc, null, ctx); return; } } else { // Close the channel so the recovering can occurs. try { ctx.getChannel().close(); } catch (Throwable t) { ; // Swallow. } return; } } if (abortOnReadCloseException(cause) || abortOnWriteCloseException(cause)) { log.debug("Trying to recover from dead Channel: {}", channel); return; } } else if (ctx.getAttachment() instanceof AsyncCallable) { future = ((AsyncCallable) ctx.getAttachment()).future(); } } catch (Throwable t) { cause = t; } if (future != null) { try { log.debug("Was unable to recover Future: {}", future); abort(future, cause); } catch (Throwable t) { log.error(t.getMessage(), t); } } closeChannel(ctx); ctx.sendUpstream(e); } protected static boolean abortOnConnectCloseException(Throwable cause) { try { for (StackTraceElement element : cause.getStackTrace()) { if (element.getClassName().equals("sun.nio.ch.SocketChannelImpl") && element.getMethodName().equals("checkConnect")) { return true; } } if (cause.getCause() != null) { return abortOnConnectCloseException(cause.getCause()); } } catch (Throwable t) { } return false; } protected static boolean abortOnDisconnectException(Throwable cause) { try { for (StackTraceElement element : cause.getStackTrace()) { if (element.getClassName().equals("org.jboss.netty.handler.ssl.SslHandler") && element.getMethodName().equals("channelDisconnected")) { return true; } } if (cause.getCause() != null) { return abortOnConnectCloseException(cause.getCause()); } } catch (Throwable t) { } return false; } protected static boolean abortOnReadCloseException(Throwable cause) { for (StackTraceElement element : cause.getStackTrace()) { if (element.getClassName().equals("sun.nio.ch.SocketDispatcher") && element.getMethodName().equals("read")) { return true; } } if (cause.getCause() != null) { return abortOnReadCloseException(cause.getCause()); } return false; } protected static boolean abortOnWriteCloseException(Throwable cause) { for (StackTraceElement element : cause.getStackTrace()) { if (element.getClassName().equals("sun.nio.ch.SocketDispatcher") && element.getMethodName().equals("write")) { return true; } } if (cause.getCause() != null) { return abortOnReadCloseException(cause.getCause()); } return false; } private final static int computeAndSetContentLength(Request request, HttpRequest r) { int length = (int) request.getContentLength(); if (length == -1 && r.getHeader(HttpHeaders.Names.CONTENT_LENGTH) != null) { length = Integer.valueOf(r.getHeader(HttpHeaders.Names.CONTENT_LENGTH)); } if (length >= 0) { r.setHeader(HttpHeaders.Names.CONTENT_LENGTH, String.valueOf(length)); } return length; } public static NettyResponseFuture newFuture(URI uri, Request request, AsyncHandler asyncHandler, HttpRequest nettyRequest, AsyncHttpClientConfig config, NettyAsyncHttpProvider provider) { NettyResponseFuture f = new NettyResponseFuture(uri, request, asyncHandler, nettyRequest, requestTimeout(config, request.getPerRequestConfig()), provider); if (request.getHeaders().getFirstValue("Expect") != null && request.getHeaders().getFirstValue("Expect").equalsIgnoreCase("100-Continue")) { f.getAndSetWriteBody(false); } return f; } private class ProgressListener implements ChannelFutureProgressListener { private final boolean notifyHeaders; private final AsyncHandler asyncHandler; private final NettyResponseFuture future; public ProgressListener(boolean notifyHeaders, AsyncHandler asyncHandler, NettyResponseFuture future) { this.notifyHeaders = notifyHeaders; this.asyncHandler = asyncHandler; this.future = future; } public void operationComplete(ChannelFuture cf) { // The write operation failed. If the channel was cached, it means it got asynchronously closed. // Let's retry a second time. Throwable cause = cf.getCause(); if (cause != null && future.getState() != NettyResponseFuture.STATE.NEW) { if (IllegalStateException.class.isAssignableFrom(cause.getClass())) { log.debug(cause.getMessage(), cause); try { cf.getChannel().close(); } catch (RuntimeException ex) { log.debug(ex.getMessage(), ex); } return; } if (ClosedChannelException.class.isAssignableFrom(cause.getClass()) || abortOnReadCloseException(cause) || abortOnWriteCloseException(cause)) { if (log.isDebugEnabled()) { log.debug(cf.getCause() == null ? "" : cf.getCause().getMessage(), cf.getCause()); } try { cf.getChannel().close(); } catch (RuntimeException ex) { log.debug(ex.getMessage(), ex); } return; } else { future.abort(cause); } return; } future.touch(); /** * We need to make sure we aren't in the middle of an authorization process before publishing events * as we will re-publish again the same event after the authorization, causing unpredictable behavior. */ Realm realm = future.getRequest().getRealm() != null ? future.getRequest().getRealm() : NettyAsyncHttpProvider.this.getConfig().getRealm(); boolean startPublishing = future.isInAuth() || realm == null || realm.getUsePreemptiveAuth() == true; if (startPublishing && ProgressAsyncHandler.class.isAssignableFrom(asyncHandler.getClass())) { if (notifyHeaders) { ProgressAsyncHandler.class.cast(asyncHandler).onHeaderWriteCompleted(); } else { ProgressAsyncHandler.class.cast(asyncHandler).onContentWriteCompleted(); } } } public void operationProgressed(ChannelFuture cf, long amount, long current, long total) { future.touch(); if (ProgressAsyncHandler.class.isAssignableFrom(asyncHandler.getClass())) { ProgressAsyncHandler.class.cast(asyncHandler).onContentWriteProgress(amount, current, total); } } } /** * Because some implementation of the ThreadSchedulingService do not clean up cancel task until they try to run * them, we wrap the task with the future so the when the NettyResponseFuture cancel the reaper future * this wrapper will release the references to the channel and the nettyResponseFuture immediately. Otherwise, * the memory referenced this way will only be released after the request timeout period which can be arbitrary long. */ private final class ReaperFuture implements Future, Runnable { private Future scheduledFuture; private Channel channel; private NettyResponseFuture nettyResponseFuture; public ReaperFuture(Channel channel, NettyResponseFuture nettyResponseFuture) { this.channel = channel; this.nettyResponseFuture = nettyResponseFuture; } public void setScheduledFuture(Future scheduledFuture) { this.scheduledFuture = scheduledFuture; } /** * @Override */ public synchronized boolean cancel(boolean mayInterruptIfRunning) { //cleanup references to allow gc to reclaim memory independently //of this Future lifecycle this.channel = null; this.nettyResponseFuture = null; return this.scheduledFuture.cancel(mayInterruptIfRunning); } /** * @Override */ public Object get() throws InterruptedException, ExecutionException { return this.scheduledFuture.get(); } /** * @Override */ public Object get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException { return this.scheduledFuture.get(timeout, unit); } /** * @Override */ public boolean isCancelled() { return this.scheduledFuture.isCancelled(); } /** * @Override */ public boolean isDone() { return this.scheduledFuture.isDone(); } /** * @Override */ public synchronized void run() { if (isClose.get()) { cancel(true); return; } if (this.nettyResponseFuture != null && this.nettyResponseFuture.hasExpired() && !this.nettyResponseFuture.isDone() && !this.nettyResponseFuture.isCancelled()) { log.debug("Request Timeout expired for {}\n", this.nettyResponseFuture); int requestTimeout = config.getRequestTimeoutInMs(); PerRequestConfig p = this.nettyResponseFuture.getRequest().getPerRequestConfig(); if (p != null && p.getRequestTimeoutInMs() != -1) { requestTimeout = p.getRequestTimeoutInMs(); } abort(this.nettyResponseFuture, new TimeoutException(String.format("No response received after %s", requestTimeout))); this.nettyResponseFuture = null; this.channel = null; } if (this.nettyResponseFuture == null || this.nettyResponseFuture.isDone() || this.nettyResponseFuture.isCancelled()) { cancel(true); } } } private abstract class AsyncCallable implements Callable { private final NettyResponseFuture future; public AsyncCallable(NettyResponseFuture future) { this.future = future; } abstract public Object call() throws Exception; public NettyResponseFuture future() { return future; } } public static class ThreadLocalBoolean extends ThreadLocal { private final boolean defaultValue; public ThreadLocalBoolean() { this(false); } public ThreadLocalBoolean(boolean defaultValue) { this.defaultValue = defaultValue; } @Override protected Boolean initialValue() { return defaultValue ? Boolean.TRUE : Boolean.FALSE; } } public static class OptimizedFileRegion implements FileRegion { private final FileChannel file; private final RandomAccessFile raf; private final long position; private final long count; private long byteWritten; public OptimizedFileRegion(RandomAccessFile raf, long position, long count) { this.raf = raf; this.file = raf.getChannel(); this.position = position; this.count = count; } public long getPosition() { return position; } public long getCount() { return count; } public long transferTo(WritableByteChannel target, long position) throws IOException { long count = this.count - position; if (count < 0 || position < 0) { throw new IllegalArgumentException( "position out of range: " + position + " (expected: 0 - " + (this.count - 1) + ")"); } if (count == 0) { return 0L; } long bw = file.transferTo(this.position + position, count, target); byteWritten += bw; if (byteWritten == raf.length()) { releaseExternalResources(); } return bw; } public void releaseExternalResources() { try { file.close(); } catch (IOException e) { log.warn("Failed to close a file.", e); } try { raf.close(); } catch (IOException e) { log.warn("Failed to close a file.", e); } } } private static class NettyTransferAdapter extends TransferCompletionHandler.TransferAdapter { private final ChannelBuffer content; private final FileInputStream file; private int byteRead = 0; public NettyTransferAdapter(FluentCaseInsensitiveStringsMap headers, ChannelBuffer content, File file) throws IOException { super(headers); this.content = content; if (file != null) { this.file = new FileInputStream(file); } else { this.file = null; } } @Override public void getBytes(byte[] bytes) { if (content.writableBytes() != 0) { content.getBytes(byteRead, bytes); byteRead += bytes.length; } else if (file != null) { try { byteRead += file.read(bytes); } catch (IOException e) { log.error(e.getMessage(), e); } } } } protected AsyncHttpClientConfig getConfig() { return config; } private static class NonConnectionsPool implements ConnectionsPool { public boolean offer(String uri, Channel connection) { return false; } public Channel poll(String uri) { return null; } public boolean removeAll(Channel connection) { return false; } public boolean canCacheConnection() { return true; } public void destroy() { } } } NettyAsyncHttpProviderConfig.java000066400000000000000000000063201166553056000352510ustar00rootroot00000000000000async-http-client-1.6.5/src/main/java/com/ning/http/client/providers/netty/* * Copyright 2010 Ning, Inc. * * Ning licenses this file to you 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. * */ package com.ning.http.client.providers.netty; import com.ning.http.client.AsyncHttpProviderConfig; import java.util.Map; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ExecutorService; /** * This class can be used to pass Netty's internal configuration options. See Netty documentation for more information. */ public class NettyAsyncHttpProviderConfig implements AsyncHttpProviderConfig { /** * Use Netty's blocking IO stategy. */ public final static String USE_BLOCKING_IO = "useBlockingIO"; /** * Use direct {@link java.nio.ByteBuffer} */ public final static String USE_DIRECT_BYTEBUFFER = "bufferFactory"; /** * Execute the connect operation asynchronously. */ public final static String EXECUTE_ASYNC_CONNECT = "asyncConnect"; /** * Allow nested request from any {@link com.ning.http.client.AsyncHandler} */ public final static String DISABLE_NESTED_REQUEST = "disableNestedRequest"; /** * Allow configuring the Netty's boss executor service. */ public final static String BOSS_EXECUTOR_SERVICE = "bossExecutorService"; /** * See {@link java.net.Socket#setReuseAddress(boolean)} */ public final static String REUSE_ADDRESS = "reuseAddress"; private final ConcurrentHashMap properties = new ConcurrentHashMap(); public NettyAsyncHttpProviderConfig(){ properties.put(REUSE_ADDRESS, "false"); } /** * Add a property that will be used when the AsyncHttpClient initialize its {@link com.ning.http.client.AsyncHttpProvider} * * @param name the name of the property * @param value the value of the property * @return this instance of AsyncHttpProviderConfig */ public NettyAsyncHttpProviderConfig addProperty(String name, Object value) { properties.put(name, value); return this; } /** * Return the value associated with the property's name * * @param name * @return this instance of AsyncHttpProviderConfig */ public Object getProperty(String name) { return properties.get(name); } /** * Remove the value associated with the property's name * * @param name * @return true if removed */ public Object removeProperty(String name) { return properties.remove(name); } /** * Return the curent entry set. * * @return a the curent entry set. */ public Set> propertiesSet() { return properties.entrySet(); } } async-http-client-1.6.5/src/main/java/com/ning/http/client/providers/netty/NettyConnectListener.java000066400000000000000000000136201166553056000336520ustar00rootroot00000000000000/* * Copyright 2010 Ning, Inc. * * Ning licenses this file to you 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. * */ package com.ning.http.client.providers.netty; import com.ning.http.client.AsyncHandler; import com.ning.http.client.AsyncHttpClientConfig; import com.ning.http.client.Request; import org.jboss.netty.buffer.ChannelBuffer; import org.jboss.netty.channel.Channel; import org.jboss.netty.channel.ChannelFuture; import org.jboss.netty.channel.ChannelFutureListener; import org.jboss.netty.handler.codec.http.HttpRequest; import org.jboss.netty.handler.ssl.SslHandler; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.IOException; import java.net.ConnectException; import java.net.InetSocketAddress; import java.net.URI; import java.nio.channels.ClosedChannelException; import java.util.concurrent.atomic.AtomicBoolean; /** * Non Blocking connect. */ final class NettyConnectListener implements ChannelFutureListener { private final static Logger logger = LoggerFactory.getLogger(NettyConnectListener.class); private final AsyncHttpClientConfig config; private final NettyResponseFuture future; private final HttpRequest nettyRequest; private final AtomicBoolean handshakeDone = new AtomicBoolean(false); private NettyConnectListener(AsyncHttpClientConfig config, NettyResponseFuture future, HttpRequest nettyRequest) { this.config = config; this.future = future; this.nettyRequest = nettyRequest; } public NettyResponseFuture future() { return future; } public final void operationComplete(ChannelFuture f) throws Exception { if (f.isSuccess()) { Channel channel = f.getChannel(); channel.getPipeline().getContext(NettyAsyncHttpProvider.class).setAttachment(future); SslHandler sslHandler = (SslHandler) channel.getPipeline().get(NettyAsyncHttpProvider.SSL_HANDLER); if (!handshakeDone.getAndSet(true) && (sslHandler != null)) { ((SslHandler) channel.getPipeline().get(NettyAsyncHttpProvider.SSL_HANDLER)).handshake().addListener(this); return; } if (sslHandler != null) { if (!config.getHostnameVerifier().verify(InetSocketAddress.class.cast(channel.getRemoteAddress()).getHostName(), sslHandler.getEngine().getSession())) { throw new ConnectException("HostnameVerifier exception."); } } future.provider().writeRequest(f.getChannel(), config, future, nettyRequest); } else { Throwable cause = f.getCause(); logger.debug("Trying to recover a dead cached channel {} with a retry value of {} ", f.getChannel(), future.canRetry()); if (future.canRetry() && cause != null && (NettyAsyncHttpProvider.abortOnDisconnectException(cause) || ClosedChannelException.class.isAssignableFrom(cause.getClass()) || future.getState() != NettyResponseFuture.STATE.NEW)) { logger.debug("Retrying {} ", nettyRequest); if (future.provider().remotelyClosed(f.getChannel(), future)) { return; } } logger.debug("Failed to recover from exception: {} with channel {}", cause, f.getChannel()); ConnectException e = new ConnectException(f.getCause() != null ? cause.getMessage() + " to " + future.getURI().toString(): future.getURI().toString()); if (cause != null) { e.initCause(cause); } future.abort(e); } } public static class Builder { private final AsyncHttpClientConfig config; private final Request request; private final AsyncHandler asyncHandler; private NettyResponseFuture future; private final NettyAsyncHttpProvider provider; private final ChannelBuffer buffer; public Builder(AsyncHttpClientConfig config, Request request, AsyncHandler asyncHandler, NettyAsyncHttpProvider provider, ChannelBuffer buffer) { this.config = config; this.request = request; this.asyncHandler = asyncHandler; this.future = null; this.provider = provider; this.buffer = buffer; } public Builder(AsyncHttpClientConfig config, Request request, AsyncHandler asyncHandler, NettyResponseFuture future, NettyAsyncHttpProvider provider, ChannelBuffer buffer) { this.config = config; this.request = request; this.asyncHandler = asyncHandler; this.future = future; this.provider = provider; this.buffer = buffer; } public NettyConnectListener build(final URI uri) throws IOException { HttpRequest nettyRequest = NettyAsyncHttpProvider.buildRequest(config, request, uri, true, buffer); if (future == null) { future = NettyAsyncHttpProvider.newFuture(uri, request, asyncHandler, nettyRequest, config, provider); } else { future.setNettyRequest(nettyRequest); future.setRequest(request); } return new NettyConnectListener(config, future, nettyRequest); } } } async-http-client-1.6.5/src/main/java/com/ning/http/client/providers/netty/NettyConnectionsPool.java000066400000000000000000000243401166553056000336700ustar00rootroot00000000000000/* * Copyright (c) 2010-2011 Sonatype, Inc. All rights reserved. * * This program is licensed to you under the Apache License Version 2.0, * and you may not use this file except in compliance with the Apache License Version 2.0. * You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0. * * Unless required by applicable law or agreed to in writing, * software distributed under the Apache License Version 2.0 is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. */ package com.ning.http.client.providers.netty; import com.ning.http.client.ConnectionsPool; import org.jboss.netty.channel.Channel; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.ArrayList; import java.util.List; import java.util.Set; import java.util.Timer; import java.util.TimerTask; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.atomic.AtomicBoolean; /** * A simple implementation of {@link com.ning.http.client.ConnectionsPool} based on a {@link java.util.concurrent.ConcurrentHashMap} */ public class NettyConnectionsPool implements ConnectionsPool { private final static Logger log = LoggerFactory.getLogger(NettyConnectionsPool.class); private final ConcurrentHashMap> connectionsPool = new ConcurrentHashMap>(); private final ConcurrentHashMap channel2IdleChannel = new ConcurrentHashMap(); private final AtomicBoolean isClosed = new AtomicBoolean(false); private final Timer idleConnectionDetector = new Timer(); private final boolean sslConnectionPoolEnabled; private final int maxTotalConnections; private final int maxConnectionPerHost; private final long maxIdleTime; public NettyConnectionsPool(NettyAsyncHttpProvider provider) { this.maxTotalConnections = provider.getConfig().getMaxTotalConnections(); this.maxConnectionPerHost = provider.getConfig().getMaxConnectionPerHost(); this.sslConnectionPoolEnabled = provider.getConfig().isSslConnectionPoolEnabled(); this.maxIdleTime = provider.getConfig().getIdleConnectionInPoolTimeoutInMs(); this.idleConnectionDetector.schedule(new IdleChannelDetector(), maxIdleTime, maxIdleTime); } private static class IdleChannel { final String uri; final Channel channel; final long start; IdleChannel(String uri, Channel channel) { this.uri = uri; this.channel = channel; this.start = System.currentTimeMillis(); } @Override public boolean equals(Object o) { if (this == o) return true; if (!(o instanceof IdleChannel)) return false; IdleChannel that = (IdleChannel) o; if (channel != null ? !channel.equals(that.channel) : that.channel != null) return false; return true; } @Override public int hashCode() { return channel != null ? channel.hashCode() : 0; } } private class IdleChannelDetector extends TimerTask { @Override public void run() { try { if (isClosed.get()) return; if (log.isDebugEnabled()) { Set keys = connectionsPool.keySet(); for (String s : keys) { log.debug("Entry count for : {} : {}", s, connectionsPool.get(s).size()); } } List channelsInTimeout = new ArrayList(); long currentTime = System.currentTimeMillis(); for (IdleChannel idleChannel : channel2IdleChannel.values()) { long age = currentTime - idleChannel.start; if (age > maxIdleTime) { log.debug("Adding Candidate Idle Channel {}", idleChannel.channel); // store in an unsynchronized list to minimize the impact on the ConcurrentHashMap. channelsInTimeout.add(idleChannel); } } long endConcurrentLoop = System.currentTimeMillis(); for (IdleChannel idleChannel : channelsInTimeout) { Object attachment = idleChannel.channel.getPipeline().getContext(NettyAsyncHttpProvider.class).getAttachment(); if (attachment != null) { if (NettyResponseFuture.class.isAssignableFrom(attachment.getClass())) { NettyResponseFuture future = (NettyResponseFuture) attachment; if (!future.isDone() && !future.isCancelled()) { log.debug("Future not in appropriate state %s\n", future); continue; } } } if (remove(idleChannel)) { log.debug("Closing Idle Channel {}", idleChannel.channel); close(idleChannel.channel); } } log.trace(String.format("%d channel open, %d idle channels closed (times: 1st-loop=%d, 2nd-loop=%d).\n", connectionsPool.size(), channelsInTimeout.size(), endConcurrentLoop - currentTime, System.currentTimeMillis() - endConcurrentLoop)); } catch (Throwable t) { log.error("uncaught exception!", t); } } } /** * {@inheritDoc} */ public boolean offer(String uri, Channel channel) { if (isClosed.get()) return false; if (!sslConnectionPoolEnabled && uri.startsWith("https")) { return false; } log.debug("Adding uri: {} for channel {}", uri, channel); channel.getPipeline().getContext(NettyAsyncHttpProvider.class).setAttachment(new NettyAsyncHttpProvider.DiscardEvent()); ConcurrentLinkedQueue idleConnectionForHost = connectionsPool.get(uri); if (idleConnectionForHost == null) { ConcurrentLinkedQueue newPool = new ConcurrentLinkedQueue(); idleConnectionForHost = connectionsPool.putIfAbsent(uri, newPool); if (idleConnectionForHost == null) idleConnectionForHost = newPool; } boolean added; int size = idleConnectionForHost.size(); if (maxConnectionPerHost == -1 || size < maxConnectionPerHost) { IdleChannel idleChannel = new IdleChannel(uri, channel); synchronized(idleConnectionForHost) { added = idleConnectionForHost.add(idleChannel); if (channel2IdleChannel.put(channel, idleChannel) != null) { log.error("Channel {} already exists in the connections pool!", channel); } } } else { log.debug("Maximum number of requests per host reached {} for {}", maxConnectionPerHost, uri); added = false; } return added; } /** * {@inheritDoc} */ public Channel poll(String uri) { if (!sslConnectionPoolEnabled && uri.startsWith("https")) { return null; } IdleChannel idleChannel = null; ConcurrentLinkedQueue idleConnectionForHost = connectionsPool.get(uri); if (idleConnectionForHost != null) { boolean poolEmpty = false; while (!poolEmpty && idleChannel == null) { if (idleConnectionForHost.size() > 0) { synchronized(idleConnectionForHost) { idleChannel = idleConnectionForHost.poll(); if (idleChannel != null) { channel2IdleChannel.remove(idleChannel.channel); } } } if (idleChannel == null) { poolEmpty = true; } else if (!idleChannel.channel.isConnected() || !idleChannel.channel.isOpen()) { idleChannel = null; log.trace("Channel not connected or not opened!"); } } } return idleChannel != null ? idleChannel.channel : null; } private boolean remove(IdleChannel pooledChannel) { if (pooledChannel == null || isClosed.get()) return false; boolean isRemoved = false; ConcurrentLinkedQueue pooledConnectionForHost = connectionsPool.get(pooledChannel.uri); if (pooledConnectionForHost != null) { isRemoved = pooledConnectionForHost.remove(pooledChannel); } isRemoved |= channel2IdleChannel.remove(pooledChannel.channel) != null; return isRemoved; } /** * {@inheritDoc} */ public boolean removeAll(Channel channel) { return !isClosed.get() && remove(channel2IdleChannel.get(channel)); } /** * {@inheritDoc} */ public boolean canCacheConnection() { if (!isClosed.get() && maxTotalConnections != -1 && channel2IdleChannel.size() >= maxTotalConnections) { return false; } else { return true; } } /** * {@inheritDoc} */ public void destroy() { if (isClosed.getAndSet(true)) return; // stop timer idleConnectionDetector.cancel(); idleConnectionDetector.purge(); for (Channel channel : channel2IdleChannel.keySet()) { close(channel); } connectionsPool.clear(); channel2IdleChannel.clear(); } private void close(Channel channel) { try { channel.getPipeline().getContext(NettyAsyncHttpProvider.class).setAttachment(new NettyAsyncHttpProvider.DiscardEvent()); channel.close(); } catch (Throwable t) { // noop } } public final String toString() { return String.format("NettyConnectionPool: {pool-size: %d}", channel2IdleChannel.size()); } } async-http-client-1.6.5/src/main/java/com/ning/http/client/providers/netty/NettyResponse.java000066400000000000000000000155741166553056000323630ustar00rootroot00000000000000/* * Copyright 2010 Ning, Inc. * * Ning licenses this file to you 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. */ package com.ning.http.client.providers.netty; import com.ning.http.client.Cookie; import com.ning.http.client.FluentCaseInsensitiveStringsMap; import com.ning.http.client.HttpResponseBodyPart; import com.ning.http.client.HttpResponseHeaders; import com.ning.http.client.HttpResponseStatus; import com.ning.http.client.Response; import com.ning.http.util.AsyncHttpProviderUtils; import org.jboss.netty.buffer.ChannelBuffer; import org.jboss.netty.buffer.ChannelBufferInputStream; import org.jboss.netty.buffer.ChannelBuffers; import java.io.IOException; import java.io.InputStream; import java.io.UnsupportedEncodingException; import java.net.MalformedURLException; import java.net.URI; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.Map; /** * Wrapper around the {@link com.ning.http.client.Response} API. */ public class NettyResponse implements Response { private final static String DEFAULT_CHARSET = "ISO-8859-1"; private final static String HEADERS_NOT_COMPUTED = "Response's headers hasn't been computed by your AsyncHandler."; private final URI uri; private final Collection bodyParts; private final HttpResponseHeaders headers; private final HttpResponseStatus status; private final List cookies = new ArrayList(); public NettyResponse(HttpResponseStatus status, HttpResponseHeaders headers, Collection bodyParts) { this.status = status; this.headers = headers; this.bodyParts = bodyParts; uri = status.getUrl(); } /* @Override */ public int getStatusCode() { return status.getStatusCode(); } /* @Override */ public String getStatusText() { return status.getStatusText(); } /* @Override */ public String getResponseBody() throws IOException { return getResponseBody(DEFAULT_CHARSET); } public String getResponseBody(String charset) throws IOException { String contentType = getContentType(); if (contentType != null && charset == null) { charset = AsyncHttpProviderUtils.parseCharset(contentType); } if (charset == null) { charset = DEFAULT_CHARSET; } return contentToString(charset); } String contentToString(String charset) throws UnsupportedEncodingException { StringBuilder b = new StringBuilder(); for (HttpResponseBodyPart bp : bodyParts) { b.append(new String(bp.getBodyPartBytes(), charset)); } return b.toString(); } /* @Override */ public InputStream getResponseBodyAsStream() throws IOException { ChannelBuffer buf = ChannelBuffers.dynamicBuffer(); for (HttpResponseBodyPart bp : bodyParts) { // Ugly. TODO // (1) We must remove the downcast, // (2) we need a CompositeByteArrayInputStream to avoid // copying the bytes. if (bp.getClass().isAssignableFrom(ResponseBodyPart.class)) { buf.writeBytes(bp.getBodyPartBytes()); } } return new ChannelBufferInputStream(buf); } /* @Override */ public String getResponseBodyExcerpt(int maxLength) throws IOException { return getResponseBodyExcerpt(maxLength, DEFAULT_CHARSET); } public String getResponseBodyExcerpt(int maxLength, String charset) throws IOException { String contentType = getContentType(); if (contentType != null && charset == null) { charset = AsyncHttpProviderUtils.parseCharset(contentType); } if (charset == null) { charset = DEFAULT_CHARSET; } String response = contentToString(charset); return response.length() <= maxLength ? response : response.substring(0, maxLength); } /* @Override */ public URI getUri() throws MalformedURLException { return uri; } /* @Override */ public String getContentType() { if (headers == null) { throw new IllegalStateException(HEADERS_NOT_COMPUTED); } return headers.getHeaders().getFirstValue("Content-Type"); } /* @Override */ public String getHeader(String name) { if (headers == null) { throw new IllegalStateException(); } return headers.getHeaders().getFirstValue(name); } /* @Override */ public List getHeaders(String name) { if (headers == null) { throw new IllegalStateException(HEADERS_NOT_COMPUTED); } return headers.getHeaders().get(name); } /* @Override */ public FluentCaseInsensitiveStringsMap getHeaders() { if (headers == null) { throw new IllegalStateException(HEADERS_NOT_COMPUTED); } return headers.getHeaders(); } /* @Override */ public boolean isRedirected() { return (status.getStatusCode() >= 300) && (status.getStatusCode() <= 399); } /* @Override */ public List getCookies() { if (headers == null) { throw new IllegalStateException(HEADERS_NOT_COMPUTED); } if (cookies.isEmpty()) { for (Map.Entry> header : headers.getHeaders().entrySet()) { if (header.getKey().equalsIgnoreCase("Set-Cookie")) { // TODO: ask for parsed header List v = header.getValue(); for (String value : v) { Cookie cookie = AsyncHttpProviderUtils.parseCookie(value); cookies.add(cookie); } } } } return Collections.unmodifiableList(cookies); } /** * {@inheritDoc} */ /* @Override */ public boolean hasResponseStatus() { return (status != null ? true : false); } /** * {@inheritDoc} */ /* @Override */ public boolean hasResponseHeaders() { return (headers != null ? true : false); } /** * {@inheritDoc} */ /* @Override */ public boolean hasResponseBody() { return (bodyParts != null && bodyParts.size() > 0 ? true : false); } } async-http-client-1.6.5/src/main/java/com/ning/http/client/providers/netty/NettyResponseFuture.java000077500000000000000000000340601166553056000335500ustar00rootroot00000000000000/* * Copyright 2010 Ning, Inc. * * Ning licenses this file to you 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. */ package com.ning.http.client.providers.netty; import com.ning.http.client.AsyncHandler; import com.ning.http.client.Request; import com.ning.http.client.listenable.AbstractListenableFuture; import org.jboss.netty.channel.Channel; import org.jboss.netty.handler.codec.http.HttpRequest; import org.jboss.netty.handler.codec.http.HttpResponse; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.net.MalformedURLException; import java.net.URI; import java.util.concurrent.Callable; import java.util.concurrent.CancellationException; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutionException; import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.atomic.AtomicReference; /** * A {@link Future} that can be used to track when an asynchronous HTTP request has been fully processed. * * @param */ public final class NettyResponseFuture extends AbstractListenableFuture { private final static Logger logger = LoggerFactory.getLogger(NettyResponseFuture.class); public final static String MAX_RETRY = "com.ning.http.client.providers.netty.maxRetry"; enum STATE { NEW, POOLED, RECONNECTED, CLOSED, } private final CountDownLatch latch = new CountDownLatch(1); private final AtomicBoolean isDone = new AtomicBoolean(false); private final AtomicBoolean isCancelled = new AtomicBoolean(false); private AsyncHandler asyncHandler; private final int responseTimeoutInMs; private Request request; private HttpRequest nettyRequest; private final AtomicReference content = new AtomicReference(); private URI uri; private boolean keepAlive = true; private HttpResponse httpResponse; private final AtomicReference exEx = new AtomicReference(); private final AtomicInteger redirectCount = new AtomicInteger(); private volatile Future reaperFuture; private final AtomicBoolean inAuth = new AtomicBoolean(false); private final AtomicBoolean statusReceived = new AtomicBoolean(false); private final AtomicLong touch = new AtomicLong(System.currentTimeMillis()); private final NettyAsyncHttpProvider asyncHttpProvider; private final AtomicReference state = new AtomicReference(STATE.NEW); private final AtomicBoolean contentProcessed = new AtomicBoolean(false); private Channel channel; private boolean reuseChannel = false; private final AtomicInteger currentRetry = new AtomicInteger(0); private final int maxRetry; private boolean writeHeaders; private boolean writeBody; private final AtomicBoolean throwableCalled = new AtomicBoolean(false); public NettyResponseFuture(URI uri, Request request, AsyncHandler asyncHandler, HttpRequest nettyRequest, int responseTimeoutInMs, NettyAsyncHttpProvider asyncHttpProvider) { this.asyncHandler = asyncHandler; this.responseTimeoutInMs = responseTimeoutInMs; this.request = request; this.nettyRequest = nettyRequest; this.uri = uri; this.asyncHttpProvider = asyncHttpProvider; if (System.getProperty(MAX_RETRY) != null) { maxRetry = Integer.valueOf(System.getProperty(MAX_RETRY)); } else { maxRetry = asyncHttpProvider.getConfig().getMaxRequestRetry(); } writeHeaders = true; writeBody = true; } protected URI getURI() throws MalformedURLException { return uri; } protected void setURI(URI uri) { this.uri = uri; } /** * {@inheritDoc} */ /* @Override */ public boolean isDone() { return isDone.get(); } /** * {@inheritDoc} */ /* @Override */ public boolean isCancelled() { return isCancelled.get(); } void setAsyncHandler(AsyncHandler asyncHandler) { this.asyncHandler = asyncHandler; } /** * {@inheritDoc} */ /* @Override */ public boolean cancel(boolean force) { cancelReaper(); if (isCancelled.get()) return false; try { channel.getPipeline().getContext(NettyAsyncHttpProvider.class).setAttachment(new NettyAsyncHttpProvider.DiscardEvent()); channel.close(); } catch (Throwable t) { // Ignore } if (!throwableCalled.getAndSet(true)) { try { asyncHandler.onThrowable(new CancellationException()); } catch (Throwable t) { logger.warn("cancel", t); } } latch.countDown(); isCancelled.set(true); super.done(); return true; } /** * Is the Future still valid * * @return true if response has expired and should be terminated. */ public boolean hasExpired() { return responseTimeoutInMs != -1 && ((System.currentTimeMillis() - touch.get()) >= responseTimeoutInMs); } /** * {@inheritDoc} */ /* @Override */ public V get() throws InterruptedException, ExecutionException { try { return get(responseTimeoutInMs, TimeUnit.MILLISECONDS); } catch (TimeoutException e) { cancelReaper(); throw new ExecutionException(e); } } void cancelReaper() { if (reaperFuture != null) { reaperFuture.cancel(true); } } /** * {@inheritDoc} */ /* @Override */ public V get(long l, TimeUnit tu) throws InterruptedException, TimeoutException, ExecutionException { if (!isDone() && !isCancelled()) { boolean expired = false; if (l == -1) { latch.await(); } else { expired = !latch.await(l, tu); if (!contentProcessed.get() && expired && ((System.currentTimeMillis() - touch.get()) <= l)) { return get(l, tu); } } if (expired) { isCancelled.set(true); TimeoutException te = new TimeoutException(String.format("No response received after %s", l)); if (!throwableCalled.getAndSet(true)) { try { asyncHandler.onThrowable(te); } catch (Throwable t) { logger.debug("asyncHandler.onThrowable", t); } finally { cancelReaper(); throw new ExecutionException(te); } } } isDone.set(true); ExecutionException e = exEx.getAndSet(null); if (e != null) { throw e; } } return getContent(); } V getContent() throws ExecutionException { ExecutionException e = exEx.getAndSet(null); if (e != null) { throw e; } V update = content.get(); // No more retry currentRetry.set(maxRetry); if (exEx.get() == null && !contentProcessed.getAndSet(true)) { try { update = asyncHandler.onCompleted(); } catch (Throwable ex) { if (!throwableCalled.getAndSet(true)) { try { asyncHandler.onThrowable(ex); } catch (Throwable t) { logger.debug("asyncHandler.onThrowable", t); } finally { cancelReaper(); throw new RuntimeException(ex); } } } content.compareAndSet(null, update); } return update; } public final void done(Callable callable) { try { cancelReaper(); if (exEx.get() != null) { return; } getContent(); isDone.set(true); if (callable != null) { try { callable.call(); } catch (Exception ex) { throw new RuntimeException(ex); } } } catch (ExecutionException t) { return; } catch (RuntimeException t) { exEx.compareAndSet(null, new ExecutionException(t)); } finally { latch.countDown(); } super.done(); } public final void abort(final Throwable t) { cancelReaper(); if (isDone.get() || isCancelled.get()) return; exEx.compareAndSet(null, new ExecutionException(t)); if (!throwableCalled.getAndSet(true)) { try { asyncHandler.onThrowable(t); } catch (Throwable te) { logger.debug("asyncHandler.onThrowable", te); } finally { isCancelled.set(true); } } latch.countDown(); super.done(); } public void content(V v) { content.set(v); } protected final Request getRequest() { return request; } public final HttpRequest getNettyRequest() { return nettyRequest; } protected final void setNettyRequest(HttpRequest nettyRequest) { this.nettyRequest = nettyRequest; } protected final AsyncHandler getAsyncHandler() { return asyncHandler; } protected final boolean getKeepAlive() { return keepAlive; } protected final void setKeepAlive(final boolean keepAlive) { this.keepAlive = keepAlive; } protected final HttpResponse getHttpResponse() { return httpResponse; } protected final void setHttpResponse(final HttpResponse httpResponse) { this.httpResponse = httpResponse; } protected int incrementAndGetCurrentRedirectCount() { return redirectCount.incrementAndGet(); } protected void setReaperFuture(Future reaperFuture) { cancelReaper(); this.reaperFuture = reaperFuture; } protected boolean isInAuth() { return inAuth.get(); } protected boolean getAndSetAuth(boolean inDigestAuth) { return inAuth.getAndSet(inDigestAuth); } protected STATE getState() { return state.get(); } protected void setState(STATE state) { this.state.set(state); } public boolean getAndSetStatusReceived(boolean sr) { return statusReceived.getAndSet(sr); } /** * {@inheritDoc} */ /* @Override */ public void touch() { touch.set(System.currentTimeMillis()); } /** * {@inheritDoc} */ /* @Override */ public boolean getAndSetWriteHeaders(boolean writeHeaders) { boolean b = this.writeHeaders; this.writeHeaders = writeHeaders; return b; } /** * {@inheritDoc} */ /* @Override */ public boolean getAndSetWriteBody(boolean writeBody) { boolean b = this.writeBody; this.writeBody = writeBody; return b; } protected NettyAsyncHttpProvider provider() { return asyncHttpProvider; } protected void attachChannel(Channel channel) { this.channel = channel; } protected void attachChannel(Channel channel, boolean reuseChannel) { this.channel = channel; this.reuseChannel = reuseChannel; } protected Channel channel(){ return channel; } protected boolean reuseChannel(){ return reuseChannel; } protected boolean canRetry() { if (currentRetry.incrementAndGet() > maxRetry) { return false; } return true; } public void setRequest(Request request) { this.request = request; } /** * Return true if the {@link Future} cannot be recovered. There is some scenario where a connection can be * closed by an unexpected IOException, and in some situation we can recover from that exception. * * @return true if that {@link Future} cannot be recovered. */ public boolean cannotBeReplay() { return isDone() || !canRetry() || isCancelled() || (channel() != null && channel().isOpen() && uri.getScheme().compareToIgnoreCase("https") != 0) || isInAuth(); } @Override public String toString() { return "NettyResponseFuture{" + "currentRetry=" + currentRetry + ",\n\tisDone=" + isDone + ",\n\tisCancelled=" + isCancelled + ",\n\tasyncHandler=" + asyncHandler + ",\n\tresponseTimeoutInMs=" + responseTimeoutInMs + ",\n\tnettyRequest=" + nettyRequest + ",\n\tcontent=" + content + ",\n\turi=" + uri + ",\n\tkeepAlive=" + keepAlive + ",\n\thttpResponse=" + httpResponse + ",\n\texEx=" + exEx + ",\n\tredirectCount=" + redirectCount + ",\n\treaperFuture=" + reaperFuture + ",\n\tinAuth=" + inAuth + ",\n\tstatusReceived=" + statusReceived + ",\n\ttouch=" + touch + '}'; } } async-http-client-1.6.5/src/main/java/com/ning/http/client/providers/netty/ResponseBodyPart.java000066400000000000000000000055001166553056000327700ustar00rootroot00000000000000/* * Copyright 2010 Ning, Inc. * * Ning licenses this file to you 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. */ package com.ning.http.client.providers.netty; import com.ning.http.client.AsyncHttpProvider; import com.ning.http.client.HttpResponseBodyPart; import org.jboss.netty.buffer.ChannelBuffer; import org.jboss.netty.handler.codec.http.HttpChunk; import org.jboss.netty.handler.codec.http.HttpResponse; import java.io.IOException; import java.io.OutputStream; import java.net.URI; import java.nio.ByteBuffer; import java.util.concurrent.atomic.AtomicReference; /** * A callback class used when an HTTP response body is received. */ public class ResponseBodyPart extends HttpResponseBodyPart { private final HttpChunk chunk; private final HttpResponse response; private final AtomicReference bytes = new AtomicReference(null); public ResponseBodyPart(URI uri, HttpResponse response, AsyncHttpProvider provider) { super(uri, provider); this.chunk = null; this.response = response; } public ResponseBodyPart(URI uri, HttpResponse response, AsyncHttpProvider provider, HttpChunk chunk) { super(uri, provider); this.chunk = chunk; this.response = response; } /** * Return the response body's part bytes received. * * @return the response body's part bytes received. */ public byte[] getBodyPartBytes() { if (bytes.get() != null) { return bytes.get(); } ChannelBuffer b = chunk != null ? chunk.getContent() : response.getContent(); int read = b.readableBytes(); int index = b.readerIndex(); byte[] rb = new byte[read]; b.readBytes(rb); bytes.set(rb); b.readerIndex(index); return bytes.get(); } public int writeTo(OutputStream outputStream) throws IOException { ChannelBuffer b = chunk != null ? chunk.getContent() : response.getContent(); int read = b.readableBytes(); int index = b.readerIndex(); if (read > 0) { b.readBytes(outputStream, read); } b.readerIndex(index); return read; } @Override public ByteBuffer getBodyByteBuffer() { return ByteBuffer.wrap(getBodyPartBytes()); } protected HttpChunk chunk() { return chunk; } } async-http-client-1.6.5/src/main/java/com/ning/http/client/providers/netty/ResponseHeaders.java000066400000000000000000000051111166553056000326150ustar00rootroot00000000000000/* * Copyright 2010 Ning, Inc. * * Ning licenses this file to you 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. */ package com.ning.http.client.providers.netty; import com.ning.http.client.AsyncHttpProvider; import com.ning.http.client.FluentCaseInsensitiveStringsMap; import com.ning.http.client.HttpResponseHeaders; import org.jboss.netty.handler.codec.http.HttpChunkTrailer; import org.jboss.netty.handler.codec.http.HttpResponse; import java.net.URI; /** * A class that represent the HTTP headers. */ public class ResponseHeaders extends HttpResponseHeaders { private final HttpChunkTrailer trailingHeaders; private final HttpResponse response; private final FluentCaseInsensitiveStringsMap headers; public ResponseHeaders(URI uri, HttpResponse response, AsyncHttpProvider provider) { super(uri, provider, false); this.trailingHeaders = null; this.response = response; headers = computerHeaders(); } public ResponseHeaders(URI uri, HttpResponse response, AsyncHttpProvider provider, HttpChunkTrailer traillingHeaders) { super(uri, provider, true); this.trailingHeaders = traillingHeaders; this.response = response; headers = computerHeaders(); } private FluentCaseInsensitiveStringsMap computerHeaders() { FluentCaseInsensitiveStringsMap h = new FluentCaseInsensitiveStringsMap(); for (String s : response.getHeaderNames()) { for (String header : response.getHeaders(s)) { h.add(s, header); } } if (trailingHeaders != null && trailingHeaders.getHeaderNames().size() > 0) { for (final String s : trailingHeaders.getHeaderNames()) { for (String header : response.getHeaders(s)) { h.add(s, header); } } } return h; } /** * Return the HTTP header * * @return an {@link com.ning.http.client.FluentCaseInsensitiveStringsMap} */ @Override public FluentCaseInsensitiveStringsMap getHeaders() { return headers; } } async-http-client-1.6.5/src/main/java/com/ning/http/client/providers/netty/ResponseStatus.java000066400000000000000000000040211166553056000325240ustar00rootroot00000000000000/* * Copyright 2010 Ning, Inc. * * Ning licenses this file to you 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. * */ package com.ning.http.client.providers.netty; import com.ning.http.client.AsyncHttpProvider; import com.ning.http.client.HttpResponseStatus; import org.jboss.netty.handler.codec.http.HttpResponse; import java.net.URI; /** * A class that represent the HTTP response' status line (code + text) */ public class ResponseStatus extends HttpResponseStatus { private final HttpResponse response; public ResponseStatus(URI uri, HttpResponse response, AsyncHttpProvider provider) { super(uri, provider); this.response = response; } /** * Return the response status code * * @return the response status code */ public int getStatusCode() { return response.getStatus().getCode(); } /** * Return the response status text * * @return the response status text */ public String getStatusText() { return response.getStatus().getReasonPhrase(); } @Override public String getProtocolName() { return response.getProtocolVersion().getProtocolName(); } @Override public int getProtocolMajorVersion() { return response.getProtocolVersion().getMajorVersion(); } @Override public int getProtocolMinorVersion() { return response.getProtocolVersion().getMinorVersion(); } @Override public String getProtocolText() { return response.getProtocolVersion().getText(); } } async-http-client-1.6.5/src/main/java/com/ning/http/client/providers/netty/spnego/000077500000000000000000000000001166553056000301555ustar00rootroot00000000000000async-http-client-1.6.5/src/main/java/com/ning/http/client/providers/netty/spnego/SpnegoEngine.java000066400000000000000000000163631166553056000334120ustar00rootroot00000000000000/* * Copyright (c) 2010-2011 Sonatype, Inc. All rights reserved. * * This program is licensed to you under the Apache License Version 2.0, * and you may not use this file except in compliance with the Apache License Version 2.0. * You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0. * * Unless required by applicable law or agreed to in writing, * software distributed under the Apache License Version 2.0 is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. */ /* * ==================================================================== * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Software Foundation. For more * information on the Apache Software Foundation, please see * . */ package com.ning.http.client.providers.netty.spnego; import com.ning.http.util.Base64; import org.ietf.jgss.GSSContext; import org.ietf.jgss.GSSException; import org.ietf.jgss.GSSManager; import org.ietf.jgss.GSSName; import org.ietf.jgss.Oid; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.IOException; /** * SPNEGO (Simple and Protected GSSAPI Negotiation Mechanism) authentication * scheme. * * @since 4.1 */ public class SpnegoEngine { private static final String SPNEGO_OID = "1.3.6.1.5.5.2"; private static final String KERBEROS_OID = "1.2.840.113554.1.2.2"; private final Logger log = LoggerFactory.getLogger(getClass()); private final SpnegoTokenGenerator spnegoGenerator; private GSSContext gssContext = null; /** * base64 decoded challenge * */ private byte[] token; private Oid negotiationOid = null; public SpnegoEngine(final SpnegoTokenGenerator spnegoGenerator) { this.spnegoGenerator = spnegoGenerator; } public SpnegoEngine() { this(null); } public String generateToken(String server) throws Throwable { try { log.debug("init {}", server); /* Using the SPNEGO OID is the correct method. * Kerberos v5 works for IIS but not JBoss. Unwrapping * the initial token when using SPNEGO OID looks like what is * described here... * * http://msdn.microsoft.com/en-us/library/ms995330.aspx * * Another helpful URL... * * http://publib.boulder.ibm.com/infocenter/wasinfo/v7r0/index.jsp?topic=/com.ibm.websphere.express.doc/info/exp/ae/tsec_SPNEGO_token.html * * Unfortunately SPNEGO is JRE >=1.6. */ /** Try SPNEGO by default, fall back to Kerberos later if error */ negotiationOid = new Oid(SPNEGO_OID); boolean tryKerberos = false; try { GSSManager manager = GSSManager.getInstance(); GSSName serverName = manager.createName("HTTP@" + server, GSSName.NT_HOSTBASED_SERVICE); gssContext = manager.createContext( serverName.canonicalize(negotiationOid), negotiationOid, null, GSSContext.DEFAULT_LIFETIME); gssContext.requestMutualAuth(true); gssContext.requestCredDeleg(true); } catch (GSSException ex) { log.error("generateToken", ex); // BAD MECH means we are likely to be using 1.5, fall back to Kerberos MECH. // Rethrow any other exception. if (ex.getMajor() == GSSException.BAD_MECH) { log.debug("GSSException BAD_MECH, retry with Kerberos MECH"); tryKerberos = true; } else { throw ex; } } if (tryKerberos) { /* Kerberos v5 GSS-API mechanism defined in RFC 1964.*/ log.debug("Using Kerberos MECH {}", KERBEROS_OID); negotiationOid = new Oid(KERBEROS_OID); GSSManager manager = GSSManager.getInstance(); GSSName serverName = manager.createName("HTTP@" + server, GSSName.NT_HOSTBASED_SERVICE); gssContext = manager.createContext( serverName.canonicalize(negotiationOid), negotiationOid, null, GSSContext.DEFAULT_LIFETIME); gssContext.requestMutualAuth(true); gssContext.requestCredDeleg(true); } // TODO suspicious: this will always be null because no value has been assigned before. Assign directly? if (token == null) { token = new byte[0]; } token = gssContext.initSecContext(token, 0, token.length); if (token == null) { throw new Exception("GSS security context initialization failed"); } /* * IIS accepts Kerberos and SPNEGO tokens. Some other servers Jboss, Glassfish? * seem to only accept SPNEGO. Below wraps Kerberos into SPNEGO token. */ if (spnegoGenerator != null && negotiationOid.toString().equals(KERBEROS_OID)) { token = spnegoGenerator.generateSpnegoDERObject(token); } gssContext.dispose(); String tokenstr = new String(Base64.encode(token)); log.debug("Sending response '{}' back to the server", tokenstr); return tokenstr; } catch (GSSException gsse) { log.error("generateToken", gsse); if (gsse.getMajor() == GSSException.DEFECTIVE_CREDENTIAL || gsse.getMajor() == GSSException.CREDENTIALS_EXPIRED) throw new Exception(gsse.getMessage(), gsse); if (gsse.getMajor() == GSSException.NO_CRED) throw new Exception(gsse.getMessage(), gsse); if (gsse.getMajor() == GSSException.DEFECTIVE_TOKEN || gsse.getMajor() == GSSException.DUPLICATE_TOKEN || gsse.getMajor() == GSSException.OLD_TOKEN) throw new Exception(gsse.getMessage(), gsse); // other error throw new Exception(gsse.getMessage()); } catch (IOException ex) { throw new Exception(ex.getMessage()); } } } SpnegoTokenGenerator.java000066400000000000000000000044171166553056000350520ustar00rootroot00000000000000async-http-client-1.6.5/src/main/java/com/ning/http/client/providers/netty/spnego/* * Copyright (c) 2010-2011 Sonatype, Inc. All rights reserved. * * This program is licensed to you under the Apache License Version 2.0, * and you may not use this file except in compliance with the Apache License Version 2.0. * You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0. * * Unless required by applicable law or agreed to in writing, * software distributed under the Apache License Version 2.0 is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. */ /* * ==================================================================== * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Software Foundation. For more * information on the Apache Software Foundation, please see * . * */ package com.ning.http.client.providers.netty.spnego; import java.io.IOException; /** * Abstract SPNEGO token generator. Implementations should take an Kerberos ticket and transform * into a SPNEGO token. *

* Implementations of this interface are expected to be thread-safe. * * @since 4.1 */ public interface SpnegoTokenGenerator { byte [] generateSpnegoDERObject(byte [] kerberosTicket) throws IOException; } async-http-client-1.6.5/src/main/java/com/ning/http/client/resumable/000077500000000000000000000000001166553056000254615ustar00rootroot00000000000000PropertiesBasedResumableProcessor.java000066400000000000000000000074531166553056000351110ustar00rootroot00000000000000async-http-client-1.6.5/src/main/java/com/ning/http/client/resumable/* * Copyright (c) 2010-2011 Sonatype, Inc. All rights reserved. * * This program is licensed to you under the Apache License Version 2.0, * and you may not use this file except in compliance with the Apache License Version 2.0. * You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0. * * Unless required by applicable law or agreed to in writing, * software distributed under the Apache License Version 2.0 is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. */ package com.ning.http.client.resumable; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.util.Map; import java.util.Scanner; import java.util.concurrent.ConcurrentHashMap; /** * A {@link com.ning.http.client.resumable.ResumableAsyncHandler.ResumableProcessor} which use a properties file * to store the download index information. */ public class PropertiesBasedResumableProcessor implements ResumableAsyncHandler.ResumableProcessor { private final static Logger log = LoggerFactory.getLogger(PropertiesBasedResumableProcessor.class); private final static File TMP = new File(System.getProperty("java.io.tmpdir"), "ahc"); private final static String storeName = "ResumableAsyncHandler.properties"; private final ConcurrentHashMap properties = new ConcurrentHashMap(); /** * {@inheritDoc} */ /* @Override */ public void put(String url, long transferredBytes) { properties.put(url, transferredBytes); } /** * {@inheritDoc} */ /* @Override */ public void remove(String uri) { if (uri != null) { properties.remove(uri); } } /** * {@inheritDoc} */ /* @Override */ public void save(Map map) { log.debug("Saving current download state {}", properties.toString()); FileOutputStream os = null; try { TMP.mkdirs(); File f = new File(TMP, storeName); f.createNewFile(); if (!f.canWrite()) { throw new IllegalStateException(); } os = new FileOutputStream(f); for (Map.Entry e : properties.entrySet()) { os.write((append(e)).getBytes("UTF-8")); } os.flush(); } catch (Throwable e) { log.warn(e.getMessage(), e); } finally { if (os != null) { try { os.close(); } catch (IOException e) { } } } } private static String append(Map.Entry e) { return new StringBuffer(e.getKey()).append("=").append(e.getValue()).append( "\n" ).toString(); } /** * {@inheritDoc} */ /* @Override */ public Map load() { try { Scanner scan = new Scanner(new File(TMP, storeName), "UTF-8"); scan.useDelimiter("[=\n]"); String key; String value; while (scan.hasNext()) { key = scan.next().trim(); value = scan.next().trim(); properties.put(key, Long.valueOf(value)); } log.debug("Loading previous download state {}", properties.toString()); } catch (FileNotFoundException ex) { log.debug("Missing {}", storeName); } catch (Throwable ex) { // Survive any exceptions log.warn(ex.getMessage(), ex); } return properties; } } async-http-client-1.6.5/src/main/java/com/ning/http/client/resumable/ResumableAsyncHandler.java000066400000000000000000000252411166553056000325430ustar00rootroot00000000000000/* * Copyright (c) 2010-2011 Sonatype, Inc. All rights reserved. * * This program is licensed to you under the Apache License Version 2.0, * and you may not use this file except in compliance with the Apache License Version 2.0. * You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0. * * Unless required by applicable law or agreed to in writing, * software distributed under the Apache License Version 2.0 is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. */ package com.ning.http.client.resumable; import com.ning.http.client.AsyncHandler; import com.ning.http.client.HttpResponseBodyPart; import com.ning.http.client.HttpResponseHeaders; import com.ning.http.client.HttpResponseStatus; import com.ning.http.client.Request; import com.ning.http.client.RequestBuilder; import com.ning.http.client.Response.ResponseBuilder; import com.ning.http.client.listener.TransferCompletionHandler; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.IOException; import java.nio.ByteBuffer; import java.util.HashMap; import java.util.Map; import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.atomic.AtomicLong; /** * An {@link AsyncHandler} which support resumable download, e.g when used with an {@link ResumableIOExceptionFilter}, * this handler can resume the download operation at the point it was before the interruption occured. This prevent having to * download the entire file again. It's the responsibility of the {@link com.ning.http.client.listener.TransferListener} * to track how many bytes has been transferred and to properly adjust the file's write position. *

* In case of a JVM crash/shutdown, you can create an instance of this class and pass the last valid bytes position. */ public class ResumableAsyncHandler implements AsyncHandler { private final static Logger logger = LoggerFactory.getLogger(TransferCompletionHandler.class); private final AtomicLong byteTransferred; private Integer contentLength; private String url; private final ResumableProcessor resumableProcessor; private final AsyncHandler decoratedAsyncHandler; private static Map resumableIndex; private final static ResumableIndexThread resumeIndexThread = new ResumableIndexThread(); private ResponseBuilder responseBuilder = new ResponseBuilder(); private final boolean accumulateBody; private ResumableListener resumableListener = new NULLResumableListener(); private ResumableAsyncHandler(long byteTransferred, ResumableProcessor resumableProcessor, AsyncHandler decoratedAsyncHandler, boolean accumulateBody) { this.byteTransferred = new AtomicLong(byteTransferred); if (resumableProcessor == null) { resumableProcessor = new NULLResumableHandler(); } this.resumableProcessor = resumableProcessor; resumableIndex = resumableProcessor.load(); resumeIndexThread.addResumableProcessor(resumableProcessor); this.decoratedAsyncHandler = decoratedAsyncHandler; this.accumulateBody = accumulateBody; } public ResumableAsyncHandler(long byteTransferred) { this(byteTransferred, null, null, false); } public ResumableAsyncHandler(boolean accumulateBody) { this(0, null, null, accumulateBody); } public ResumableAsyncHandler() { this(0, null, null, false); } public ResumableAsyncHandler(AsyncHandler decoratedAsyncHandler) { this(0, new PropertiesBasedResumableProcessor(), decoratedAsyncHandler, false); } public ResumableAsyncHandler(long byteTransferred, AsyncHandler decoratedAsyncHandler) { this(byteTransferred, new PropertiesBasedResumableProcessor(), decoratedAsyncHandler, false); } public ResumableAsyncHandler(ResumableProcessor resumableProcessor) { this(0, resumableProcessor, null, false); } public ResumableAsyncHandler(ResumableProcessor resumableProcessor, boolean accumulateBody) { this(0, resumableProcessor, null, accumulateBody); } /** * {@inheritDoc} */ /* @Override */ public AsyncHandler.STATE onStatusReceived(final HttpResponseStatus status) throws Exception { responseBuilder.accumulate(status); if (status.getStatusCode() == 200 || status.getStatusCode() == 206) { url = status.getUrl().toURL().toString(); } else { return AsyncHandler.STATE.ABORT; } if (decoratedAsyncHandler != null) { return decoratedAsyncHandler.onStatusReceived(status); } return AsyncHandler.STATE.CONTINUE; } /** * {@inheritDoc} */ /* @Override */ public void onThrowable(Throwable t) { if (decoratedAsyncHandler != null) { decoratedAsyncHandler.onThrowable(t); } else { logger.debug("", t); } } /** * {@inheritDoc} */ /* @Override */ public AsyncHandler.STATE onBodyPartReceived(HttpResponseBodyPart bodyPart) throws Exception { if (accumulateBody) { responseBuilder.accumulate(bodyPart); } STATE state = STATE.CONTINUE; try { resumableListener.onBytesReceived(bodyPart.getBodyByteBuffer()); } catch (IOException ex) { return AsyncHandler.STATE.ABORT; } if (decoratedAsyncHandler != null) { state = decoratedAsyncHandler.onBodyPartReceived(bodyPart); } byteTransferred.addAndGet(bodyPart.getBodyPartBytes().length); resumableProcessor.put(url, byteTransferred.get()); return state; } /** * {@inheritDoc} */ /* @Override */ public T onCompleted() throws Exception { resumableProcessor.remove(url); resumableListener.onAllBytesReceived(); if (decoratedAsyncHandler != null) { decoratedAsyncHandler.onCompleted(); } // Not sure return (T) responseBuilder.build(); } /** * {@inheritDoc} */ /* @Override */ public AsyncHandler.STATE onHeadersReceived(HttpResponseHeaders headers) throws Exception { responseBuilder.accumulate(headers); if (headers.getHeaders().getFirstValue("Content-Length") != null) { contentLength = Integer.valueOf(headers.getHeaders().getFirstValue("Content-Length")); if (contentLength == null || contentLength == -1) { return AsyncHandler.STATE.ABORT; } } if (decoratedAsyncHandler != null) { return decoratedAsyncHandler.onHeadersReceived(headers); } return AsyncHandler.STATE.CONTINUE; } /** * Invoke this API if you want to set the Range header on your {@link Request} based on the last valid bytes * position. * * @param request {@link Request} * @return a {@link Request} with the Range header properly set. */ public Request adjustRequestRange(Request request) { if (resumableIndex.get(request.getUrl()) != null) { byteTransferred.set(resumableIndex.get(request.getUrl())); } // The Resumbale if (resumableListener != null && resumableListener.length() > 0 && byteTransferred.get() != resumableListener.length()) { byteTransferred.set(resumableListener.length()); } RequestBuilder builder = new RequestBuilder(request); if (request.getHeaders().get("Range") == null && byteTransferred.get() != 0) { builder.setHeader("Range", "bytes=" + byteTransferred.get() + "-"); } return builder.build(); } /** * Set a {@link ResumableListener} * * @param resumableListener a {@link ResumableListener} * @return this */ public ResumableAsyncHandler setResumableListener(ResumableListener resumableListener) { this.resumableListener = resumableListener; return this; } private static class ResumableIndexThread extends Thread { public final ConcurrentLinkedQueue resumableProcessors = new ConcurrentLinkedQueue(); public ResumableIndexThread() { Runtime.getRuntime().addShutdownHook(this); } public void addResumableProcessor(ResumableProcessor p) { resumableProcessors.offer(p); } public void run() { for (ResumableProcessor p : resumableProcessors) { p.save(resumableIndex); } } } /** * An interface to implement in order to manage the way the incomplete file management are handled. */ public static interface ResumableProcessor { /** * Associate a key with the number of bytes sucessfully transferred. * * @param key a key. The recommended way is to use an url. * @param transferredBytes The number of bytes sucessfully transferred. */ public void put(String key, long transferredBytes); /** * Remove the key associate value. * * @param key key from which the value will be discarted */ public void remove(String key); /** * Save the current {@link Map} instance which contains information about the current transfer state. * This method *only* invoked when the JVM is shutting down. * * @param map */ public void save(Map map); /** * Load the {@link Map} in memory, contains information about the transferred bytes. * * @return {@link Map} */ public Map load(); } private static class NULLResumableHandler implements ResumableProcessor { public void put(String url, long transferredBytes) { } public void remove(String uri) { } public void save(Map map) { } public Map load() { return new HashMap(); } } private static class NULLResumableListener implements ResumableListener { private long length = 0L; public void onBytesReceived( ByteBuffer byteBuffer ) throws IOException { length += byteBuffer.remaining(); } public void onAllBytesReceived() { } public long length() { return length; } } } async-http-client-1.6.5/src/main/java/com/ning/http/client/resumable/ResumableIOExceptionFilter.java000066400000000000000000000031331166553056000335200ustar00rootroot00000000000000/* * Copyright (c) 2010-2011 Sonatype, Inc. All rights reserved. * * This program is licensed to you under the Apache License Version 2.0, * and you may not use this file except in compliance with the Apache License Version 2.0. * You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0. * * Unless required by applicable law or agreed to in writing, * software distributed under the Apache License Version 2.0 is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. */ package com.ning.http.client.resumable; import com.ning.http.client.Request; import com.ning.http.client.filter.FilterContext; import com.ning.http.client.filter.FilterException; import com.ning.http.client.filter.IOExceptionFilter; /** * Simple {@link IOExceptionFilter} that replay the current {@link com.ning.http.client.Request} using * a {@link ResumableAsyncHandler} */ public class ResumableIOExceptionFilter implements IOExceptionFilter { public FilterContext filter(FilterContext ctx) throws FilterException { if (ctx.getIOException() != null && ResumableAsyncHandler.class.isAssignableFrom(ctx.getAsyncHandler().getClass())) { Request request = ResumableAsyncHandler.class.cast(ctx.getAsyncHandler()).adjustRequestRange(ctx.getRequest()); return new FilterContext.FilterContextBuilder(ctx).request(request).replayRequest(true).build(); } return ctx; } } async-http-client-1.6.5/src/main/java/com/ning/http/client/resumable/ResumableListener.java000066400000000000000000000026501166553056000317540ustar00rootroot00000000000000/* * Copyright (c) 2010-2011 Sonatype, Inc. All rights reserved. * * This program is licensed to you under the Apache License Version 2.0, * and you may not use this file except in compliance with the Apache License Version 2.0. * You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0. * * Unless required by applicable law or agreed to in writing, * software distributed under the Apache License Version 2.0 is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. */ package com.ning.http.client.resumable; import java.io.IOException; import java.nio.ByteBuffer; /** * A listener class that can be used to digest the bytes from an {@link ResumableAsyncHandler} */ public interface ResumableListener { /** * Invoked when some bytes are available to digest. * * @param byteBuffer the current bytes * @throws IOException */ public void onBytesReceived(ByteBuffer byteBuffer) throws IOException; /** * Invoked when all the bytes has been sucessfully transferred. */ public void onAllBytesReceived(); /** * Return the length of previously downloaded bytes. * * @return the length of previously downloaded bytes */ public long length(); }async-http-client-1.6.5/src/main/java/com/ning/http/client/simple/000077500000000000000000000000001166553056000247735ustar00rootroot00000000000000async-http-client-1.6.5/src/main/java/com/ning/http/client/simple/HeaderMap.java000066400000000000000000000062151166553056000274700ustar00rootroot00000000000000package com.ning.http.client.simple; /* * Copyright (c) 2010 Sonatype, Inc. All rights reserved. * * This program is licensed to you under the Apache License Version 2.0, * and you may not use this file except in compliance with the Apache License Version 2.0. * You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0. * * Unless required by applicable law or agreed to in writing, * software distributed under the Apache License Version 2.0 is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. */ import java.util.Collection; import java.util.List; import java.util.Map; import java.util.Set; import com.ning.http.client.FluentCaseInsensitiveStringsMap; /** * A map containing headers with the sole purpose of being given to * {@link SimpleAHCTransferListener#onHeaders(String, HeaderMap)}. * * @author Benjamin Hanzelmann */ public class HeaderMap implements Map> { private FluentCaseInsensitiveStringsMap headers; public HeaderMap(FluentCaseInsensitiveStringsMap headers) { this.headers = headers; } public Set keySet() { return headers.keySet(); } public Set>> entrySet() { return headers.entrySet(); } public int size() { return headers.size(); } public boolean isEmpty() { return headers.isEmpty(); } public boolean containsKey(Object key) { return headers.containsKey(key); } public boolean containsValue(Object value) { return headers.containsValue(value); } /** * @see FluentCaseInsensitiveStringsMap#getFirstValue(String) */ public String getFirstValue(String key) { return headers.getFirstValue(key); } /** * @see FluentCaseInsensitiveStringsMap#getJoinedValue(String, String) */ public String getJoinedValue(String key, String delimiter) { return headers.getJoinedValue(key, delimiter); } public List get(Object key) { return headers.get(key); } /** * Only read access is supported. */ public List put(String key, List value) { throw new UnsupportedOperationException("Only read access is supported."); } /** * Only read access is supported. */ public List remove(Object key) { throw new UnsupportedOperationException("Only read access is supported."); } /** * Only read access is supported. */ public void putAll(Map> t) { throw new UnsupportedOperationException("Only read access is supported."); } /** * Only read access is supported. */ public void clear() { throw new UnsupportedOperationException("Only read access is supported."); } /** * Only read access is supported. */ public Collection> values() { return headers.values(); } } async-http-client-1.6.5/src/main/java/com/ning/http/client/simple/SimpleAHCTransferListener.java000066400000000000000000000065331166553056000326250ustar00rootroot00000000000000package com.ning.http.client.simple; /* * Copyright (c) 2010-2011 Sonatype, Inc. All rights reserved. * * This program is licensed to you under the Apache License Version 2.0, * and you may not use this file except in compliance with the Apache License Version 2.0. * You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0. * * Unless required by applicable law or agreed to in writing, * software distributed under the Apache License Version 2.0 is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. */ import com.ning.http.client.SimpleAsyncHttpClient; /** * A simple transfer listener for use with the {@link SimpleAsyncHttpClient}. *

* Note: This listener does not cover requests failing before a connection is * established. For error handling, see * {@link SimpleAsyncHttpClient.Builder#setDefaultThrowableHandler(com.ning.http.client.ThrowableHandler)} * * @author Benjamin Hanzelmann */ public interface SimpleAHCTransferListener { /** * This method is called after the connection status is received. * * @param url * the url for the connection. * @param statusCode * the received status code. * @param statusText * the received status text. */ void onStatus(String url, int statusCode, String statusText); /** * This method is called after the response headers are received. * * @param url * the url for the connection. * @param headers * the received headers, never {@code null}. */ void onHeaders(String url, HeaderMap headers); /** * This method is called when bytes of the responses body are received. * * @param url * the url for the connection. * @param amount * the number of transferred bytes so far. * @param current * the number of transferred bytes since the last call to this * method. * @param total * the total number of bytes to be transferred. This is taken * from the Content-Length-header and may be unspecified (-1). */ void onBytesReceived(String url, long amount, long current, long total); /** * This method is called when bytes are sent. * * @param url * the url for the connection. * @param amount * the number of transferred bytes so far. * @param current * the number of transferred bytes since the last call to this * method. * @param total * the total number of bytes to be transferred. This is taken * from the Content-Length-header and may be unspecified (-1). */ void onBytesSent(String url, long amount, long current, long total); /** * This method is called when the request is completed. * * @param url * the url for the connection. * @param statusCode * the received status code. * @param statusText * the received status text. */ void onCompleted(String url, int statusCode, String statusText); } async-http-client-1.6.5/src/main/java/com/ning/http/client/webdav/000077500000000000000000000000001166553056000247525ustar00rootroot00000000000000async-http-client-1.6.5/src/main/java/com/ning/http/client/webdav/WebDavCompletionHandlerBase.java000066400000000000000000000143301166553056000331110ustar00rootroot00000000000000/* * Copyright (c) 2010-2011 Sonatype, Inc. All rights reserved. * * This program is licensed to you under the Apache License Version 2.0, * and you may not use this file except in compliance with the Apache License Version 2.0. * You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0. * * Unless required by applicable law or agreed to in writing, * software distributed under the Apache License Version 2.0 is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. */ package com.ning.http.client.webdav; import com.ning.http.client.AsyncCompletionHandlerBase; import com.ning.http.client.AsyncHandler; import com.ning.http.client.HttpResponseBodyPart; import com.ning.http.client.HttpResponseHeaders; import com.ning.http.client.HttpResponseStatus; import com.ning.http.client.Response; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import org.xml.sax.SAXException; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; /** * Simple {@link AsyncHandler} that add support for WebDav's response manipulation. * * @param */ public abstract class WebDavCompletionHandlerBase implements AsyncHandler { private final Logger logger = LoggerFactory.getLogger(AsyncCompletionHandlerBase.class); private final Collection bodies = Collections.synchronizedCollection(new ArrayList()); private HttpResponseStatus status; private HttpResponseHeaders headers; /** * {@inheritDoc} */ /* @Override */ public final STATE onBodyPartReceived(final HttpResponseBodyPart content) throws Exception { bodies.add(content); return STATE.CONTINUE; } /** * {@inheritDoc} */ /* @Override */ public final STATE onStatusReceived(final HttpResponseStatus status) throws Exception { this.status = status; return STATE.CONTINUE; } /** * {@inheritDoc} */ /* @Override */ public final STATE onHeadersReceived(final HttpResponseHeaders headers) throws Exception { this.headers = headers; return STATE.CONTINUE; } /** * {@inheritDoc} */ /* @Override */ public final T onCompleted() throws Exception { if (status != null) { Response response = status.provider().prepareResponse(status, headers, bodies); Document document = null; if (status.getStatusCode() == 207) { document = readXMLResponse(response.getResponseBodyAsStream()); } return onCompleted(new WebDavResponse(status.provider().prepareResponse(status, headers, bodies), document)); } else { throw new IllegalStateException("Status is null"); } } /** * {@inheritDoc} */ /* @Override */ public void onThrowable(Throwable t) { logger.debug(t.getMessage(), t); } /** * Invoked once the HTTP response has been fully read. * * @param response The {@link com.ning.http.client.Response} * @return Type of the value that will be returned by the associated {@link java.util.concurrent.Future} */ abstract public T onCompleted(WebDavResponse response) throws Exception; private class HttpStatusWrapper extends HttpResponseStatus { private final HttpResponseStatus wrapper; private final String statusText; private final int statusCode; public HttpStatusWrapper(HttpResponseStatus wrapper, String statusText, int statusCode) { super(wrapper.getUrl(), wrapper.provider()); this.wrapper = wrapper; this.statusText = statusText; this.statusCode = statusCode; } @Override public int getStatusCode() { return (statusText == null ? wrapper.getStatusCode() : statusCode); } @Override public String getStatusText() { return (statusText == null ? wrapper.getStatusText() : statusText); } @Override public String getProtocolName() { return wrapper.getProtocolName(); } @Override public int getProtocolMajorVersion() { return wrapper.getProtocolMajorVersion(); } @Override public int getProtocolMinorVersion() { return wrapper.getProtocolMinorVersion(); } @Override public String getProtocolText() { return wrapper.getStatusText(); } } private Document readXMLResponse(InputStream stream) { DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); Document document = null; try { document = factory.newDocumentBuilder().parse(stream); parse(document); } catch (SAXException e) { logger.error(e.getMessage(), e); throw new RuntimeException(e); } catch (IOException e) { logger.error(e.getMessage(), e); throw new RuntimeException(e); } catch (ParserConfigurationException e) { logger.error(e.getMessage(), e); throw new RuntimeException(e); } return document; } private void parse(Document document) { Element element = document.getDocumentElement(); NodeList statusNode = element.getElementsByTagName("status"); for (int i = 0; i < statusNode.getLength(); i++) { Node node = statusNode.item(i); String value = node.getFirstChild().getNodeValue(); int statusCode = Integer.valueOf(value.substring(value.indexOf(" "), value.lastIndexOf(" ")).trim()); String statusText = value.substring(value.lastIndexOf(" ")); status = new HttpStatusWrapper(status, statusText, statusCode); } } } async-http-client-1.6.5/src/main/java/com/ning/http/client/webdav/WebDavResponse.java000066400000000000000000000063161166553056000305120ustar00rootroot00000000000000/* * Copyright (c) 2010-2011 Sonatype, Inc. All rights reserved. * * This program is licensed to you under the Apache License Version 2.0, * and you may not use this file except in compliance with the Apache License Version 2.0. * You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0. * * Unless required by applicable law or agreed to in writing, * software distributed under the Apache License Version 2.0 is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. */ package com.ning.http.client.webdav; import com.ning.http.client.Cookie; import com.ning.http.client.FluentCaseInsensitiveStringsMap; import com.ning.http.client.Response; import org.w3c.dom.Document; import java.io.IOException; import java.io.InputStream; import java.net.MalformedURLException; import java.net.URI; import java.util.List; /** * Customized {@link Response} which add support for getting the response's body as an XML document (@link WebDavResponse#getBodyAsXML} */ public class WebDavResponse implements Response{ private final Response response; private final Document document; public WebDavResponse(Response response, Document document) { this.response = response; this.document = document; } public int getStatusCode() { return response.getStatusCode(); } public String getStatusText() { return response.getStatusText(); } public InputStream getResponseBodyAsStream() throws IOException { return response.getResponseBodyAsStream(); } public String getResponseBodyExcerpt(int maxLength) throws IOException { return response.getResponseBodyExcerpt(maxLength); } public String getResponseBodyExcerpt(int maxLength, String charset) throws IOException { return response.getResponseBodyExcerpt(maxLength, charset); } public String getResponseBody() throws IOException { return response.getResponseBody(); } public String getResponseBody(String charset) throws IOException { return response.getResponseBody(charset); } public URI getUri() throws MalformedURLException { return response.getUri(); } public String getContentType() { return response.getContentType(); } public String getHeader(String name) { return response.getHeader(name); } public List getHeaders(String name) { return response.getHeaders(name); } public FluentCaseInsensitiveStringsMap getHeaders() { return response.getHeaders(); } public boolean isRedirected() { return response.isRedirected(); } public List getCookies() { return response.getCookies(); } public boolean hasResponseStatus() { return response.hasResponseStatus(); } public boolean hasResponseHeaders() { return response.hasResponseHeaders(); } public boolean hasResponseBody() { return response.hasResponseBody(); } public Document getBodyAsXML(){ return document; } } async-http-client-1.6.5/src/main/java/com/ning/http/multipart/000077500000000000000000000000001166553056000242455ustar00rootroot00000000000000async-http-client-1.6.5/src/main/java/com/ning/http/multipart/ByteArrayPartSource.java000066400000000000000000000034131166553056000310230ustar00rootroot00000000000000/* * Copyright 2010 Ning, Inc. * * Ning licenses this file to you 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. */ package com.ning.http.multipart; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; /** * This class is an adaptation of the Apache HttpClient implementation * @link http://hc.apache.org/httpclient-3.x/ */ public class ByteArrayPartSource implements PartSource { /** Name of the source file. */ private final String fileName; /** Byte array of the source file. */ private final byte[] bytes; /** * Constructor for ByteArrayPartSource. * * @param fileName the name of the file these bytes represent * @param bytes the content of this part */ public ByteArrayPartSource(String fileName, byte[] bytes) { this.fileName = fileName; this.bytes = bytes; } /** * @see PartSource#getLength() */ public long getLength() { return bytes.length; } /** * @see PartSource#getFileName() */ public String getFileName() { return fileName; } /** * @see PartSource#createInputStream() */ public InputStream createInputStream() throws IOException { return new ByteArrayInputStream(bytes); } } async-http-client-1.6.5/src/main/java/com/ning/http/multipart/FilePart.java000066400000000000000000000154601166553056000266240ustar00rootroot00000000000000/* * Copyright 2010 Ning, Inc. * * Ning licenses this file to you 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. */ package com.ning.http.multipart; import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; /** * This class is an adaptation of the Apache HttpClient implementation * @link http://hc.apache.org/httpclient-3.x/ */ public class FilePart extends PartBase { /** Default content encoding of file attachments. */ public static final String DEFAULT_CONTENT_TYPE = "application/octet-stream"; /** Default charset of file attachments. */ public static final String DEFAULT_CHARSET = "ISO-8859-1"; /** Default transfer encoding of file attachments. */ public static final String DEFAULT_TRANSFER_ENCODING = "binary"; /** Attachment's file name */ protected static final String FILE_NAME = "; filename="; /** Attachment's file name as a byte array */ private static final byte[] FILE_NAME_BYTES = MultipartEncodingUtil.getAsciiBytes(FILE_NAME); /** Source of the file part. */ private PartSource source; /** * FilePart Constructor. * * @param name the name for this part * @param partSource the source for this part * @param contentType the content type for this part, if null the * {@link #DEFAULT_CONTENT_TYPE default} is used * @param charset the charset encoding for this part, if null the * {@link #DEFAULT_CHARSET default} is used */ public FilePart(String name, PartSource partSource, String contentType, String charset) { super( name, contentType == null ? DEFAULT_CONTENT_TYPE : contentType, charset == null ? "ISO-8859-1" : charset, DEFAULT_TRANSFER_ENCODING ); if (partSource == null) { throw new IllegalArgumentException("Source may not be null"); } this.source = partSource; } /** * FilePart Constructor. * * @param name the name for this part * @param partSource the source for this part */ public FilePart(String name, PartSource partSource) { this(name, partSource, null, null); } /** * FilePart Constructor. * * @param name the name of the file part * @param file the file to post * * @throws java.io.FileNotFoundException if the file is not a normal * file or if it is not readable. */ public FilePart(String name, File file) throws FileNotFoundException { this(name, new FilePartSource(file), null, null); } /** * FilePart Constructor. * * @param name the name of the file part * @param file the file to post * @param contentType the content type for this part, if null the * {@link #DEFAULT_CONTENT_TYPE default} is used * @param charset the charset encoding for this part, if null the * {@link #DEFAULT_CHARSET default} is used * * @throws FileNotFoundException if the file is not a normal * file or if it is not readable. */ public FilePart(String name, File file, String contentType, String charset) throws FileNotFoundException { this(name, new FilePartSource(file), contentType, charset); } /** * FilePart Constructor. * * @param name the name of the file part * @param fileName the file name * @param file the file to post * * @throws FileNotFoundException if the file is not a normal * file or if it is not readable. */ public FilePart(String name, String fileName, File file) throws FileNotFoundException { this(name, new FilePartSource(fileName, file), null, null); } /** * FilePart Constructor. * * @param name the name of the file part * @param fileName the file name * @param file the file to post * @param contentType the content type for this part, if null the * {@link #DEFAULT_CONTENT_TYPE default} is used * @param charset the charset encoding for this part, if null the * {@link #DEFAULT_CHARSET default} is used * * @throws FileNotFoundException if the file is not a normal * file or if it is not readable. */ public FilePart(String name, String fileName, File file, String contentType, String charset) throws FileNotFoundException { this(name, new FilePartSource(fileName, file), contentType, charset); } /** * Write the disposition header to the output stream * @param out The output stream * @throws java.io.IOException If an IO problem occurs */ protected void sendDispositionHeader(OutputStream out) throws IOException { super.sendDispositionHeader(out); String filename = this.source.getFileName(); if (filename != null) { out.write(FILE_NAME_BYTES); out.write(QUOTE_BYTES); out.write(MultipartEncodingUtil.getAsciiBytes(filename)); out.write(QUOTE_BYTES); } } /** * Write the data in "source" to the specified stream. * @param out The output stream. * @throws IOException if an IO problem occurs. */ protected void sendData(OutputStream out) throws IOException { if (lengthOfData() == 0) { // this file contains no data, so there is nothing to send. // we don't want to create a zero length buffer as this will // cause an infinite loop when reading. return; } byte[] tmp = new byte[4096]; InputStream instream = source.createInputStream(); try { int len; while ((len = instream.read(tmp)) >= 0) { out.write(tmp, 0, len); } } finally { // we're done with the stream, close it instream.close(); } } /** * Returns the source of the file part. * * @return The source. */ protected PartSource getSource() { return this.source; } /** * Return the length of the data. * @return The length. * @throws IOException if an IO problem occurs */ protected long lengthOfData() throws IOException { return source.getLength(); } } async-http-client-1.6.5/src/main/java/com/ning/http/multipart/FilePartSource.java000066400000000000000000000063271166553056000300070ustar00rootroot00000000000000/* * Copyright 2010 Ning, Inc. * * Ning licenses this file to you 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. */ package com.ning.http.multipart; import java.io.ByteArrayInputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; /** * This class is an adaptation of the Apache HttpClient implementation * @link http://hc.apache.org/httpclient-3.x/ */ public class FilePartSource implements PartSource { /** File part file. */ private File file = null; /** File part file name. */ private String fileName = null; /** * Constructor for FilePartSource. * * @param file the FilePart source File. * * @throws java.io.FileNotFoundException if the file does not exist or * cannot be read */ public FilePartSource(File file) throws FileNotFoundException { this.file = file; if (file != null) { if (!file.isFile()) { throw new FileNotFoundException("File is not a normal file."); } if (!file.canRead()) { throw new FileNotFoundException("File is not readable."); } this.fileName = file.getName(); } } /** * Constructor for FilePartSource. * * @param fileName the file name of the FilePart * @param file the source File for the FilePart * * @throws FileNotFoundException if the file does not exist or * cannot be read */ public FilePartSource(String fileName, File file) throws FileNotFoundException { this(file); if (fileName != null) { this.fileName = fileName; } } /** * Return the length of the file * @return the length of the file. * @see PartSource#getLength() */ public long getLength() { if (this.file != null) { return this.file.length(); } else { return 0; } } /** * Return the current filename * @return the filename. * @see PartSource#getFileName() */ public String getFileName() { return (fileName == null) ? "noname" : fileName; } /** * Return a new {@link java.io.FileInputStream} for the current filename. * @return the new input stream. * @throws java.io.IOException If an IO problem occurs. * @see PartSource#createInputStream() */ public InputStream createInputStream() throws IOException { if (this.file != null) { return new FileInputStream(this.file); } else { return new ByteArrayInputStream(new byte[] {}); } } public File getFile() { return file; } } async-http-client-1.6.5/src/main/java/com/ning/http/multipart/MultipartBody.java000066400000000000000000000460141166553056000277140ustar00rootroot00000000000000/* * Copyright (c) 2010-2011 Sonatype, Inc. All rights reserved. * * This program is licensed to you under the Apache License Version 2.0, * and you may not use this file except in compliance with the Apache License Version 2.0. * You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0. * * Unless required by applicable law or agreed to in writing, * software distributed under the Apache License Version 2.0 is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. */ package com.ning.http.multipart; import com.ning.http.client.RandomAccessBody; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.io.RandomAccessFile; import java.nio.ByteBuffer; import java.nio.channels.FileChannel; import java.nio.channels.WritableByteChannel; import java.util.ArrayList; import java.util.List; public class MultipartBody implements RandomAccessBody { private byte[] boundary; private long contentLength; private List parts; private List files; private int startPart; private final static Logger logger = LoggerFactory.getLogger(MultipartBody.class); ByteArrayInputStream currentStream; int currentStreamPosition; boolean endWritten; boolean doneWritingParts; FileLocation fileLocation; FilePart currentFilePart; FileChannel currentFileChannel; enum FileLocation {NONE, START, MIDDLE, END} public MultipartBody(List parts, String boundary, String contentLength) { this.boundary = MultipartEncodingUtil.getAsciiBytes(boundary.substring("multipart/form-data; boundary=".length())); this.contentLength = Long.parseLong(contentLength); this.parts = parts; files = new ArrayList(); startPart = 0; currentStreamPosition = -1; endWritten = false; doneWritingParts = false; fileLocation = FileLocation.NONE; currentFilePart = null; } public void close() throws IOException { for (RandomAccessFile file : files) { file.close(); } } public long getContentLength() { return contentLength; } public long read(ByteBuffer buffer) throws IOException { try { int overallLength = 0; int maxLength = buffer.capacity(); if (startPart == parts.size() && endWritten) { return overallLength; } boolean full = false; while (!full && !doneWritingParts) { com.ning.http.client.Part part = null; if (startPart < parts.size()) { part = parts.get(startPart); } if (currentFileChannel != null) { overallLength += currentFileChannel.read(buffer); if (currentFileChannel.position() == currentFileChannel.size()) { currentFileChannel.close(); currentFileChannel = null; } if (overallLength == maxLength) { full = true; } } else if (currentStreamPosition > -1) { overallLength += writeToBuffer(buffer, maxLength - overallLength); if (overallLength == maxLength) { full = true; } if (startPart == parts.size() && currentStream.available() == 0) { doneWritingParts = true; } } else if (part instanceof StringPart) { StringPart currentPart = (StringPart) part; initializeStringPart(currentPart); startPart++; } else if (part instanceof com.ning.http.client.StringPart) { StringPart currentPart = generateClientStringpart(part); initializeStringPart(currentPart); startPart++; } else if (part instanceof FilePart) { if (fileLocation == FileLocation.NONE) { currentFilePart = (FilePart) part; initializeFilePart(currentFilePart); } else if (fileLocation == FileLocation.START) { initializeFileBody(currentFilePart); } else if (fileLocation == FileLocation.MIDDLE) { initializeFileEnd(currentFilePart); } else if (fileLocation == FileLocation.END) { startPart++; if (startPart == parts.size() && currentStream.available() == 0) { doneWritingParts = true; } } } else if (part instanceof com.ning.http.client.FilePart) { if (fileLocation == FileLocation.NONE) { currentFilePart = generateClientFilePart(part); initializeFilePart(currentFilePart); } else if (fileLocation == FileLocation.START) { initializeFileBody(currentFilePart); } else if (fileLocation == FileLocation.MIDDLE) { initializeFileEnd(currentFilePart); } else if (fileLocation == FileLocation.END) { startPart++; if (startPart == parts.size() && currentStream.available() == 0) { doneWritingParts = true; } } } else if (part instanceof com.ning.http.client.ByteArrayPart) { com.ning.http.client.ByteArrayPart bytePart = (com.ning.http.client.ByteArrayPart) part; if (fileLocation == FileLocation.NONE) { currentFilePart = generateClientByteArrayPart(bytePart); initializeFilePart(currentFilePart); } else if (fileLocation == FileLocation.START) { initializeByteArrayBody(currentFilePart); } else if (fileLocation == FileLocation.MIDDLE) { initializeFileEnd(currentFilePart); } else if (fileLocation == FileLocation.END) { startPart++; if (startPart == parts.size() && currentStream.available() == 0) { doneWritingParts = true; } } } } if (doneWritingParts) { if (currentStreamPosition == -1) { ByteArrayOutputStream endWriter = new ByteArrayOutputStream(); Part.sendMessageEnd(endWriter, boundary); initializeBuffer(endWriter); } if (currentStreamPosition > -1) { overallLength += writeToBuffer(buffer, maxLength - overallLength); if (currentStream.available() == 0) { currentStream.close(); currentStreamPosition = -1; endWritten = true; } } } return overallLength; } catch (Exception e) { logger.info("read exception", e); return 0; } } private void initializeByteArrayBody(FilePart filePart) throws IOException { ByteArrayOutputStream output = generateByteArrayBody(filePart); initializeBuffer(output); fileLocation = FileLocation.MIDDLE; } private void initializeFileEnd(FilePart currentPart) throws IOException { ByteArrayOutputStream output = generateFileEnd(currentPart); initializeBuffer(output); fileLocation = FileLocation.END; } private void initializeFileBody(FilePart currentPart) throws IOException { if (FilePartSource.class.isAssignableFrom(currentPart.getSource().getClass())) { FilePartSource source = (FilePartSource) currentPart.getSource(); File file = source.getFile(); RandomAccessFile raf = new RandomAccessFile(file, "r"); files.add(raf); currentFileChannel = raf.getChannel(); } else { PartSource partSource = currentPart.getSource(); InputStream stream = partSource.createInputStream(); byte[] bytes = new byte[(int) partSource.getLength()]; stream.read(bytes); currentStream = new ByteArrayInputStream(bytes); currentStreamPosition = 0; } fileLocation = FileLocation.MIDDLE; } private void initializeFilePart(FilePart filePart) throws IOException { filePart.setPartBoundary(boundary); ByteArrayOutputStream output = generateFileStart(filePart); initializeBuffer(output); fileLocation = FileLocation.START; } private void initializeStringPart(StringPart currentPart) throws IOException { currentPart.setPartBoundary(boundary); ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); Part.sendPart(outputStream, currentPart, boundary); initializeBuffer(outputStream); } private int writeToBuffer(ByteBuffer buffer, int length) throws IOException { int available = currentStream.available(); int writeLength = Math.min(available, length); byte[] bytes = new byte[writeLength]; currentStream.read(bytes); buffer.put(bytes); if (available <= length) { currentStream.close(); currentStreamPosition = -1; } else { currentStreamPosition += writeLength; } return writeLength; } private void initializeBuffer(ByteArrayOutputStream outputStream) throws IOException { currentStream = new ByteArrayInputStream(outputStream.toByteArray()); currentStreamPosition = 0; } public long transferTo(long position, long count, WritableByteChannel target) throws IOException { long overallLength = 0; if (startPart == parts.size()) { return contentLength; } int tempPart = startPart; for (com.ning.http.client.Part part : parts) { if (part instanceof Part) { overallLength += handleMultiPart(target, (Part) part); } else { overallLength += handleClientPart(target, part); } tempPart++; } ByteArrayOutputStream endWriter = new ByteArrayOutputStream(); Part.sendMessageEnd(endWriter, boundary); overallLength += writeToTarget(target, endWriter); startPart = tempPart; return overallLength; } private long handleClientPart( WritableByteChannel target, com.ning.http.client.Part part) throws IOException { if (part.getClass().equals(com.ning.http.client.StringPart.class)) { StringPart currentPart = generateClientStringpart(part); return handleStringPart(target, currentPart); } else if (part.getClass().equals(com.ning.http.client.FilePart.class)) { FilePart filePart = generateClientFilePart(part); return handleFilePart(target, filePart); } else if (part.getClass().equals(com.ning.http.client.ByteArrayPart.class)) { com.ning.http.client.ByteArrayPart bytePart = (com.ning.http.client.ByteArrayPart) part; FilePart filePart = generateClientByteArrayPart(bytePart); return handleByteArrayPart(target, filePart, bytePart.getData()); } return 0; } private FilePart generateClientByteArrayPart( com.ning.http.client.ByteArrayPart bytePart) { ByteArrayPartSource source = new ByteArrayPartSource(bytePart.getFileName(), bytePart.getData()); FilePart filePart = new FilePart(bytePart.getName(), source, bytePart.getMimeType(), bytePart.getCharSet()); return filePart; } private FilePart generateClientFilePart(com.ning.http.client.Part part) throws FileNotFoundException { com.ning.http.client.FilePart currentPart = (com.ning.http.client.FilePart) part; FilePart filePart = new FilePart(currentPart.getName(), currentPart.getFile(), currentPart.getMimeType(), currentPart.getCharSet()); return filePart; } private StringPart generateClientStringpart(com.ning.http.client.Part part) { com.ning.http.client.StringPart stringPart = (com.ning.http.client.StringPart) part; StringPart currentPart = new StringPart(stringPart.getName(), stringPart.getValue(), stringPart.getCharset()); return currentPart; } private long handleByteArrayPart(WritableByteChannel target, FilePart filePart, byte[] data) throws IOException { ByteArrayOutputStream output = generateByteArrayBody(filePart); return writeToTarget(target, output); } private ByteArrayOutputStream generateByteArrayBody(FilePart filePart) throws IOException { ByteArrayOutputStream output = new ByteArrayOutputStream(); Part.sendPart(output, filePart, boundary); return output; } private long handleFileEnd(WritableByteChannel target, FilePart filePart) throws IOException { ByteArrayOutputStream endOverhead = generateFileEnd(filePart); return this.writeToTarget(target, endOverhead); } private ByteArrayOutputStream generateFileEnd(FilePart filePart) throws IOException { ByteArrayOutputStream endOverhead = new ByteArrayOutputStream(); filePart.sendEnd(endOverhead); return endOverhead; } private long handleFileHeaders(WritableByteChannel target, FilePart filePart) throws IOException { filePart.setPartBoundary(boundary); ByteArrayOutputStream overhead = generateFileStart(filePart); return writeToTarget(target, overhead); } private ByteArrayOutputStream generateFileStart(FilePart filePart) throws IOException { ByteArrayOutputStream overhead = new ByteArrayOutputStream(); filePart.setPartBoundary(boundary); filePart.sendStart(overhead); filePart.sendDispositionHeader(overhead); filePart.sendContentTypeHeader(overhead); filePart.sendTransferEncodingHeader(overhead); filePart.sendEndOfHeader(overhead); return overhead; } private long handleFilePart(WritableByteChannel target, FilePart filePart) throws IOException { if (FilePartSource.class.isAssignableFrom(filePart.getSource().getClass())) { int length = 0; length += handleFileHeaders(target, filePart); FilePartSource source = (FilePartSource) filePart.getSource(); File file = source.getFile(); RandomAccessFile raf = new RandomAccessFile(file, "r"); files.add(raf); FileChannel fc = raf.getChannel(); long l = file.length(); int fileLength = 0; synchronized (fc) { while (fileLength != l) { fileLength += fc.transferTo(fileLength, l, target); if (fileLength != l) { logger.info("Waiting for writing..."); try { fc.wait(1000); } catch (InterruptedException e) { logger.trace(e.getMessage(), e); } } } } fc.close(); length += handleFileEnd(target, filePart); return length; } else { return handlePartSource(target, filePart); } } private long handlePartSource(WritableByteChannel target, FilePart filePart) throws IOException { int length = 0; length += handleFileHeaders(target, filePart); PartSource partSource = filePart.getSource(); InputStream stream = partSource.createInputStream(); try { int nRead = 0; while (nRead != -1) { // Do not buffer the entire monster in memory. byte[] bytes = new byte[8192]; nRead = stream.read(bytes); if (nRead > 0) { ByteArrayOutputStream bos = new ByteArrayOutputStream(nRead); bos.write(bytes, 0, nRead); writeToTarget(target, bos); } } } finally { stream.close(); } length += handleFileEnd(target, filePart); return length; } private long handleStringPart(WritableByteChannel target, StringPart currentPart) throws IOException { currentPart.setPartBoundary(boundary); ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); Part.sendPart(outputStream, currentPart, boundary); return writeToTarget(target, outputStream); } private long handleMultiPart(WritableByteChannel target, Part currentPart) throws IOException { currentPart.setPartBoundary(boundary); if (currentPart.getClass().equals(StringPart.class)) { return handleStringPart(target, (StringPart) currentPart); } else if (currentPart.getClass().equals(FilePart.class)) { FilePart filePart = (FilePart) currentPart; return handleFilePart(target, filePart); } return 0; } private long writeToTarget(WritableByteChannel target, ByteArrayOutputStream byteWriter) throws IOException { int written = 0; int maxSpin = 0; synchronized (byteWriter) { ByteBuffer message = ByteBuffer.wrap(byteWriter.toByteArray()); while ((target.isOpen()) && (written < byteWriter.size())) { written += target.write(message); if (written != byteWriter.size() && maxSpin++ < 10) { logger.info("Waiting for writing..."); try { byteWriter.wait(1000); maxSpin++; } catch (InterruptedException e) { logger.trace(e.getMessage(), e); } } else { if (maxSpin >= 10) { throw new IOException("Unable to write on channel " + target); } maxSpin = 0; } } } return written; } } async-http-client-1.6.5/src/main/java/com/ning/http/multipart/MultipartEncodingUtil.java000066400000000000000000000037131166553056000314020ustar00rootroot00000000000000/* * Copyright 2010 Ning, Inc. * * Ning licenses this file to you 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. */ package com.ning.http.multipart; import java.io.UnsupportedEncodingException; /** * This class is an adaptation of the Apache HttpClient implementation * @link http://hc.apache.org/httpclient-3.x/ */ public class MultipartEncodingUtil { public static byte[] getAsciiBytes(String data){ try { return data.getBytes("US-ASCII"); } catch (UnsupportedEncodingException e) { throw new RuntimeException(e); } } public static String getAsciiString(final byte[] data) { if (data == null) { throw new IllegalArgumentException("Parameter may not be null"); } try { return new String(data,"US-ASCII"); } catch (UnsupportedEncodingException e) { throw new RuntimeException(e); } } public static byte[] getBytes(final String data, String charset) { if (data == null) { throw new IllegalArgumentException("data may not be null"); } if (charset == null || charset.length() == 0) { throw new IllegalArgumentException("charset may not be null or empty"); } try { return data.getBytes(charset); } catch (UnsupportedEncodingException e) { throw new IllegalArgumentException(String.format("Unsupported encoding: %s", charset)); } } } async-http-client-1.6.5/src/main/java/com/ning/http/multipart/MultipartRequestEntity.java000066400000000000000000000114571166553056000316470ustar00rootroot00000000000000/* * Copyright 2010 Ning, Inc. * * Ning licenses this file to you 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. */ package com.ning.http.multipart; import com.ning.http.client.FluentStringsMap; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.IOException; import java.io.OutputStream; import java.util.Random; /** * This class is an adaptation of the Apache HttpClient implementation * @link http://hc.apache.org/httpclient-3.x/ */ public class MultipartRequestEntity implements RequestEntity { /** The Content-Type for multipart/form-data. */ private static final String MULTIPART_FORM_CONTENT_TYPE = "multipart/form-data"; /** * The pool of ASCII chars to be used for generating a multipart boundary. */ private static byte[] MULTIPART_CHARS = MultipartEncodingUtil.getAsciiBytes( "-_1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"); /** * Generates a random multipart boundary string. * @return */ private static byte[] generateMultipartBoundary() { Random rand = new Random(); byte[] bytes = new byte[rand.nextInt(11) + 30]; // a random size from 30 to 40 for (int i = 0; i < bytes.length; i++) { bytes[i] = MULTIPART_CHARS[rand.nextInt(MULTIPART_CHARS.length)]; } return bytes; } private final Logger log = LoggerFactory.getLogger(MultipartRequestEntity.class); /** The MIME parts as set by the constructor */ protected Part[] parts; private byte[] multipartBoundary; private FluentStringsMap methodParams; /** * Creates a new multipart entity containing the given parts. * @param parts The parts to include. * @param methodParams The params of the HttpMethod using this entity. */ public MultipartRequestEntity(Part[] parts, FluentStringsMap methodParams) { if (parts == null) { throw new IllegalArgumentException("parts cannot be null"); } if (methodParams == null) { methodParams = new FluentStringsMap(); } this.parts = parts; this.methodParams = methodParams; } /** * Returns the MIME boundary string that is used to demarcate boundaries of * this part. The first call to this method will implicitly create a new * boundary string. To create a boundary string first the * HttpMethodParams.MULTIPART_BOUNDARY parameter is considered. Otherwise * a random one is generated. * * @return The boundary string of this entity in ASCII encoding. */ protected byte[] getMultipartBoundary() { if (multipartBoundary == null) { String temp = methodParams.get("") == null ? null : methodParams.get("").iterator().next(); if (temp != null) { multipartBoundary = MultipartEncodingUtil.getAsciiBytes(temp); } else { multipartBoundary = generateMultipartBoundary(); } } return multipartBoundary; } /** * Returns true if all parts are repeatable, false otherwise. */ public boolean isRepeatable() { for (int i = 0; i < parts.length; i++) { if (!parts[i].isRepeatable()) { return false; } } return true; } /* (non-Javadoc) * @see org.apache.commons.httpclient.methods.RequestEntity#writeRequest(java.io.OutputStream) */ public void writeRequest(OutputStream out) throws IOException { Part.sendParts(out, parts, getMultipartBoundary()); } /* (non-Javadoc) * @see org.apache.commons.httpclient.methods.RequestEntity#getContentLength() */ public long getContentLength() { try { return Part.getLengthOfParts(parts, getMultipartBoundary()); } catch (Exception e) { log.error("An exception occurred while getting the length of the parts", e); return 0; } } /* (non-Javadoc) * @see org.apache.commons.httpclient.methods.RequestEntity#getContentType() */ public String getContentType() { StringBuffer buffer = new StringBuffer(MULTIPART_FORM_CONTENT_TYPE); buffer.append("; boundary="); buffer.append(MultipartEncodingUtil.getAsciiString(getMultipartBoundary())); return buffer.toString(); } } async-http-client-1.6.5/src/main/java/com/ning/http/multipart/Part.java000066400000000000000000000330051166553056000260170ustar00rootroot00000000000000/* * Copyright 2010 Ning, Inc. * * Ning licenses this file to you 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. */ package com.ning.http.multipart; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.OutputStream; /** * This class is an adaptation of the Apache HttpClient implementation * * @link http://hc.apache.org/httpclient-3.x/ */ public abstract class Part implements com.ning.http.client.Part { /** * The boundary */ protected static final String BOUNDARY = "----------------314159265358979323846"; /** * The default boundary to be used if etBoundaryBytes(byte[]) has not * been called. */ private static final byte[] DEFAULT_BOUNDARY_BYTES = MultipartEncodingUtil.getAsciiBytes(BOUNDARY); /** * Carriage return/linefeed */ protected static final String CRLF = "\r\n"; /** * Carriage return/linefeed as a byte array */ static final byte[] CRLF_BYTES = MultipartEncodingUtil.getAsciiBytes(CRLF); /** * Content dispostion characters */ protected static final String QUOTE = "\""; /** * Content dispostion as a byte array */ static final byte[] QUOTE_BYTES = MultipartEncodingUtil.getAsciiBytes(QUOTE); /** * Extra characters */ protected static final String EXTRA = "--"; /** * Extra characters as a byte array */ static final byte[] EXTRA_BYTES = MultipartEncodingUtil.getAsciiBytes(EXTRA); /** * Content dispostion characters */ protected static final String CONTENT_DISPOSITION = "Content-Disposition: form-data; name="; /** * Content dispostion as a byte array */ static final byte[] CONTENT_DISPOSITION_BYTES = MultipartEncodingUtil.getAsciiBytes(CONTENT_DISPOSITION); /** * Content type header */ protected static final String CONTENT_TYPE = "Content-Type: "; /** * Content type header as a byte array */ static final byte[] CONTENT_TYPE_BYTES = MultipartEncodingUtil.getAsciiBytes(CONTENT_TYPE); /** * Content charset */ protected static final String CHARSET = "; charset="; /** * Content charset as a byte array */ static final byte[] CHARSET_BYTES = MultipartEncodingUtil.getAsciiBytes(CHARSET); /** * Content type header */ protected static final String CONTENT_TRANSFER_ENCODING = "Content-Transfer-Encoding: "; /** * Content type header as a byte array */ static final byte[] CONTENT_TRANSFER_ENCODING_BYTES = MultipartEncodingUtil.getAsciiBytes(CONTENT_TRANSFER_ENCODING); /** * Return the boundary string. * * @return the boundary string * @deprecated uses a constant string. Rather use {@link #getPartBoundary} */ public static String getBoundary() { return BOUNDARY; } /** * The ASCII bytes to use as the multipart boundary. */ private byte[] boundaryBytes; /** * Return the name of this part. * * @return The name. */ public abstract String getName(); /** * Returns the content type of this part. * * @return the content type, or null to exclude the content type header */ public abstract String getContentType(); /** * Return the character encoding of this part. * * @return the character encoding, or null to exclude the character * encoding header */ public abstract String getCharSet(); /** * Return the transfer encoding of this part. * * @return the transfer encoding, or null to exclude the transfer encoding header */ public abstract String getTransferEncoding(); /** * Gets the part boundary to be used. * * @return the part boundary as an array of bytes. * @since 3.0 */ protected byte[] getPartBoundary() { if (boundaryBytes == null) { // custom boundary bytes have not been set, use the default. return DEFAULT_BOUNDARY_BYTES; } else { return boundaryBytes; } } /** * Sets the part boundary. Only meant to be used by * {@link Part#sendParts(java.io.OutputStream, Part[], byte[])} * and {@link Part#getLengthOfParts(Part[], byte[])} * * @param boundaryBytes An array of ASCII bytes. * @since 3.0 */ void setPartBoundary(byte[] boundaryBytes) { this.boundaryBytes = boundaryBytes; } /** * Tests if this part can be sent more than once. * * @return true if {@link #sendData(java.io.OutputStream)} can be successfully called * more than once. * @since 3.0 */ public boolean isRepeatable() { return true; } /** * Write the start to the specified output stream * * @param out The output stream * @throws java.io.IOException If an IO problem occurs. */ protected void sendStart(OutputStream out) throws IOException { out.write(EXTRA_BYTES); out.write(getPartBoundary()); out.write(CRLF_BYTES); } /** * Write the content disposition header to the specified output stream * * @param out The output stream * @throws IOException If an IO problem occurs. */ protected void sendDispositionHeader(OutputStream out) throws IOException { out.write(CONTENT_DISPOSITION_BYTES); out.write(QUOTE_BYTES); out.write(MultipartEncodingUtil.getAsciiBytes(getName())); out.write(QUOTE_BYTES); } /** * Write the content type header to the specified output stream * * @param out The output stream * @throws IOException If an IO problem occurs. */ protected void sendContentTypeHeader(OutputStream out) throws IOException { String contentType = getContentType(); if (contentType != null) { out.write(CRLF_BYTES); out.write(CONTENT_TYPE_BYTES); out.write(MultipartEncodingUtil.getAsciiBytes(contentType)); String charSet = getCharSet(); if (charSet != null) { out.write(CHARSET_BYTES); out.write(MultipartEncodingUtil.getAsciiBytes(charSet)); } } } /** * Write the content transfer encoding header to the specified * output stream * * @param out The output stream * @throws IOException If an IO problem occurs. */ protected void sendTransferEncodingHeader(OutputStream out) throws IOException { String transferEncoding = getTransferEncoding(); if (transferEncoding != null) { out.write(CRLF_BYTES); out.write(CONTENT_TRANSFER_ENCODING_BYTES); out.write(MultipartEncodingUtil.getAsciiBytes(transferEncoding)); } } /** * Write the end of the header to the output stream * * @param out The output stream * @throws IOException If an IO problem occurs. */ protected void sendEndOfHeader(OutputStream out) throws IOException { out.write(CRLF_BYTES); out.write(CRLF_BYTES); } /** * Write the data to the specified output stream * * @param out The output stream * @throws IOException If an IO problem occurs. */ protected abstract void sendData(OutputStream out) throws IOException; /** * Return the length of the main content * * @return long The length. * @throws IOException If an IO problem occurs */ protected abstract long lengthOfData() throws IOException; /** * Write the end data to the output stream. * * @param out The output stream * @throws IOException If an IO problem occurs. */ protected void sendEnd(OutputStream out) throws IOException { out.write(CRLF_BYTES); } /** * Write all the data to the output stream. * If you override this method make sure to override * #length() as well * * @param out The output stream * @throws IOException If an IO problem occurs. */ public void send(OutputStream out) throws IOException { sendStart(out); sendDispositionHeader(out); sendContentTypeHeader(out); sendTransferEncodingHeader(out); sendEndOfHeader(out); sendData(out); sendEnd(out); } /** * Return the full length of all the data. * If you override this method make sure to override * #send(OutputStream) as well * * @return long The length. * @throws IOException If an IO problem occurs */ public long length() throws IOException { if (lengthOfData() < 0) { return -1; } ByteArrayOutputStream overhead = new ByteArrayOutputStream(); sendStart(overhead); sendDispositionHeader(overhead); sendContentTypeHeader(overhead); sendTransferEncodingHeader(overhead); sendEndOfHeader(overhead); sendEnd(overhead); return overhead.size() + lengthOfData(); } /** * Return a string representation of this object. * * @return A string representation of this object. * @see java.lang.Object#toString() */ public String toString() { return this.getName(); } /** * Write all parts and the last boundary to the specified output stream. * * @param out The stream to write to. * @param parts The parts to write. * @throws IOException If an I/O error occurs while writing the parts. */ public static void sendParts(OutputStream out, final Part[] parts) throws IOException { sendParts(out, parts, DEFAULT_BOUNDARY_BYTES); } /** * Write all parts and the last boundary to the specified output stream. * * @param out The stream to write to. * @param parts The parts to write. * @param partBoundary The ASCII bytes to use as the part boundary. * @throws IOException If an I/O error occurs while writing the parts. * @since 3.0 */ public static void sendParts(OutputStream out, Part[] parts, byte[] partBoundary) throws IOException { if (parts == null) { throw new IllegalArgumentException("Parts may not be null"); } if (partBoundary == null || partBoundary.length == 0) { throw new IllegalArgumentException("partBoundary may not be empty"); } for (Part part : parts) { // set the part boundary before the part is sent part.setPartBoundary(partBoundary); part.send(out); } out.write(EXTRA_BYTES); out.write(partBoundary); out.write(EXTRA_BYTES); out.write(CRLF_BYTES); } public static void sendMessageEnd(OutputStream out, byte[] partBoundary) throws IOException { if (partBoundary == null || partBoundary.length == 0) { throw new IllegalArgumentException("partBoundary may not be empty"); } out.write(EXTRA_BYTES); out.write(partBoundary); out.write(EXTRA_BYTES); out.write(CRLF_BYTES); } /** * Write all parts and the last boundary to the specified output stream. * * @param out The stream to write to. * @param part The part to write. * @throws IOException If an I/O error occurs while writing the parts. * @since N/A */ public static void sendPart(OutputStream out, Part part, byte[] partBoundary) throws IOException { if (part == null) { throw new IllegalArgumentException("Parts may not be null"); } part.setPartBoundary(partBoundary); part.send(out); } /** * Return the total sum of all parts and that of the last boundary * * @param parts The parts. * @return The total length * @throws IOException If an I/O error occurs while writing the parts. */ public static long getLengthOfParts(Part[] parts) throws IOException { return getLengthOfParts(parts, DEFAULT_BOUNDARY_BYTES); } /** * Gets the length of the multipart message including the given parts. * * @param parts The parts. * @param partBoundary The ASCII bytes to use as the part boundary. * @return The total length * @throws IOException If an I/O error occurs while writing the parts. * @since 3.0 */ public static long getLengthOfParts(Part[] parts, byte[] partBoundary) throws IOException { if (parts == null) { throw new IllegalArgumentException("Parts may not be null"); } long total = 0; for (Part part : parts) { // set the part boundary before we calculate the part's length part.setPartBoundary(partBoundary); long l = part.length(); if (l < 0) { return -1; } total += l; } total += EXTRA_BYTES.length; total += partBoundary.length; total += EXTRA_BYTES.length; total += CRLF_BYTES.length; return total; } } async-http-client-1.6.5/src/main/java/com/ning/http/multipart/PartBase.java000066400000000000000000000066211166553056000266160ustar00rootroot00000000000000/* * Copyright 2010 Ning, Inc. * * Ning licenses this file to you 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. */ package com.ning.http.multipart; /** * This class is an adaptation of the Apache HttpClient implementation * @link http://hc.apache.org/httpclient-3.x/ */ public abstract class PartBase extends Part { /** Name of the file part. */ private String name; /** Content type of the file part. */ private String contentType; /** Content encoding of the file part. */ private String charSet; /** The transfer encoding. */ private String transferEncoding; /** * Constructor. * * @param name The name of the part * @param contentType The content type, or null * @param charSet The character encoding, or null * @param transferEncoding The transfer encoding, or null */ public PartBase(String name, String contentType, String charSet, String transferEncoding) { if (name == null) { throw new IllegalArgumentException("Name must not be null"); } this.name = name; this.contentType = contentType; this.charSet = charSet; this.transferEncoding = transferEncoding; } /** * Returns the name. * @return The name. */ public String getName() { return this.name; } /** * Returns the content type of this part. * @return String The name. */ public String getContentType() { return this.contentType; } /** * Return the character encoding of this part. * @return String The name. */ public String getCharSet() { return this.charSet; } /** * Returns the transfer encoding of this part. * @return String The name. */ public String getTransferEncoding() { return transferEncoding; } /** * Sets the character encoding. * * @param charSet the character encoding, or null to exclude the character * encoding header */ public void setCharSet(String charSet) { this.charSet = charSet; } /** * Sets the content type. * * @param contentType the content type, or null to exclude the content type header */ public void setContentType(String contentType) { this.contentType = contentType; } /** * Sets the part name. * * @param name */ public void setName(String name) { if (name == null) { throw new IllegalArgumentException("Name must not be null"); } this.name = name; } /** * Sets the transfer encoding. * * @param transferEncoding the transfer encoding, or null to exclude the * transfer encoding header */ public void setTransferEncoding(String transferEncoding) { this.transferEncoding = transferEncoding; } } async-http-client-1.6.5/src/main/java/com/ning/http/multipart/PartSource.java000066400000000000000000000030051166553056000271750ustar00rootroot00000000000000/* * Copyright 2010 Ning, Inc. * * Ning licenses this file to you 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. */ package com.ning.http.multipart; import java.io.IOException; import java.io.InputStream; /** * This class is an adaptation of the Apache HttpClient implementation * @link http://hc.apache.org/httpclient-3.x/ */ public interface PartSource { /** * Gets the number of bytes contained in this source. * * @return a value >= 0 */ long getLength(); /** * Gets the name of the file this source represents. * * @return the fileName used for posting a MultiPart file part */ String getFileName(); /** * Gets a new InputStream for reading this source. This method can be * called more than once and should therefore return a new stream every * time. * * @return a new InputStream * * @throws java.io.IOException if an error occurs when creating the InputStream */ InputStream createInputStream() throws IOException; } async-http-client-1.6.5/src/main/java/com/ning/http/multipart/RequestEntity.java000066400000000000000000000037161166553056000277440ustar00rootroot00000000000000/* * Copyright 2010 Ning, Inc. * * Ning licenses this file to you 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. */ package com.ning.http.multipart; import java.io.IOException; import java.io.OutputStream; /** * This class is an adaptation of the Apache HttpClient implementation * @link http://hc.apache.org/httpclient-3.x/ */ public interface RequestEntity { /** * Tests if {@link #writeRequest(java.io.OutputStream)} can be called more than once. * * @return true if the entity can be written to {@link java.io.OutputStream} more than once, * false otherwise. */ boolean isRepeatable(); /** * Writes the request entity to the given stream. * @param out * @throws java.io.IOException */ void writeRequest(OutputStream out) throws IOException; /** * Gets the request entity's length. This method should return a non-negative value if the content * length is known or a negative value if it is not. In the latter case the * EntityEnclosingMethod will use chunk encoding to * transmit the request entity. * * @return a non-negative value when content length is known or a negative value when content length * is not known */ long getContentLength(); /** * Gets the entity's content type. This content type will be used as the value for the * "Content-Type" header. * @return the entity's content type */ String getContentType(); } async-http-client-1.6.5/src/main/java/com/ning/http/multipart/StringPart.java000066400000000000000000000067531166553056000272200ustar00rootroot00000000000000/* * Copyright 2010 Ning, Inc. * * Ning licenses this file to you 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. */ package com.ning.http.multipart; import java.io.IOException; import java.io.OutputStream; /** * This class is an adaptation of the Apache HttpClient implementation * @link http://hc.apache.org/httpclient-3.x/ */ public class StringPart extends PartBase { /** Default content encoding of string parameters. */ public static final String DEFAULT_CONTENT_TYPE = "text/plain"; /** Default charset of string parameters*/ public static final String DEFAULT_CHARSET = "US-ASCII"; /** Default transfer encoding of string parameters*/ public static final String DEFAULT_TRANSFER_ENCODING = "8bit"; /** Contents of this StringPart. */ private byte[] content; /** The String value of this part. */ private String value; /** * Constructor. * * @param name The name of the part * @param value the string to post * @param charset the charset to be used to encode the string, if null * the {@link #DEFAULT_CHARSET default} is used */ public StringPart(String name, String value, String charset) { super( name, DEFAULT_CONTENT_TYPE, charset == null ? DEFAULT_CHARSET : charset, DEFAULT_TRANSFER_ENCODING ); if (value == null) { throw new IllegalArgumentException("Value may not be null"); } if (value.indexOf(0) != -1) { // See RFC 2048, 2.8. "8bit Data" throw new IllegalArgumentException("NULs may not be present in string parts"); } this.value = value; } /** * Constructor. * * @param name The name of the part * @param value the string to post */ public StringPart(String name, String value) { this(name, value, null); } /** * Gets the content in bytes. Bytes are lazily created to allow the charset to be changed * after the part is created. * * @return the content in bytes */ private byte[] getContent() { if (content == null) { content = MultipartEncodingUtil.getBytes(value, getCharSet()); } return content; } /** * Writes the data to the given OutputStream. * @param out the OutputStream to write to * @throws java.io.IOException if there is a write error */ protected void sendData(OutputStream out) throws IOException { out.write(getContent()); } /** * Return the length of the data. * @return The length of the data. * @throws IOException If an IO problem occurs */ protected long lengthOfData() throws IOException { return getContent().length; } /* (non-Javadoc) * @see org.apache.commons.httpclient.methods.multipart.BasePart#setCharSet(java.lang.String) */ public void setCharSet(String charSet) { super.setCharSet(charSet); this.content = null; } } async-http-client-1.6.5/src/main/java/com/ning/http/util/000077500000000000000000000000001166553056000232015ustar00rootroot00000000000000async-http-client-1.6.5/src/main/java/com/ning/http/util/AsyncHttpProviderUtils.java000066400000000000000000000404701166553056000305220ustar00rootroot00000000000000/* * Copyright (c) 2010-2011 Sonatype, Inc. All rights reserved. * * This program is licensed to you under the Apache License Version 2.0, * and you may not use this file except in compliance with the Apache License Version 2.0. * You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0. * * Unless required by applicable law or agreed to in writing, * software distributed under the Apache License Version 2.0 is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. */ package com.ning.http.util; import com.ning.http.client.AsyncHttpProvider; import com.ning.http.client.ByteArrayPart; import com.ning.http.client.Cookie; import com.ning.http.client.FilePart; import com.ning.http.client.FluentStringsMap; import com.ning.http.client.HttpResponseBodyPart; import com.ning.http.client.Part; import com.ning.http.client.StringPart; import com.ning.http.multipart.ByteArrayPartSource; import com.ning.http.multipart.MultipartRequestEntity; import com.ning.http.multipart.PartSource; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.net.URI; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Collection; import java.util.List; import java.util.Locale; /** * {@link com.ning.http.client.AsyncHttpProvider} common utilities. *

* The cookies's handling code is from the Netty framework. */ public class AsyncHttpProviderUtils { public final static String DEFAULT_CHARSET = "ISO-8859-1"; private final static String BODY_NOT_COMPUTED = "Response's body hasn't been computed by your AsyncHandler."; protected final static ThreadLocal simpleDateFormat = new ThreadLocal() { protected SimpleDateFormat[] initialValue() { return new SimpleDateFormat[] { new SimpleDateFormat("EEE MMM d HH:mm:ss yyyy", Locale.US), //ASCTIME new SimpleDateFormat("EEEE, dd-MMM-yy HH:mm:ss zzz", Locale.US), //RFC1036 new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss z", Locale.US), new SimpleDateFormat("EEE, dd-MMM-yyyy HH:mm:ss z", Locale.US), new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss Z", Locale.US), new SimpleDateFormat("EEE, dd-MMM-yyyy HH:mm:ss Z", Locale.US), new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss zzz", Locale.US) // RFC1123 }; } }; public final static SimpleDateFormat[] get() { return simpleDateFormat.get(); } //space ' ' static final byte SP = 32; //tab ' ' static final byte HT = 9; /** * Carriage return */ static final byte CR = 13; /** * Equals '=' */ static final byte EQUALS = 61; /** * Line feed character */ static final byte LF = 10; /** * carriage return line feed */ static final byte[] CRLF = new byte[]{CR, LF}; /** * Colon ':' */ static final byte COLON = 58; /** * Semicolon ';' */ static final byte SEMICOLON = 59; /** * comma ',' */ static final byte COMMA = 44; static final byte DOUBLE_QUOTE = '"'; static final String PATH = "Path"; static final String EXPIRES = "Expires"; static final String MAX_AGE = "Max-Age"; static final String DOMAIN = "Domain"; static final String SECURE = "Secure"; static final String HTTPONLY = "HTTPOnly"; static final String COMMENT = "Comment"; static final String COMMENTURL = "CommentURL"; static final String DISCARD = "Discard"; static final String PORT = "Port"; static final String VERSION = "Version"; public final static URI createUri(String u) { URI uri = URI.create(u); final String scheme = uri.getScheme(); if (scheme == null || !scheme.equalsIgnoreCase("http") && !scheme.equalsIgnoreCase("https")) { throw new IllegalArgumentException("The URI scheme, of the URI " + u + ", must be equal (ignoring case) to 'http' or 'https'"); } String path = uri.getPath(); if (path == null) { throw new IllegalArgumentException("The URI path, of the URI " + uri + ", must be non-null"); } else if (path.length() > 0 && path.charAt(0) != '/') { throw new IllegalArgumentException("The URI path, of the URI " + uri + ". must start with a '/'"); } else if (path.length() == 0) { return URI.create(u + "/"); } return uri; } public final static String getBaseUrl(URI uri) { String url = uri.getScheme() + "://" + uri.getAuthority(); int port = uri.getPort(); if (port == -1) { port = getPort(uri); url += ":" + port; } return url; } public final static String getAuthority(URI uri) { String url = uri.getAuthority(); int port = uri.getPort(); if (port == -1) { port = getPort(uri); url += ":" + port; } return url; } public final static URI getRedirectUri(URI uri, String location) { URI newUri = uri.resolve(location); String scheme = newUri.getScheme(); if (scheme == null || !scheme.equalsIgnoreCase("http") && !scheme.equalsIgnoreCase("https")) { throw new IllegalArgumentException("The URI scheme, of the URI " + newUri + ", must be equal (ignoring case) to 'http' or 'https'"); } return newUri; } public final static int getPort(URI uri) { int port = uri.getPort(); if (port == -1) port = uri.getScheme().equals("http") ? 80 : 443; return port; } /** * This is quite ugly as our internal names are duplicated, but we build on top of HTTP Client implementation. * * @param params * @param methodParams * @return a MultipartRequestEntity. * @throws java.io.FileNotFoundException */ public final static MultipartRequestEntity createMultipartRequestEntity(List params, FluentStringsMap methodParams) throws FileNotFoundException { com.ning.http.multipart.Part[] parts = new com.ning.http.multipart.Part[params.size()]; int i = 0; for (Part part : params) { if (part instanceof com.ning.http.multipart.Part) { parts[i] = (com.ning.http.multipart.Part) part; } else if (part instanceof StringPart) { parts[i] = new com.ning.http.multipart.StringPart(part.getName(), ((StringPart) part).getValue(), ((StringPart) part).getCharset()); } else if (part instanceof FilePart) { parts[i] = new com.ning.http.multipart.FilePart(part.getName(), ((FilePart) part).getFile(), ((FilePart) part).getMimeType(), ((FilePart) part).getCharSet()); } else if (part instanceof ByteArrayPart) { PartSource source = new ByteArrayPartSource(((ByteArrayPart) part).getFileName(), ((ByteArrayPart) part).getData()); parts[i] = new com.ning.http.multipart.FilePart(part.getName(), source, ((ByteArrayPart) part).getMimeType(), ((ByteArrayPart) part).getCharSet()); } else if (part == null) { throw new NullPointerException("Part cannot be null"); } else { throw new IllegalArgumentException(String.format("Unsupported part type for multipart parameter %s", part.getName())); } ++i; } return new MultipartRequestEntity(parts, methodParams); } public final static byte[] readFully(InputStream in, int[] lengthWrapper) throws IOException { // just in case available() returns bogus (or -1), allocate non-trivial chunk byte[] b = new byte[Math.max(512, in.available())]; int offset = 0; while (true) { int left = b.length - offset; int count = in.read(b, offset, left); if (count < 0) { // EOF break; } offset += count; if (count == left) { // full buffer, need to expand b = doubleUp(b); } } // wish Java had Tuple return type... lengthWrapper[0] = offset; return b; } private static byte[] doubleUp(byte[] b) { int len = b.length; byte[] b2 = new byte[len + len]; System.arraycopy(b, 0, b2, 0, len); return b2; } public static String encodeCookies(Collection cookies) { StringBuilder sb = new StringBuilder(); for (Cookie cookie : cookies) { if (cookie.getVersion() >= 1) { add(sb, '$' + VERSION, 1); } add(sb, cookie.getName(), cookie.getValue()); if (cookie.getPath() != null) { add(sb, '$' + PATH, cookie.getPath()); } if (cookie.getDomain() != null) { add(sb, '$' + DOMAIN, cookie.getDomain()); } if (cookie.getVersion() >= 1) { if (!cookie.getPorts().isEmpty()) { sb.append('$'); sb.append(PORT); sb.append((char) EQUALS); sb.append((char) DOUBLE_QUOTE); for (int port : cookie.getPorts()) { sb.append(port); sb.append((char) COMMA); } sb.setCharAt(sb.length() - 1, (char) DOUBLE_QUOTE); sb.append((char) SEMICOLON); } } } sb.setLength(sb.length() - 1); return sb.toString(); } private static void add(StringBuilder sb, String name, String val) { if (val == null) { addQuoted(sb, name, ""); return; } for (int i = 0; i < val.length(); i++) { char c = val.charAt(i); switch (c) { case '\t': case ' ': case '"': case '(': case ')': case ',': case '/': case ':': case ';': case '<': case '=': case '>': case '?': case '@': case '[': case '\\': case ']': case '{': case '}': addQuoted(sb, name, val); return; } } addUnquoted(sb, name, val); } private static void addUnquoted(StringBuilder sb, String name, String val) { sb.append(name); sb.append((char) EQUALS); sb.append(val); sb.append((char) SEMICOLON); } private static void addQuoted(StringBuilder sb, String name, String val) { if (val == null) { val = ""; } sb.append(name); sb.append((char) EQUALS); sb.append((char) DOUBLE_QUOTE); sb.append(val.replace("\\", "\\\\").replace("\"", "\\\"")); sb.append((char) DOUBLE_QUOTE); sb.append((char) SEMICOLON); } private static void add(StringBuilder sb, String name, int val) { sb.append(name); sb.append((char) EQUALS); sb.append(val); sb.append((char) SEMICOLON); } public static String constructUserAgent(Class httpProvider) { StringBuffer b = new StringBuffer("AsyncHttpClient/1.0") .append(" ") .append("(") .append(httpProvider.getSimpleName()) .append(" - ") .append(System.getProperty("os.name")) .append(" - ") .append(System.getProperty("os.version")) .append(" - ") .append(System.getProperty("java.version")) .append(" - ") .append(Runtime.getRuntime().availableProcessors()) .append(" core(s))"); return b.toString(); } public static String parseCharset(String contentType) { for (String part : contentType.split(";")) { if (part.trim().startsWith("charset=")) { String[] val = part.split("="); if (val[1] != null) { return val[1].trim(); } } } return null; } public static Cookie parseCookie(String value) { String[] fields = value.split(";\\s*"); String[] cookie = fields[0].split("="); String cookieName = cookie[0]; String cookieValue = (cookie.length==1) ? null : cookie[1]; int maxAge = -1; String path = null; String domain = null; boolean secure = false; boolean maxAgeSet = false; boolean expiresSet = false; for (int j = 1; j < fields.length; j++) { if ("secure".equalsIgnoreCase(fields[j])) { secure = true; } else if (fields[j].indexOf('=') > 0) { String[] f = fields[j].split("="); if(f.length==1) continue; // Add protection against null field values // favor 'max-age' field over 'expires' if (!maxAgeSet && "max-age".equalsIgnoreCase(f[0])) { try { maxAge = Integer.valueOf(removeQuote(f[1])); } catch (NumberFormatException e1) { // ignore failure to parse -> treat as session cookie // invalidate a previously parsed expires-field maxAge = -1; } maxAgeSet = true; } else if (!maxAgeSet && !expiresSet && "expires".equalsIgnoreCase(f[0])) { try { maxAge = convertExpireField(f[1]); } catch (Exception e) { // original behavior, is this correct at all (expires field with max-age semantics)? try { maxAge = Integer.valueOf(f[1]); } catch (NumberFormatException e1) { // ignore failure to parse -> treat as session cookie } } expiresSet = true; } else if ("domain".equalsIgnoreCase(f[0])) { domain = f[1]; } else if ("path".equalsIgnoreCase(f[0])) { path = f[1]; } } } if (maxAge < -1) { maxAge = -1; } return new Cookie(domain, cookieName, cookieValue, path, maxAge, secure); } private static int convertExpireField(String timestring) throws Exception { Exception exception = null; for (SimpleDateFormat sdf : simpleDateFormat.get()) { try { long expire = sdf.parse(removeQuote(timestring.trim())).getTime(); return (int) ((expire - System.currentTimeMillis()) / 1000); } catch (ParseException e) { exception = e; } catch (NumberFormatException e) { exception = e; } } throw exception; } private final static String removeQuote(String s) { if (s.startsWith("\"")) { s = s.substring(1); } if (s.endsWith("\"")) { s = s.substring(0,s.length() -1); } return s; } public static void checkBodyParts(int statusCode, Collection bodyParts) { if (bodyParts == null || bodyParts.size() == 0) { // We allow empty body on 204 if (statusCode == 204) return; throw new IllegalStateException(BODY_NOT_COMPUTED); } } } async-http-client-1.6.5/src/main/java/com/ning/http/util/AuthenticatorUtils.java000066400000000000000000000052461166553056000277060ustar00rootroot00000000000000/* * Copyright (c) 2010-2011 Sonatype, Inc. All rights reserved. * * This program is licensed to you under the Apache License Version 2.0, * and you may not use this file except in compliance with the Apache License Version 2.0. * You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0. * * Unless required by applicable law or agreed to in writing, * software distributed under the Apache License Version 2.0 is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. */ package com.ning.http.util; import com.ning.http.client.ProxyServer; import com.ning.http.client.Realm; import java.io.UnsupportedEncodingException; import java.security.NoSuchAlgorithmException; public final class AuthenticatorUtils { public static String computeBasicAuthentication(Realm realm) throws UnsupportedEncodingException { String s = realm.getPrincipal() + ":" + realm.getPassword(); return "Basic " + Base64.encode(s.getBytes(realm.getEncoding())); } public static String computeBasicAuthentication(ProxyServer proxyServer) throws UnsupportedEncodingException { String s = proxyServer.getPrincipal() + ":" + proxyServer.getPassword(); return "Basic " + Base64.encode(s.getBytes(proxyServer.getEncoding())); } public static String computeDigestAuthentication(Realm realm) throws NoSuchAlgorithmException, UnsupportedEncodingException { StringBuilder builder = new StringBuilder().append("Digest "); construct(builder, "username", realm.getPrincipal()); construct(builder, "realm", realm.getRealmName()); construct(builder, "nonce", realm.getNonce()); construct(builder, "uri", realm.getUri()); builder.append("algorithm").append('=').append(realm.getAlgorithm()).append(", "); construct(builder, "response", realm.getResponse()); builder.append("qop").append('=').append(realm.getQop()).append(", "); builder.append("nc").append('=').append(realm.getNc()).append(", "); construct(builder, "cnonce", realm.getCnonce(), true); return new String(builder.toString().getBytes("ISO_8859_1")); } private static StringBuilder construct(StringBuilder builder, String name, String value) { return construct(builder,name,value,false); } private static StringBuilder construct(StringBuilder builder, String name, String value, boolean tail) { return builder.append(name).append('=').append('"').append(value).append(tail ? "\"" : "\", "); } } async-http-client-1.6.5/src/main/java/com/ning/http/util/Base64.java000066400000000000000000000106751166553056000251010ustar00rootroot00000000000000/* * Copyright (c) 2010-2011 Sonatype, Inc. All rights reserved. * * This program is licensed to you under the Apache License Version 2.0, * and you may not use this file except in compliance with the Apache License Version 2.0. * You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0. * * Unless required by applicable law or agreed to in writing, * software distributed under the Apache License Version 2.0 is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. */ package com.ning.http.util; /** * Implements the "base64" binary encoding scheme as defined by * RFC 2045. * * Portions of code here are taken from Apache Pivot */ public final class Base64 { private static final char[] lookup = new char[64]; private static final byte[] reverseLookup = new byte[256]; static { // Populate the lookup array for (int i = 0; i < 26; i++) { lookup[i] = (char) ('A' + i); } for (int i = 26, j = 0; i < 52; i++, j++) { lookup[i] = (char) ('a' + j); } for (int i = 52, j = 0; i < 62; i++, j++) { lookup[i] = (char) ('0' + j); } lookup[62] = '+'; lookup[63] = '/'; // Populate the reverse lookup array for (int i = 0; i < 256; i++) { reverseLookup[i] = -1; } for (int i = 'Z'; i >= 'A'; i--) { reverseLookup[i] = (byte) (i - 'A'); } for (int i = 'z'; i >= 'a'; i--) { reverseLookup[i] = (byte) (i - 'a' + 26); } for (int i = '9'; i >= '0'; i--) { reverseLookup[i] = (byte) (i - '0' + 52); } reverseLookup['+'] = 62; reverseLookup['/'] = 63; reverseLookup['='] = 0; } /** * This class is not instantiable. */ private Base64() { } /** * Encodes the specified data into a base64 string. * * @param bytes The unencoded raw data. */ public static String encode(byte[] bytes) { // always sequence of 4 characters for each 3 bytes; padded with '='s as necessary: StringBuilder buf = new StringBuilder(((bytes.length + 2) / 3) * 4); // first, handle complete chunks (fast loop) int i = 0; for (int end = bytes.length - 2; i < end; ) { int chunk = ((bytes[i++] & 0xFF) << 16) | ((bytes[i++] & 0xFF) << 8) | (bytes[i++] & 0xFF); buf.append(lookup[chunk >> 18]); buf.append(lookup[(chunk >> 12) & 0x3F]); buf.append(lookup[(chunk >> 6) & 0x3F]); buf.append(lookup[chunk & 0x3F]); } // then leftovers, if any int len = bytes.length; if (i < len) { // 1 or 2 extra bytes? int chunk = ((bytes[i++] & 0xFF) << 16); buf.append(lookup[chunk >> 18]); if (i < len) { // 2 bytes chunk |= ((bytes[i] & 0xFF) << 8); buf.append(lookup[(chunk >> 12) & 0x3F]); buf.append(lookup[(chunk >> 6) & 0x3F]); } else { // 1 byte buf.append(lookup[(chunk >> 12) & 0x3F]); buf.append('='); } buf.append('='); } return buf.toString(); } /** * Decodes the specified base64 string back into its raw data. * * @param encoded The base64 encoded string. */ public static byte[] decode(String encoded) { int padding = 0; for (int i = encoded.length() - 1; encoded.charAt(i) == '='; i--) { padding++; } int length = encoded.length() * 6 / 8 - padding; byte[] bytes = new byte[length]; for (int i = 0, index = 0, n = encoded.length(); i < n; i += 4) { int word = reverseLookup[encoded.charAt(i)] << 18; word += reverseLookup[encoded.charAt(i + 1)] << 12; word += reverseLookup[encoded.charAt(i + 2)] << 6; word += reverseLookup[encoded.charAt(i + 3)]; for (int j = 0; j < 3 && index + j < length; j++) { bytes[index + j] = (byte) (word >> (8 * (2 - j))); } index += 3; } return bytes; } } async-http-client-1.6.5/src/main/java/com/ning/http/util/CleanupChannelGroup.java000066400000000000000000000103731166553056000277450ustar00rootroot00000000000000/* * Copyright (c) 2010-2011 Sonatype, Inc. All rights reserved. * * This program is licensed to you under the Apache License Version 2.0, * and you may not use this file except in compliance with the Apache License Version 2.0. * You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0. * * Unless required by applicable law or agreed to in writing, * software distributed under the Apache License Version 2.0 is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. */ /* * Copyright 2010 Bruno de Carvalho * * 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. */ package com.ning.http.util; import org.jboss.netty.channel.Channel; import org.jboss.netty.channel.ChannelFuture; import org.jboss.netty.channel.group.ChannelGroup; import org.jboss.netty.channel.group.ChannelGroupFuture; import org.jboss.netty.channel.group.DefaultChannelGroup; import org.jboss.netty.channel.group.DefaultChannelGroupFuture; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.ArrayList; import java.util.Collection; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.locks.ReentrantReadWriteLock; /** * Extension of {@link DefaultChannelGroup} that's used mainly as a cleanup container, where {@link #close()} is only * supposed to be called once. * * @author Bruno de Carvalho */ public class CleanupChannelGroup extends DefaultChannelGroup { private final static Logger logger = LoggerFactory.getLogger(CleanupChannelGroup.class); // internal vars -------------------------------------------------------------------------------------------------- private final AtomicBoolean closed; private final ReentrantReadWriteLock lock; // constructors --------------------------------------------------------------------------------------------------- public CleanupChannelGroup() { this.closed = new AtomicBoolean(false); this.lock = new ReentrantReadWriteLock(); } public CleanupChannelGroup(String name) { super(name); this.closed = new AtomicBoolean(false); this.lock = new ReentrantReadWriteLock(); } // DefaultChannelGroup -------------------------------------------------------------------------------------------- @Override public ChannelGroupFuture close() { this.lock.writeLock().lock(); try { if (!this.closed.getAndSet(true)) { // First time close() is called. return super.close(); } else { Collection futures = new ArrayList(); logger.debug("CleanupChannelGroup Already closed"); return new DefaultChannelGroupFuture(ChannelGroup.class.cast(this), futures); } } finally { this.lock.writeLock().unlock(); } } @Override public boolean add(Channel channel) { // Synchronization must occur to avoid add() and close() overlap (thus potentially leaving one channel open). // This could also be done by synchronizing the method itself but using a read lock here (rather than a // synchronized() block) allows multiple concurrent calls to add(). this.lock.readLock().lock(); try { if (this.closed.get()) { // Immediately close channel, as close() was already called. channel.close(); return false; } return super.add(channel); } finally { this.lock.readLock().unlock(); } } } async-http-client-1.6.5/src/main/java/com/ning/http/util/DateUtil.java000066400000000000000000000210151166553056000255560ustar00rootroot00000000000000/* * Copyright (c) 2010-2011 Sonatype, Inc. All rights reserved. * * This program is licensed to you under the Apache License Version 2.0, * and you may not use this file except in compliance with the Apache License Version 2.0. * You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0. * * Unless required by applicable law or agreed to in writing, * software distributed under the Apache License Version 2.0 is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. */ package com.ning.http.util; /* * $Header: /home/jerenkrantz/tmp/commons/commons-convert/cvs/home/cvs/jakarta-commons//httpclient/src/java/org/apache/commons/httpclient/util/DateUtil.java,v 1.2 2004/12/24 20:36:13 olegk Exp $ * $Revision: 480424 $ * $Date: 2006-11-29 06:56:49 +0100 (Wed, 29 Nov 2006) $ * * ==================================================================== * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Software Foundation. For more * information on the Apache Software Foundation, please see * . * */ import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Arrays; import java.util.Calendar; import java.util.Collection; import java.util.Date; import java.util.Iterator; import java.util.Locale; import java.util.TimeZone; /** * A utility class for parsing and formatting HTTP dates as used in cookies and * other headers. This class handles dates as defined by RFC 2616 section * 3.3.1 as well as some other common non-standard formats. * * @author Christopher Brown * @author Michael Becke */ public class DateUtil { /** * Date format pattern used to parse HTTP date headers in RFC 1123 format. */ public static final String PATTERN_RFC1123 = "EEE, dd MMM yyyy HH:mm:ss zzz"; /** * Date format pattern used to parse HTTP date headers in RFC 1036 format. */ public static final String PATTERN_RFC1036 = "EEEE, dd-MMM-yy HH:mm:ss zzz"; /** * Date format pattern used to parse HTTP date headers in ANSI C * asctime() format. */ public static final String PATTERN_ASCTIME = "EEE MMM d HH:mm:ss yyyy"; private static final Collection DEFAULT_PATTERNS = Arrays.asList( new String[] { PATTERN_ASCTIME, PATTERN_RFC1036, PATTERN_RFC1123 } ); private static final Date DEFAULT_TWO_DIGIT_YEAR_START; static { Calendar calendar = Calendar.getInstance(); calendar.set(2000, Calendar.JANUARY, 1, 0, 0); DEFAULT_TWO_DIGIT_YEAR_START = calendar.getTime(); } private static final TimeZone GMT = TimeZone.getTimeZone("GMT"); /** * Parses a date value. The formats used for parsing the date value are retrieved from * the default http params. * * @param dateValue the date value to parse * * @return the parsed date * * @throws DateParseException if the value could not be parsed using any of the * supported date formats */ public static Date parseDate(String dateValue) throws DateParseException { return parseDate(dateValue, null, null); } /** * Parses the date value using the given date formats. * * @param dateValue the date value to parse * @param dateFormats the date formats to use * * @return the parsed date * * @throws DateParseException if none of the dataFormats could parse the dateValue */ public static Date parseDate(String dateValue, Collection dateFormats) throws DateParseException { return parseDate(dateValue, dateFormats, null); } /** * Parses the date value using the given date formats. * * @param dateValue the date value to parse * @param dateFormats the date formats to use * @param startDate During parsing, two digit years will be placed in the range * startDate to startDate + 100 years. This value may * be null. When null is given as a parameter, year * 2000 will be used. * * @return the parsed date * * @throws DateParseException if none of the dataFormats could parse the dateValue */ public static Date parseDate( String dateValue, Collection dateFormats, Date startDate ) throws DateParseException { if (dateValue == null) { throw new IllegalArgumentException("dateValue is null"); } if (dateFormats == null) { dateFormats = DEFAULT_PATTERNS; } if (startDate == null) { startDate = DEFAULT_TWO_DIGIT_YEAR_START; } // trim single quotes around date if present // see issue #5279 if (dateValue.length() > 1 && dateValue.startsWith("'") && dateValue.endsWith("'") ) { dateValue = dateValue.substring (1, dateValue.length() - 1); } SimpleDateFormat dateParser = null; Iterator formatIter = dateFormats.iterator(); while (formatIter.hasNext()) { String format = (String) formatIter.next(); if (dateParser == null) { dateParser = new SimpleDateFormat(format, Locale.US); dateParser.setTimeZone(TimeZone.getTimeZone("GMT")); dateParser.set2DigitYearStart(startDate); } else { dateParser.applyPattern(format); } try { return dateParser.parse(dateValue); } catch (ParseException pe) { // ignore this exception, we will try the next format } } // we were unable to parse the date throw new DateParseException("Unable to parse the date " + dateValue); } /** * Formats the given date according to the RFC 1123 pattern. * * @param date The date to format. * @return An RFC 1123 formatted date string. * * @see #PATTERN_RFC1123 */ public static String formatDate(Date date) { return formatDate(date, PATTERN_RFC1123); } /** * Formats the given date according to the specified pattern. The pattern * must conform to that used by the {@link java.text.SimpleDateFormat simple date * format} class. * * @param date The date to format. * @param pattern The pattern to use for formatting the date. * @return A formatted date string. * * @throws IllegalArgumentException If the given date pattern is invalid. * * @see java.text.SimpleDateFormat */ public static String formatDate(Date date, String pattern) { if (date == null) throw new IllegalArgumentException("date is null"); if (pattern == null) throw new IllegalArgumentException("pattern is null"); SimpleDateFormat formatter = new SimpleDateFormat(pattern, Locale.US); formatter.setTimeZone(GMT); return formatter.format(date); } /** This class should not be instantiated. */ private DateUtil() { } public static class DateParseException extends Exception { /** * */ public DateParseException() { super(); } /** * @param message the exception message */ public DateParseException(String message) { super(message); } } } async-http-client-1.6.5/src/main/java/com/ning/http/util/ProxyUtils.java000066400000000000000000000135631166553056000262160ustar00rootroot00000000000000/* * Copyright (c) 2010-2011 Sonatype, Inc. All rights reserved. * * This program is licensed to you under the Apache License Version 2.0, * and you may not use this file except in compliance with the Apache License Version 2.0. * You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0. * * Unless required by applicable law or agreed to in writing, * software distributed under the Apache License Version 2.0 is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. */ package com.ning.http.util; import com.ning.http.client.AsyncHttpClientConfig; import com.ning.http.client.ProxyServer; import com.ning.http.client.ProxyServer.Protocol; import com.ning.http.client.Request; import java.net.URI; import java.util.List; import java.util.Properties; /** * Utilities for Proxy handling. * * @author cstamas */ public class ProxyUtils { private static final String PROPERTY_PREFIX = "com.ning.http.client.AsyncHttpClientConfig.proxy."; /** * The host to use as proxy. */ public static final String PROXY_HOST = "http.proxyHost"; /** * The port to use for the proxy. */ public static final String PROXY_PORT = "http.proxyPort"; /** * The protocol to use. Is mapped to the {@link Protocol} enum. */ public static final String PROXY_PROTOCOL = PROPERTY_PREFIX + "protocol"; /** * A specification of non-proxy hosts. See http://download.oracle.com/javase/1.4.2/docs/guide/net/properties.html */ public static final String PROXY_NONPROXYHOSTS = "http.nonProxyHosts"; /** * The username to use for authentication for the proxy server. */ public static final String PROXY_USER = PROPERTY_PREFIX + "user"; /** * The password to use for authentication for the proxy server. */ public static final String PROXY_PASSWORD = PROPERTY_PREFIX + "password"; /** * Checks whether proxy should be used according to nonProxyHosts settings of it, or we want to go directly to * target host. If null proxy is passed in, this method returns true -- since there is NO proxy, we * should avoid to use it. Simple hostname pattern matching using "*" are supported, but only as prefixes. * See http://download.oracle.com/javase/1.4.2/docs/guide/net/properties.html * * @param proxyServer * @param request * @return true if we have to avoid proxy use (obeying non-proxy hosts settings), false otherwise. */ public static boolean avoidProxy(final ProxyServer proxyServer, final Request request) { return avoidProxy(proxyServer, URI.create(request.getUrl()).getHost()); } /** * Checks whether proxy should be used according to nonProxyHosts settings of it, or we want to go directly to * target host. If null proxy is passed in, this method returns true -- since there is NO proxy, we * should avoid to use it. Simple hostname pattern matching using "*" are supported, but only as prefixes. * See http://download.oracle.com/javase/1.4.2/docs/guide/net/properties.html * * @param proxyServer * @param target the hostname * @return true if we have to avoid proxy use (obeying non-proxy hosts settings), false otherwise. * */ public static boolean avoidProxy(final ProxyServer proxyServer, final String target) { if (proxyServer != null) { final String targetHost = target.toLowerCase(); List nonProxyHosts = proxyServer.getNonProxyHosts(); if (nonProxyHosts != null && nonProxyHosts.size() > 0) { for (String nonProxyHost : nonProxyHosts) { if (nonProxyHost.startsWith("*") && nonProxyHost.length() > 1 && targetHost.endsWith(nonProxyHost.substring(1).toLowerCase())) { return true; } else if (nonProxyHost.equalsIgnoreCase(targetHost)) { return true; } } } return false; } else { return true; } } /** * Creates a proxy server instance from the given properties. *

* Currently the default http.* proxy properties are supported as well as properties specific for AHC. * * @see http://download.oracle.com/javase/1.4.2/docs/guide/net/properties.html * @see #PROXY_HOST * @see #PROXY_PORT * @see #PROXY_PROTOCOL * @see #PROXY_NONPROXYHOSTS * * @param properties * the properties to evaluate. Must not be null. * @return a ProxyServer instance or null, if no valid properties were set. */ public static ProxyServer createProxy(Properties properties) { String host = System.getProperty(PROXY_HOST); if ( host != null ) { int port = Integer.valueOf(System.getProperty(PROXY_PORT, "80")); Protocol protocol; try { protocol = Protocol.valueOf(System.getProperty(PROXY_PROTOCOL, "HTTP")); } catch(IllegalArgumentException e) { protocol = Protocol.HTTP; } ProxyServer proxyServer = new ProxyServer(protocol, host, port, System.getProperty(PROXY_USER), System.getProperty(PROXY_PASSWORD)); String nonProxyHosts = System.getProperties().getProperty(PROXY_NONPROXYHOSTS); if (nonProxyHosts != null) { for (String spec : nonProxyHosts.split("\\|")) { proxyServer.addNonProxyHost(spec); } } return proxyServer; } return null; } } async-http-client-1.6.5/src/main/java/com/ning/http/util/SslUtils.java000066400000000000000000000142621166553056000256330ustar00rootroot00000000000000/* * Copyright 2010 Ning, Inc. * * Ning licenses this file to you 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. */ package com.ning.http.util; import javax.net.ssl.KeyManager; import javax.net.ssl.KeyManagerFactory; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLEngine; import javax.net.ssl.TrustManager; import javax.net.ssl.TrustManagerFactory; import javax.net.ssl.X509TrustManager; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.security.GeneralSecurityException; import java.security.KeyStore; import java.security.SecureRandom; import java.security.Security; /** * This class is a copy of http://github.com/sonatype/wagon-ning/raw/master/src/main/java/org/apache/maven/wagon/providers/http/SslUtils.java */ public class SslUtils { public static SSLEngine getSSLEngine() throws GeneralSecurityException, IOException { SSLEngine engine = null; SSLContext context = getSSLContext(); if (context != null) { engine = context.createSSLEngine(); engine.setUseClientMode(true); } return engine; } public static SSLContext getSSLContext() throws GeneralSecurityException, IOException { SSLConfig config = new SSLConfig(); if (config.keyStoreLocation == null || config.trustStoreLocation == null) { return getLooseSSLContext(); } else { return getStrictSSLContext(config); } } static SSLContext getStrictSSLContext(SSLConfig config) throws GeneralSecurityException, IOException { KeyStore keyStore = KeyStore.getInstance(config.keyStoreType); InputStream keystoreInputStream = new FileInputStream(config.keyStoreLocation); try { keyStore.load(keystoreInputStream, (config.keyStorePassword == null) ? null : config.keyStorePassword.toCharArray()); } finally { keystoreInputStream.close(); } KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(config.keyManagerAlgorithm); keyManagerFactory.init(keyStore, (config.keyManagerPassword == null) ? null : config.keyManagerPassword.toCharArray()); KeyManager[] keyManagers = keyManagerFactory.getKeyManagers(); KeyStore trustStore = KeyStore.getInstance(config.trustStoreType); InputStream truststoreInputStream = new FileInputStream(config.trustStoreLocation); try { trustStore.load(truststoreInputStream, (config.trustStorePassword == null) ? null : config.trustStorePassword.toCharArray()); } finally { truststoreInputStream.close(); } TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(config.trustManagerAlgorithm); trustManagerFactory.init(trustStore); TrustManager[] trustManagers = trustManagerFactory.getTrustManagers(); SSLContext context = SSLContext.getInstance("TLS"); context.init(keyManagers, trustManagers, null); return context; } static SSLContext getLooseSSLContext() throws GeneralSecurityException { SSLContext sslContext = SSLContext.getInstance("TLS"); sslContext.init(null, new TrustManager[]{LooseTrustManager.INSTANCE}, new SecureRandom()); return sslContext; } static class LooseTrustManager implements X509TrustManager { public static final LooseTrustManager INSTANCE = new LooseTrustManager(); public java.security.cert.X509Certificate[] getAcceptedIssuers() { return null; } public void checkClientTrusted(java.security.cert.X509Certificate[] certs, String authType) { } public void checkServerTrusted(java.security.cert.X509Certificate[] certs, String authType) { } } private final static class SSLConfig { public String keyStoreLocation; public String keyStoreType = "JKS"; public String keyStorePassword = "changeit"; public String keyManagerAlgorithm = "SunX509"; public String keyManagerPassword = "changeit"; public String trustStoreLocation; public String trustStoreType = "JKS"; public String trustStorePassword = "changeit"; public String trustManagerAlgorithm = "SunX509"; public SSLConfig() { keyStoreLocation = System.getProperty("javax.net.ssl.keyStore"); keyStorePassword = System.getProperty("javax.net.ssl.keyStorePassword", "changeit"); keyStoreType = System.getProperty("javax.net.ssl.keyStoreType", KeyStore.getDefaultType()); keyManagerAlgorithm = Security.getProperty("ssl.KeyManagerFactory.algorithm"); if (keyManagerAlgorithm == null){ keyManagerAlgorithm = "SunX509"; } keyManagerPassword = System.getProperty("javax.net.ssl.keyStorePassword", "changeit"); trustStoreLocation = System.getProperty("javax.net.ssl.trustStore"); if (trustStoreLocation == null) { trustStoreLocation = keyStoreLocation; trustStorePassword = keyStorePassword; trustStoreType = keyStoreType; } else { trustStorePassword = System.getProperty("javax.net.ssl.trustStorePassword", "changeit"); trustStoreType = System.getProperty("javax.net.ssl.trustStoreType", KeyStore.getDefaultType()); } trustManagerAlgorithm = Security.getProperty("ssl.TrustManagerFactory.algorithm"); if (trustManagerAlgorithm == null){ trustManagerAlgorithm = "SunX509"; } } } } async-http-client-1.6.5/src/main/java/com/ning/http/util/UTF8Codec.java000066400000000000000000000041221166553056000255270ustar00rootroot00000000000000/* * Copyright 2010 Ning, Inc. * * Ning licenses this file to you 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. */ package com.ning.http.util; import java.io.UnsupportedEncodingException; /** * Wrapper class for more convenient (and possibly more efficient in future) * UTF-8 encoding and decoding. */ public class UTF8Codec { private final static String ENCODING_UTF8 = "UTF-8"; // When we move to JDK 1.6+, we can do this: /* import java.nio.charset.Charset; private final static Charset utf8; static { utf8 = Charset.forName("UTF-8"); } public static byte[] toUTF8(String input) { return input.getBytes(utf8); } public static String fromUTF8(byte[] input) { return fromUTF8(input, 0, input.length); } public static String fromUTF8(byte[] input, int offset, int len) { return new String(input, offset, len, utf8); } */ // But until then (with 1.5) public static byte[] toUTF8(String input) { try { return input.getBytes(ENCODING_UTF8); } catch (UnsupportedEncodingException e) { // never happens, but since it's declared... throw new IllegalStateException(); } } public static String fromUTF8(byte[] input) { return fromUTF8(input, 0, input.length); } public static String fromUTF8(byte[] input, int offset, int len) { try { return new String(input, offset, len, ENCODING_UTF8); } catch (UnsupportedEncodingException e) { // never happens throw new IllegalStateException(); } } } async-http-client-1.6.5/src/main/java/com/ning/http/util/UTF8UrlEncoder.java000066400000000000000000000063311166553056000265600ustar00rootroot00000000000000/* * Copyright 2010 Ning, Inc. * * Ning licenses this file to you 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. */ package com.ning.http.util; /** * Convenience class that encapsulates details of "percent encoding" * (as per RFC-3986, see [http://www.ietf.org/rfc/rfc3986.txt]). */ public class UTF8UrlEncoder { private static final boolean encodeSpaceUsingPlus = System.getProperty("com.com.ning.http.util.UTF8UrlEncoder.encodeSpaceUsingPlus") == null ? false : true; /** * Encoding table used for figuring out ascii characters that must be escaped * (all non-Ascii characers need to be encoded anyway) */ private final static int[] SAFE_ASCII = new int[128]; static { for (int i = 'a'; i <= 'z'; ++i) { SAFE_ASCII[i] = 1; } for (int i = 'A'; i <= 'Z'; ++i) { SAFE_ASCII[i] = 1; } for (int i = '0'; i <= '9'; ++i) { SAFE_ASCII[i] = 1; } SAFE_ASCII['-'] = 1; SAFE_ASCII['.'] = 1; SAFE_ASCII['_'] = 1; SAFE_ASCII['~'] = 1; } private final static char[] HEX = "0123456789ABCDEF".toCharArray(); private UTF8UrlEncoder() { } public static String encode(String input) { StringBuilder sb = new StringBuilder(input.length() + 16); appendEncoded(sb, input); return sb.toString(); } public static StringBuilder appendEncoded(StringBuilder sb, String input) { final int[] safe = SAFE_ASCII; for (int i = 0, len = input.length(); i < len; ++i) { char c = input.charAt(i); if (c <= 127) { if (safe[c] != 0) { sb.append(c); } else { appendSingleByteEncoded(sb, c); } } else { appendMultiByteEncoded(sb, c); } } return sb; } private final static void appendSingleByteEncoded(StringBuilder sb, int value) { if (encodeSpaceUsingPlus && value == 32) { sb.append('+'); return; } sb.append('%'); sb.append(HEX[value >> 4]); sb.append(HEX[value & 0xF]); } private final static void appendMultiByteEncoded(StringBuilder sb, int value) { // two or three bytes? (ignoring surrogate pairs for now, which would yield 4 bytes) if (value < 0x800) { appendSingleByteEncoded(sb, (0xc0 | (value >> 6))); appendSingleByteEncoded(sb, (0x80 | (value & 0x3f))); } else { appendSingleByteEncoded(sb, (0xe0 | (value >> 12))); appendSingleByteEncoded(sb, (0x80 | ((value >> 6) & 0x3f))); appendSingleByteEncoded(sb, (0x80 | (value & 0x3f))); } } } async-http-client-1.6.5/src/test/000077500000000000000000000000001166553056000166465ustar00rootroot00000000000000async-http-client-1.6.5/src/test/java/000077500000000000000000000000001166553056000175675ustar00rootroot00000000000000async-http-client-1.6.5/src/test/java/com/000077500000000000000000000000001166553056000203455ustar00rootroot00000000000000async-http-client-1.6.5/src/test/java/com/ning/000077500000000000000000000000001166553056000213005ustar00rootroot00000000000000async-http-client-1.6.5/src/test/java/com/ning/http/000077500000000000000000000000001166553056000222575ustar00rootroot00000000000000async-http-client-1.6.5/src/test/java/com/ning/http/client/000077500000000000000000000000001166553056000235355ustar00rootroot00000000000000async-http-client-1.6.5/src/test/java/com/ning/http/client/RealmTest.java000066400000000000000000000035651166553056000263110ustar00rootroot00000000000000/* * Copyright (c) 2010-2011 Sonatype, Inc. All rights reserved. * * This program is licensed to you under the Apache License Version 2.0, * and you may not use this file except in compliance with the Apache License Version 2.0. * You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0. * * Unless required by applicable law or agreed to in writing, * software distributed under the Apache License Version 2.0 is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. */ package com.ning.http.client; import com.ning.http.client.Realm.AuthScheme; import com.ning.http.client.Realm.RealmBuilder; import org.testng.Assert; import org.testng.annotations.Test; public class RealmTest { @Test(groups = "fast") public void testClone() { RealmBuilder builder = new RealmBuilder(); builder.setPrincipal( "user" ).setPassword( "pass" ); builder.setEnconding( "enc" ).setUsePreemptiveAuth( true ); builder.setRealmName( "realm" ).setAlgorithm( "algo" ); builder.setScheme( AuthScheme.BASIC ); Realm orig = builder.build(); Realm clone = new RealmBuilder().clone( orig ).build(); Assert.assertEquals( clone.getPrincipal(), orig.getPrincipal() ); Assert.assertEquals( clone.getPassword(), orig.getPassword() ); Assert.assertEquals( clone.getEncoding(), orig.getEncoding() ); Assert.assertEquals( clone.getUsePreemptiveAuth(), orig.getUsePreemptiveAuth() ); Assert.assertEquals( clone.getRealmName(), orig.getRealmName() ); Assert.assertEquals( clone.getAlgorithm(), orig.getAlgorithm() ); Assert.assertEquals( clone.getAuthScheme(), orig.getAuthScheme() ); } } async-http-client-1.6.5/src/test/java/com/ning/http/client/async/000077500000000000000000000000001166553056000246525ustar00rootroot00000000000000async-http-client-1.6.5/src/test/java/com/ning/http/client/async/AbstractBasicTest.java000066400000000000000000000200541166553056000310630ustar00rootroot00000000000000/* * Copyright 2010 Ning, Inc. * * Ning licenses this file to you 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. */ package com.ning.http.client.async; import com.ning.http.client.AsyncCompletionHandler; import com.ning.http.client.AsyncHandler; import com.ning.http.client.AsyncHttpClient; import com.ning.http.client.AsyncHttpClientConfig; import com.ning.http.client.HttpResponseBodyPart; import com.ning.http.client.HttpResponseHeaders; import com.ning.http.client.HttpResponseStatus; import com.ning.http.client.Response; 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.slf4j.Logger; import org.slf4j.LoggerFactory; import org.testng.Assert; import org.testng.annotations.AfterClass; import org.testng.annotations.BeforeClass; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.net.ServerSocket; import java.util.Enumeration; public abstract class AbstractBasicTest { protected final Logger log = LoggerFactory.getLogger(AbstractBasicTest.class); protected Server server; protected int port1; protected int port2; public final static int TIMEOUT = 30; public static class EchoHandler extends AbstractHandler { /* @Override */ public void handle(String pathInContext, Request request, HttpServletRequest httpRequest, HttpServletResponse httpResponse) throws IOException, ServletException { if (httpRequest.getHeader("X-HEAD") != null) { httpResponse.setContentLength(1); } if (httpRequest.getHeader("X-ISO") != null) { httpResponse.setContentType("text/html; charset=ISO-8859-1"); } else { httpResponse.setContentType("text/html; charset=utf-8"); } if (request.getMethod().equalsIgnoreCase("OPTIONS")) { httpResponse.addHeader("Allow","GET,HEAD,POST,OPTIONS,TRACE"); }; Enumeration e = httpRequest.getHeaderNames(); String param; while (e.hasMoreElements()) { param = e.nextElement().toString(); if (param.startsWith("LockThread")) { try { Thread.sleep(40 * 1000); } catch (InterruptedException ex) { } } if (param.startsWith("X-redirect")) { httpResponse.sendRedirect(httpRequest.getHeader("X-redirect")); return; } httpResponse.addHeader("X-" + param, httpRequest.getHeader(param)); } Enumeration i = httpRequest.getParameterNames(); StringBuilder requestBody = new StringBuilder(); while (i.hasMoreElements()) { param = i.nextElement().toString(); httpResponse.addHeader("X-" + param, httpRequest.getParameter(param)); requestBody.append(param); requestBody.append("_"); } String pathInfo = httpRequest.getPathInfo(); if (pathInfo != null) httpResponse.addHeader("X-pathInfo", pathInfo); String queryString = httpRequest.getQueryString(); if (queryString != null) httpResponse.addHeader("X-queryString", queryString); httpResponse.addHeader("X-KEEP-ALIVE", httpRequest.getRemoteAddr() + ":" + httpRequest.getRemotePort()); javax.servlet.http.Cookie[] cs = httpRequest.getCookies(); if (cs != null) { for (javax.servlet.http.Cookie c : cs) { httpResponse.addCookie(c); } } if (requestBody.length() > 0) { httpResponse.getOutputStream().write(requestBody.toString().getBytes()); } int size = 16384; if (httpRequest.getContentLength() > 0) { size = httpRequest.getContentLength(); } byte[] bytes = new byte[size]; if (bytes.length > 0) { int read = 0; while (read > -1) { read = httpRequest.getInputStream().read(bytes); if (read > 0) { httpResponse.getOutputStream().write(bytes, 0, read); } } } httpResponse.setStatus(200); httpResponse.getOutputStream().flush(); httpResponse.getOutputStream().close(); } } @AfterClass(alwaysRun = true) public void tearDownGlobal() throws Exception { server.stop(); } protected int findFreePort() throws IOException { ServerSocket socket = null; try { socket = new ServerSocket(0); return socket.getLocalPort(); } finally { if (socket != null) { socket.close(); } } } protected String getTargetUrl() { return String.format("http://127.0.0.1:%d/foo/test", port1); } protected String getTargetUrl2() { return String.format("https://127.0.0.1:%d/foo/test", port2); } public AbstractHandler configureHandler() throws Exception { return new EchoHandler(); } @BeforeClass(alwaysRun = true) public void setUpGlobal() throws Exception { server = new Server(); port1 = findFreePort(); port2 = findFreePort(); Connector listener = new SelectChannelConnector(); listener.setHost("127.0.0.1"); listener.setPort(port1); server.addConnector(listener); listener = new SelectChannelConnector(); listener.setHost("127.0.0.1"); listener.setPort(port2); server.addConnector(listener); server.setHandler(configureHandler()); server.start(); log.info("Local HTTP server started successfully"); } public static class AsyncCompletionHandlerAdapter extends AsyncCompletionHandler { public Runnable runnable; @Override public Response onCompleted(Response response) throws Exception { return response; } /* @Override */ public void onThrowable(Throwable t) { t.printStackTrace(); Assert.fail("Unexpected exception: " + t.getMessage(), t); } } public static class AsyncHandlerAdapter implements AsyncHandler { /* @Override */ public void onThrowable(Throwable t) { t.printStackTrace(); Assert.fail("Unexpected exception", t); } /* @Override */ public STATE onBodyPartReceived(final HttpResponseBodyPart content) throws Exception { return STATE.CONTINUE; } /* @Override */ public STATE onStatusReceived(final HttpResponseStatus responseStatus) throws Exception { return STATE.CONTINUE; } /* @Override */ public STATE onHeadersReceived(final HttpResponseHeaders headers) throws Exception { return STATE.CONTINUE; } /* @Override */ public String onCompleted() throws Exception { return ""; } } public abstract AsyncHttpClient getAsyncHttpClient(AsyncHttpClientConfig config); } async-http-client-1.6.5/src/test/java/com/ning/http/client/async/AsyncProvidersBasicTest.java000077500000000000000000001657261166553056000323160ustar00rootroot00000000000000/* * Copyright 2010 Ning, Inc. * * Ning licenses this file to you 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. */ package com.ning.http.client.async; import com.ning.http.client.AsyncCompletionHandler; import com.ning.http.client.AsyncHttpClient; import com.ning.http.client.AsyncHttpClientConfig; import com.ning.http.client.AsyncHttpClientConfig.Builder; import com.ning.http.client.AsyncHttpClientConfigBean; import com.ning.http.client.AsyncHttpProviderConfig; import com.ning.http.client.Cookie; import com.ning.http.client.FluentCaseInsensitiveStringsMap; import com.ning.http.client.MaxRedirectException; import com.ning.http.client.Part; import com.ning.http.client.ProxyServer; import com.ning.http.client.Request; import com.ning.http.client.RequestBuilder; import com.ning.http.client.Response; import com.ning.http.client.StringPart; import com.ning.http.client.providers.netty.NettyAsyncHttpProviderConfig; import org.testng.Assert; import org.testng.annotations.Test; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.OutputStream; import java.net.ConnectException; import java.net.HttpURLConnection; import java.net.URL; import java.nio.channels.UnresolvedAddressException; import java.util.Arrays; import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.concurrent.CancellationException; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutionException; import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicReference; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertNull; import static org.testng.Assert.assertTrue; import static org.testng.Assert.fail; public abstract class AsyncProvidersBasicTest extends AbstractBasicTest { private static final String UTF_8 = "text/html;charset=UTF-8"; @Test(groups = {"standalone", "default_provider", "async"}) public void asyncProviderEncodingTest() throws Throwable { AsyncHttpClient p = getAsyncHttpClient(new AsyncHttpClientConfig.Builder().build()); Request request = new RequestBuilder("GET").setUrl("http://foo.com/foo.html?q=+%20x").build(); String requestUrl = request.getUrl(); Assert.assertEquals(requestUrl, "http://foo.com/foo.html?q=%20%20x"); Future responseFuture = p.executeRequest(request, new AsyncCompletionHandler() { @Override public String onCompleted(Response response) throws Exception { return response.getUri().toString(); } /* @Override */ public void onThrowable(Throwable t) { t.printStackTrace(); Assert.fail("Unexpected exception: " + t.getMessage(), t); } }); String url = responseFuture.get(); Assert.assertEquals(url, "http://foo.com/foo.html?q=%20%20x"); p.close(); } @Test(groups = {"standalone", "default_provider", "async"}) public void asyncProviderEncodingTest2() throws Throwable { AsyncHttpClient p = getAsyncHttpClient(new AsyncHttpClientConfig.Builder().build()); Request request = new RequestBuilder("GET").setUrl("http://foo.com/foo.html") .addQueryParameter("q", "a b") .build(); Future responseFuture = p.executeRequest(request, new AsyncCompletionHandler() { @Override public String onCompleted(Response response) throws Exception { return response.getUri().toString(); } /* @Override */ public void onThrowable(Throwable t) { t.printStackTrace(); Assert.fail("Unexpected exception: " + t.getMessage(), t); } }); String url = responseFuture.get(); Assert.assertEquals(url, "http://foo.com/foo.html?q=a%20b"); p.close(); } @Test(groups = {"standalone", "default_provider", "async"}) public void emptyRequestURI() throws Throwable { AsyncHttpClient p = getAsyncHttpClient(new AsyncHttpClientConfig.Builder().build()); Request request = new RequestBuilder("GET").setUrl("http://foo.com") .build(); Future responseFuture = p.executeRequest(request, new AsyncCompletionHandler() { @Override public String onCompleted(Response response) throws Exception { return response.getUri().toString(); } /* @Override */ public void onThrowable(Throwable t) { t.printStackTrace(); Assert.fail("Unexpected exception: " + t.getMessage(), t); } }); String url = responseFuture.get(); Assert.assertEquals(url, "http://foo.com/"); p.close(); } @Test(groups = {"standalone", "default_provider", "async"}) public void asyncProviderContentLenghtGETTest() throws Throwable { AsyncHttpClient p = getAsyncHttpClient(new AsyncHttpClientConfig.Builder().build()); final CountDownLatch l = new CountDownLatch(1); URL url = new URL(getTargetUrl()); final HttpURLConnection connection = (HttpURLConnection) url.openConnection(); connection.connect(); Request request = new RequestBuilder("GET").setUrl(getTargetUrl()).build(); p.executeRequest(request, new AsyncCompletionHandlerAdapter() { @Override public Response onCompleted(Response response) throws Exception { try { assertEquals(response.getStatusCode(), 200); int contentLenght = -1; if (response.getHeader("content-length") != null) { contentLenght = Integer.valueOf(response.getHeader("content-length")); } int ct = connection.getContentLength(); assertEquals(contentLenght, ct); } finally { l.countDown(); } return response; } @Override public void onThrowable(Throwable t) { try { Assert.fail("Unexpected exception", t); } finally { l.countDown(); } } }).get(); if (!l.await(TIMEOUT, TimeUnit.SECONDS)) { Assert.fail("Timeout out"); } p.close(); } @Test(groups = {"standalone", "default_provider", "async"}) public void asyncContentTypeGETTest() throws Throwable { AsyncHttpClient p = getAsyncHttpClient(new AsyncHttpClientConfig.Builder().build()); final CountDownLatch l = new CountDownLatch(1); Request request = new RequestBuilder("GET").setUrl(getTargetUrl()).build(); p.executeRequest(request, new AsyncCompletionHandlerAdapter() { @Override public Response onCompleted(Response response) throws Exception { try { assertEquals(response.getStatusCode(), 200); assertEquals(response.getContentType(), UTF_8); } finally { l.countDown(); } return response; } }).get(); if (!l.await(TIMEOUT, TimeUnit.SECONDS)) { Assert.fail("Timeout out"); } p.close(); } @Test(groups = {"standalone", "default_provider", "async"}) public void asyncHeaderGETTest() throws Throwable { AsyncHttpClient n = getAsyncHttpClient(new AsyncHttpClientConfig.Builder().build()); final CountDownLatch l = new CountDownLatch(1); Request request = new RequestBuilder("GET").setUrl(getTargetUrl()).build(); n.executeRequest(request, new AsyncCompletionHandlerAdapter() { @Override public Response onCompleted(Response response) throws Exception { try { assertEquals(response.getStatusCode(), 200); assertEquals(response.getContentType(), UTF_8); } finally { l.countDown(); } return response; } }).get(); if (!l.await(TIMEOUT, TimeUnit.SECONDS)) { Assert.fail("Timeout out"); } n.close(); } @Test(groups = {"standalone", "default_provider", "async"}) public void asyncHeaderPOSTTest() throws Throwable { final CountDownLatch l = new CountDownLatch(1); AsyncHttpClient n = getAsyncHttpClient(new AsyncHttpClientConfig.Builder().build()); FluentCaseInsensitiveStringsMap h = new FluentCaseInsensitiveStringsMap(); h.add("Test1", "Test1"); h.add("Test2", "Test2"); h.add("Test3", "Test3"); h.add("Test4", "Test4"); h.add("Test5", "Test5"); Request request = new RequestBuilder("GET").setUrl(getTargetUrl()).setHeaders(h).build(); n.executeRequest(request, new AsyncCompletionHandlerAdapter() { @Override public Response onCompleted(Response response) throws Exception { try { System.out.println(">>>>> " + response.getStatusText()); assertEquals(response.getStatusCode(), 200); for (int i = 1; i < 5; i++) { assertEquals(response.getHeader("X-Test" + i), "Test" + i); } } finally { l.countDown(); } return response; } }).get(); if (!l.await(TIMEOUT, TimeUnit.SECONDS)) { Assert.fail("Timeout out"); } n.close(); } @Test(groups = {"standalone", "default_provider", "async"}) public void asyncParamPOSTTest() throws Throwable { AsyncHttpClient n = getAsyncHttpClient(new AsyncHttpClientConfig.Builder().build()); final CountDownLatch l = new CountDownLatch(1); FluentCaseInsensitiveStringsMap h = new FluentCaseInsensitiveStringsMap(); h.add("Content-Type", "application/x-www-form-urlencoded"); Map> m = new HashMap>(); for (int i = 0; i < 5; i++) { m.put("param_" + i, Arrays.asList("value_" + i)); } Request request = new RequestBuilder("POST").setUrl(getTargetUrl()).setHeaders(h).setParameters(m).build(); n.executeRequest(request, new AsyncCompletionHandlerAdapter() { @Override public Response onCompleted(Response response) throws Exception { try { assertEquals(response.getStatusCode(), 200); for (int i = 1; i < 5; i++) { System.out.println(">>>>> " + response.getHeader("X-param_" + i)); assertEquals(response.getHeader("X-param_" + i), "value_" + i); } } finally { l.countDown(); } return response; } }).get(); if (!l.await(TIMEOUT, TimeUnit.SECONDS)) { Assert.fail("Timeout out"); } n.close(); } @Test(groups = {"standalone", "default_provider", "async"}) public void asyncStatusHEADTest() throws Throwable { AsyncHttpClient n = getAsyncHttpClient(new AsyncHttpClientConfig.Builder().build()); final CountDownLatch l = new CountDownLatch(1); Request request = new RequestBuilder("HEAD").setUrl(getTargetUrl()).build(); Response response = n.executeRequest(request, new AsyncCompletionHandlerAdapter() { @Override public Response onCompleted(Response response) throws Exception { try { assertEquals(response.getStatusCode(), 200); } finally { l.countDown(); } return response; } }).get(); try { String s = response.getResponseBody(); Assert.assertEquals("",s); } catch (IllegalStateException ex) { fail(); } if (!l.await(TIMEOUT, TimeUnit.SECONDS)) { Assert.fail("Timeout out"); } n.close(); } // TODO: fix test @Test(groups = {"standalone", "default_provider", "async"}, enabled = false) public void asyncStatusHEADContentLenghtTest() throws Throwable { AsyncHttpClient n = getAsyncHttpClient(new AsyncHttpClientConfig.Builder() .setRequestTimeoutInMs(120 * 1000).build()); final CountDownLatch l = new CountDownLatch(1); Request request = new RequestBuilder("HEAD") .setUrl(getTargetUrl()) .build(); n.executeRequest(request, new AsyncCompletionHandlerAdapter() { @Override public Response onCompleted(Response response) throws Exception { Assert.fail(); return response; } @Override public void onThrowable(Throwable t) { try { assertEquals(t.getClass(), IOException.class); assertEquals(t.getMessage(), "No response received. Connection timed out"); } finally { l.countDown(); } } }).get(); if (!l.await(10 * 5 * 1000, TimeUnit.SECONDS)) { Assert.fail("Timeout out"); } n.close(); } @Test(groups = {"online", "default_provider", "async"}) public void asyncNullSchemeTest() throws Throwable { AsyncHttpClient c = getAsyncHttpClient(null); try { c.prepareGet("www.sun.com").execute(); Assert.fail(); } catch (IllegalArgumentException ex) { Assert.assertTrue(true); } c.close(); } @Test(groups = {"standalone", "default_provider", "async"}) public void asyncDoGetTransferEncodingTest() throws Throwable { AsyncHttpClient c = getAsyncHttpClient(new AsyncHttpClientConfig.Builder().build()); final CountDownLatch l = new CountDownLatch(1); c.prepareGet(getTargetUrl()).execute(new AsyncCompletionHandlerAdapter() { @Override public Response onCompleted(Response response) throws Exception { try { assertEquals(response.getStatusCode(), 200); assertEquals(response.getHeader("Transfer-Encoding"), "chunked"); } finally { l.countDown(); } return response; } }).get(); if (!l.await(TIMEOUT, TimeUnit.SECONDS)) { Assert.fail("Timeout out"); } c.close(); } @Test(groups = {"standalone", "default_provider", "async"}) public void asyncDoGetHeadersTest() throws Throwable { AsyncHttpClient c = getAsyncHttpClient(null); final CountDownLatch l = new CountDownLatch(1); FluentCaseInsensitiveStringsMap h = new FluentCaseInsensitiveStringsMap(); h.add("Test1", "Test1"); h.add("Test2", "Test2"); h.add("Test3", "Test3"); h.add("Test4", "Test4"); h.add("Test5", "Test5"); c.prepareGet(getTargetUrl()).setHeaders(h).execute(new AsyncCompletionHandlerAdapter() { @Override public Response onCompleted(Response response) throws Exception { try { assertEquals(response.getStatusCode(), 200); for (int i = 1; i < 5; i++) { assertEquals(response.getHeader("X-Test" + i), "Test" + i); } } finally { l.countDown(); } return response; } }).get(); if (!l.await(TIMEOUT, TimeUnit.SECONDS)) { Assert.fail("Timeout out"); } c.close(); } @Test(groups = {"standalone", "default_provider", "async"}) public void asyncDoGetCookieTest() throws Throwable { AsyncHttpClient c = getAsyncHttpClient(null); final CountDownLatch l = new CountDownLatch(1); FluentCaseInsensitiveStringsMap h = new FluentCaseInsensitiveStringsMap(); h.add("Test1", "Test1"); h.add("Test2", "Test2"); h.add("Test3", "Test3"); h.add("Test4", "Test4"); h.add("Test5", "Test5"); final Cookie coo = new Cookie("/", "foo", "value", "/", -1, false); c.prepareGet(getTargetUrl()).setHeaders(h).addCookie(coo).execute(new AsyncCompletionHandlerAdapter() { @Override public Response onCompleted(Response response) throws Exception { try { assertEquals(response.getStatusCode(), 200); List cookies = response.getCookies(); assertEquals(cookies.size(), 1); assertEquals(cookies.get(0).toString(), coo.toString()); } finally { l.countDown(); } return response; } }).get(); if (!l.await(TIMEOUT, TimeUnit.SECONDS)) { Assert.fail("Timeout out"); } c.close(); } @Test(groups = {"standalone", "default_provider", "async"}) public void asyncDoPostDefaultContentType() throws Throwable { AsyncHttpClient c = getAsyncHttpClient(null); final CountDownLatch l = new CountDownLatch(1); c.preparePost(getTargetUrl()).addParameter("foo", "bar").execute(new AsyncCompletionHandlerAdapter() { @Override public Response onCompleted(Response response) throws Exception { try { assertEquals(response.getStatusCode(), 200); FluentCaseInsensitiveStringsMap h = response.getHeaders(); assertEquals(h.getJoinedValue("X-Content-Type", ", "), "application/x-www-form-urlencoded"); } finally { l.countDown(); } return response; } }).get(); if (!l.await(TIMEOUT, TimeUnit.SECONDS)) { Assert.fail("Timeout out"); } c.close(); } @Test(groups = {"standalone", "default_provider", "async"}) public void asyncDoPostBodyIsoTest() throws Throwable { AsyncHttpClient c = getAsyncHttpClient(null); final CountDownLatch l = new CountDownLatch(1); Response r = c.preparePost(getTargetUrl()).addHeader("X-ISO", "true").setBody("ŽŽŽŽŽŽ").execute().get(); assertEquals(r.getResponseBody().getBytes("ISO-8859-1"),"ŽŽŽŽŽŽ".getBytes("ISO-8859-1")); c.close(); } @Test(groups = {"standalone", "default_provider", "async"}) public void asyncDoPostBytesTest() throws Throwable { AsyncHttpClient c = getAsyncHttpClient(null); final CountDownLatch l = new CountDownLatch(1); FluentCaseInsensitiveStringsMap h = new FluentCaseInsensitiveStringsMap(); h.add("Content-Type", "application/x-www-form-urlencoded"); StringBuilder sb = new StringBuilder(); for (int i = 0; i < 5; i++) { sb.append("param_"); sb.append(i); sb.append("=value_"); sb.append(i); sb.append("&"); } sb.deleteCharAt(sb.length() - 1); c.preparePost(getTargetUrl()).setHeaders(h).setBody(sb.toString()).execute(new AsyncCompletionHandlerAdapter() { @Override public Response onCompleted(Response response) throws Exception { try { assertEquals(response.getStatusCode(), 200); for (int i = 1; i < 5; i++) { System.out.println(">>>>> " + response.getHeader("X-param_" + i)); assertEquals(response.getHeader("X-param_" + i), "value_" + i); } } finally { l.countDown(); } return response; } }).get(); if (!l.await(TIMEOUT, TimeUnit.SECONDS)) { Assert.fail("Timeout out"); } c.close(); } @Test(groups = {"standalone", "default_provider", "async"}) public void asyncDoPostInputStreamTest() throws Throwable { AsyncHttpClient c = getAsyncHttpClient(null); final CountDownLatch l = new CountDownLatch(1); FluentCaseInsensitiveStringsMap h = new FluentCaseInsensitiveStringsMap(); h.add("Content-Type", "application/x-www-form-urlencoded"); StringBuilder sb = new StringBuilder(); for (int i = 0; i < 5; i++) { sb.append("param_"); sb.append(i); sb.append("=value_"); sb.append(i); sb.append("&"); } sb.deleteCharAt(sb.length() - 1); ByteArrayInputStream is = new ByteArrayInputStream(sb.toString().getBytes()); c.preparePost(getTargetUrl()).setHeaders(h).setBody(is).execute(new AsyncCompletionHandlerAdapter() { @Override public Response onCompleted(Response response) throws Exception { try { assertEquals(response.getStatusCode(), 200); for (int i = 1; i < 5; i++) { System.out.println(">>>>> " + response.getHeader("X-param_" + i)); assertEquals(response.getHeader("X-param_" + i), "value_" + i); } } finally { l.countDown(); } return response; } }).get(); if (!l.await(TIMEOUT, TimeUnit.SECONDS)) { Assert.fail("Timeout out"); } c.close(); } @Test(groups = {"standalone", "default_provider", "async"}) public void asyncDoPutInputStreamTest() throws Throwable { AsyncHttpClient c = getAsyncHttpClient(null); final CountDownLatch l = new CountDownLatch(1); FluentCaseInsensitiveStringsMap h = new FluentCaseInsensitiveStringsMap(); h.add("Content-Type", "application/x-www-form-urlencoded"); StringBuilder sb = new StringBuilder(); for (int i = 0; i < 5; i++) { sb.append("param_"); sb.append(i); sb.append("=value_"); sb.append(i); sb.append("&"); } sb.deleteCharAt(sb.length() - 1); ByteArrayInputStream is = new ByteArrayInputStream(sb.toString().getBytes()); c.preparePut(getTargetUrl()).setHeaders(h).setBody(is).execute(new AsyncCompletionHandlerAdapter() { @Override public Response onCompleted(Response response) throws Exception { try { assertEquals(response.getStatusCode(), 200); for (int i = 1; i < 5; i++) { System.out.println(">>>>> " + response.getHeader("X-param_" + i)); assertEquals(response.getHeader("X-param_" + i), "value_" + i); } } finally { l.countDown(); } return response; } }).get(); if (!l.await(TIMEOUT, TimeUnit.SECONDS)) { Assert.fail("Timeout out"); } c.close(); } @Test(groups = {"standalone", "default_provider", "async"}) public void asyncDoPostEntityWriterTest() throws Throwable { AsyncHttpClient c = getAsyncHttpClient(null); final CountDownLatch l = new CountDownLatch(1); FluentCaseInsensitiveStringsMap h = new FluentCaseInsensitiveStringsMap(); h.add("Content-Type", "application/x-www-form-urlencoded"); final StringBuilder sb = new StringBuilder(); for (int i = 0; i < 5; i++) { sb.append("param_"); sb.append(i); sb.append("=value_"); sb.append(i); sb.append("&"); } sb.deleteCharAt(sb.length() - 1); byte[] bytes = sb.toString().getBytes(); h.add("Content-Length", String.valueOf(bytes.length)); c.preparePost(getTargetUrl()).setHeaders(h).setBody(new Request.EntityWriter() { /* @Override */ public void writeEntity(OutputStream out) throws IOException { out.write(sb.toString().getBytes("UTF-8")); } }).execute(new AsyncCompletionHandlerAdapter() { @Override public Response onCompleted(Response response) throws Exception { try { assertEquals(response.getStatusCode(), 200); for (int i = 1; i < 5; i++) { System.out.println(">>>>> " + response.getHeader("X-param_" + i)); assertEquals(response.getHeader("X-param_" + i), "value_" + i); } } finally { l.countDown(); } return response; } }).get(); if (!l.await(TIMEOUT, TimeUnit.SECONDS)) { Assert.fail("Timeout out"); } c.close(); } @Test(groups = {"standalone", "default_provider", "async"}) public void asyncDoPostMultiPartTest() throws Throwable { AsyncHttpClient c = getAsyncHttpClient(null); final CountDownLatch l = new CountDownLatch(1); Part p = new StringPart("foo", "bar"); c.preparePost(getTargetUrl()).addBodyPart(p).execute(new AsyncCompletionHandlerAdapter() { @Override public Response onCompleted(Response response) throws Exception { try { String xContentType = response.getHeader("X-Content-Type"); String boundary = xContentType.substring( (xContentType.indexOf("boundary") + "boundary".length() + 1)); String s = response.getResponseBodyExcerpt(boundary.length() + "--".length()).substring("--".length()); assertEquals(boundary, s); } finally { l.countDown(); } return response; } }).get(); if (!l.await(TIMEOUT, TimeUnit.SECONDS)) { Assert.fail("Timeout out"); } c.close(); } @Test(groups = {"standalone", "default_provider", "async"}) public void asyncDoPostBasicGZIPTest() throws Throwable { AsyncHttpClientConfig cf = new AsyncHttpClientConfig.Builder().setCompressionEnabled(true).build(); AsyncHttpClient c = getAsyncHttpClient(cf); final CountDownLatch l = new CountDownLatch(1); FluentCaseInsensitiveStringsMap h = new FluentCaseInsensitiveStringsMap(); h.add("Content-Type", "application/x-www-form-urlencoded"); StringBuilder sb = new StringBuilder(); for (int i = 0; i < 5; i++) { sb.append("param_"); sb.append(i); sb.append("=value_"); sb.append(i); sb.append("&"); } sb.deleteCharAt(sb.length() - 1); c.preparePost(getTargetUrl()).setHeaders(h).setBody(sb.toString()).execute(new AsyncCompletionHandlerAdapter() { @Override public Response onCompleted(Response response) throws Exception { try { assertEquals(response.getStatusCode(), 200); assertEquals(response.getHeader("X-Accept-Encoding"), "gzip"); } finally { l.countDown(); } return response; } }).get(); if (!l.await(TIMEOUT, TimeUnit.SECONDS)) { Assert.fail("Timeout out"); } c.close(); } @Test(groups = {"standalone", "default_provider", "async"}) public void asyncDoPostProxyTest() throws Throwable { AsyncHttpClientConfig cf = new AsyncHttpClientConfig.Builder().setProxyServer(new ProxyServer("127.0.0.1", port2)).build(); AsyncHttpClient c = getAsyncHttpClient(cf); FluentCaseInsensitiveStringsMap h = new FluentCaseInsensitiveStringsMap(); h.add("Content-Type", "application/x-www-form-urlencoded"); StringBuilder sb = new StringBuilder(); for (int i = 0; i < 5; i++) { sb.append("param_"); sb.append(i); sb.append("=value_"); sb.append(i); sb.append("&"); } sb.deleteCharAt(sb.length() - 1); Response response = c.preparePost(getTargetUrl()).setHeaders(h).setBody(sb.toString()).execute(new AsyncCompletionHandler() { @Override public Response onCompleted(Response response) throws Exception { return response; } @Override public void onThrowable(Throwable t) { } }).get(); assertEquals(response.getStatusCode(), 200); assertEquals(response.getHeader("X-Proxy-Connection"), "keep-alive"); c.close(); } @Test(groups = {"standalone", "default_provider", "async"}) public void asyncRequestVirtualServerPOSTTest() throws Throwable { AsyncHttpClient n = getAsyncHttpClient(new AsyncHttpClientConfig.Builder().build()); FluentCaseInsensitiveStringsMap h = new FluentCaseInsensitiveStringsMap(); h.add("Content-Type", "application/x-www-form-urlencoded"); Map> m = new HashMap>(); for (int i = 0; i < 5; i++) { m.put("param_" + i, Arrays.asList("value_" + i)); } Request request = new RequestBuilder("POST") .setUrl(getTargetUrl()) .setHeaders(h) .setParameters(m) .setVirtualHost("localhost:" + port1) .build(); Response response = n.executeRequest(request, new AsyncCompletionHandlerAdapter()).get(); assertEquals(response.getStatusCode(), 200); if (response.getHeader("X-Host").startsWith("localhost")) { assertEquals(response.getHeader("X-Host"), "localhost:" + port1); } else { assertEquals(response.getHeader("X-Host"), "127.0.0.1:" + port1); } n.close(); } @Test(groups = {"standalone", "default_provider", "async"}) public void asyncDoPutTest() throws Throwable { AsyncHttpClient c = getAsyncHttpClient(null); FluentCaseInsensitiveStringsMap h = new FluentCaseInsensitiveStringsMap(); h.add("Content-Type", "application/x-www-form-urlencoded"); StringBuilder sb = new StringBuilder(); for (int i = 0; i < 5; i++) { sb.append("param_"); sb.append(i); sb.append("=value_"); sb.append(i); sb.append("&"); } sb.deleteCharAt(sb.length() - 1); Response response = c.preparePut(getTargetUrl()).setHeaders(h).setBody(sb.toString()).execute(new AsyncCompletionHandlerAdapter()).get(); assertEquals(response.getStatusCode(), 200); c.close(); } @Test(groups = {"standalone", "default_provider", "async"}) public void asyncDoPostLatchBytesTest() throws Throwable { AsyncHttpClient c = getAsyncHttpClient(null); final CountDownLatch l = new CountDownLatch(1); FluentCaseInsensitiveStringsMap h = new FluentCaseInsensitiveStringsMap(); h.add("Content-Type", "application/x-www-form-urlencoded"); StringBuilder sb = new StringBuilder(); for (int i = 0; i < 5; i++) { sb.append("param_"); sb.append(i); sb.append("=value_"); sb.append(i); sb.append("&"); } sb.deleteCharAt(sb.length() - 1); c.preparePost(getTargetUrl()).setHeaders(h).setBody(sb.toString()).execute(new AsyncCompletionHandlerAdapter() { @Override public Response onCompleted(Response response) throws Exception { try { assertEquals(response.getStatusCode(), 200); for (int i = 1; i < 5; i++) { System.out.println(">>>>> " + response.getHeader("X-param_" + i)); assertEquals(response.getHeader("X-param_" + i), "value_" + i); } return response; } finally { l.countDown(); } } }); if (!l.await(TIMEOUT, TimeUnit.SECONDS)) { Assert.fail("Timeout out"); } c.close(); } @Test(groups = {"standalone", "default_provider", "async"}) public void asyncDoPostDelayCancelTest() throws Throwable { AsyncHttpClient c = getAsyncHttpClient(null); FluentCaseInsensitiveStringsMap h = new FluentCaseInsensitiveStringsMap(); h.add("Content-Type", "application/x-www-form-urlencoded"); h.add("LockThread", "true"); StringBuilder sb = new StringBuilder(); sb.append("LockThread=true"); Future future = c.preparePost(getTargetUrl()).setHeaders(h).setBody(sb.toString()).execute(new AsyncCompletionHandlerAdapter(){ @Override public void onThrowable(Throwable t) { } }); future.cancel(true); Response response = future.get(TIMEOUT, TimeUnit.SECONDS); Assert.assertNull(response); c.close(); } @Test(groups = {"standalone", "default_provider", "async"}) public void asyncDoPostDelayBytesTest() throws Throwable { AsyncHttpClient c = getAsyncHttpClient(null); FluentCaseInsensitiveStringsMap h = new FluentCaseInsensitiveStringsMap(); h.add("Content-Type", "application/x-www-form-urlencoded"); h.add("LockThread", "true"); StringBuilder sb = new StringBuilder(); sb.append("LockThread=true"); try { Future future = c.preparePost(getTargetUrl()).setHeaders(h).setBody(sb.toString()).execute(new AsyncCompletionHandlerAdapter() { @Override public void onThrowable(Throwable t) { t.printStackTrace(); } }); future.get(10, TimeUnit.SECONDS); } catch (ExecutionException ex) { if (ex.getCause() != null && TimeoutException.class.isAssignableFrom(ex.getCause().getClass())) { Assert.assertTrue(true); } } catch (TimeoutException te) { Assert.assertTrue(true); } catch (IllegalStateException ex) { Assert.assertTrue(false); } c.close(); } @Test(groups = {"standalone", "default_provider", "async"}) public void asyncDoPostNullBytesTest() throws Throwable { AsyncHttpClient c = getAsyncHttpClient(null); FluentCaseInsensitiveStringsMap h = new FluentCaseInsensitiveStringsMap(); h.add("Content-Type", "application/x-www-form-urlencoded"); StringBuilder sb = new StringBuilder(); for (int i = 0; i < 5; i++) { sb.append("param_"); sb.append(i); sb.append("=value_"); sb.append(i); sb.append("&"); } sb.deleteCharAt(sb.length() - 1); Future future = c.preparePost(getTargetUrl()).setHeaders(h).setBody(sb.toString()).execute(new AsyncCompletionHandlerAdapter()); Response response = future.get(); Assert.assertNotNull(response); assertEquals(response.getStatusCode(), 200); c.close(); } @Test(groups = {"standalone", "default_provider", "async"}) public void asyncDoPostListenerBytesTest() throws Throwable { AsyncHttpClient c = getAsyncHttpClient(null); FluentCaseInsensitiveStringsMap h = new FluentCaseInsensitiveStringsMap(); h.add("Content-Type", "application/x-www-form-urlencoded"); StringBuilder sb = new StringBuilder(); for (int i = 0; i < 5; i++) { sb.append("param_"); sb.append(i); sb.append("=value_"); sb.append(i); sb.append("&"); } sb.deleteCharAt(sb.length() - 1); final CountDownLatch l = new CountDownLatch(1); c.preparePost(getTargetUrl()).setHeaders(h).setBody(sb.toString()).execute(new AsyncCompletionHandlerAdapter() { @Override public Response onCompleted(Response response) throws Exception { try { assertEquals(response.getStatusCode(), 200); } finally { l.countDown(); } return response; } }); if (!l.await(TIMEOUT, TimeUnit.SECONDS)) { Assert.fail("Latch time out"); } c.close(); } @Test(groups = {"standalone", "default_provider", "async"}) public void asyncConnectInvalidFuture() throws Throwable { int dummyPort = findFreePort(); AsyncHttpClient c = getAsyncHttpClient(null); final AtomicInteger count = new AtomicInteger(); for (int i = 0; i < 20; i++) { try { Response response = c.preparePost(String.format("http://127.0.0.1:%d/", dummyPort)).execute(new AsyncCompletionHandlerAdapter() { /* @Override */ public void onThrowable(Throwable t) { count.incrementAndGet(); } }).get(); assertNull(response, "Should have thrown ExecutionException"); } catch (ExecutionException ex) { Throwable cause = ex.getCause(); if (!(cause instanceof ConnectException)) { fail("Should have been caused by ConnectException, not by " + cause.getClass().getName()); } } } assertEquals(count.get(), 20); c.close(); } @Test(groups = {"standalone", "default_provider", "async"}) public void asyncConnectInvalidPortFuture() throws Throwable { int dummyPort = findFreePort(); AsyncHttpClient c = getAsyncHttpClient(null); try { Response response = c.preparePost(String.format("http://127.0.0.1:%d/", dummyPort)).execute(new AsyncCompletionHandlerAdapter() { /* @Override */ public void onThrowable(Throwable t) { t.printStackTrace(); } }).get(); assertNull(response, "Should have thrown ExecutionException"); } catch (ExecutionException ex) { Throwable cause = ex.getCause(); if (!(cause instanceof ConnectException)) { fail("Should have been caused by ConnectException, not by " + cause.getClass().getName()); } } c.close(); } @Test(groups = {"standalone", "default_provider", "async"}) public void asyncConnectInvalidPort() throws Throwable { AsyncHttpClient c = getAsyncHttpClient(null); // pick a random unused local port int port = findFreePort(); try { Response response = c.preparePost(String.format("http://127.0.0.1:%d/", port)).execute(new AsyncCompletionHandlerAdapter() { /* @Override */ public void onThrowable(Throwable t) { t.printStackTrace(); } }).get(); assertNull(response, "No ExecutionException was thrown"); } catch (ExecutionException ex) { assertEquals(ex.getCause().getClass(), ConnectException.class); } c.close(); } @Test(groups = {"standalone", "default_provider", "async"}) public void asyncConnectInvalidHandlerPort() throws Throwable { AsyncHttpClient c = getAsyncHttpClient(null); final CountDownLatch l = new CountDownLatch(1); int port = findFreePort(); c.prepareGet(String.format("http://127.0.0.1:%d/", port)).execute(new AsyncCompletionHandlerAdapter() { /* @Override */ public void onThrowable(Throwable t) { try { assertEquals(t.getClass(), ConnectException.class); } finally { l.countDown(); } } }); if (!l.await(TIMEOUT, TimeUnit.SECONDS)) { Assert.fail("Timed out"); } c.close(); } @Test(groups = {"online", "default_provider", "async"}) public void asyncConnectInvalidHandlerHost() throws Throwable { AsyncHttpClient c = getAsyncHttpClient(null); final CountDownLatch l = new CountDownLatch(1); c.prepareGet("http://null.apache.org:9999/").execute(new AsyncCompletionHandlerAdapter() { /* @Override */ public void onThrowable(Throwable t) { if (t != null) { if (t.getClass().equals(ConnectException.class)) { l.countDown(); } else if (t.getClass().equals(UnresolvedAddressException.class)) { l.countDown(); } } } }); if (!l.await(TIMEOUT, TimeUnit.SECONDS)) { Assert.fail("Timed out"); } c.close(); } @Test(groups = {"standalone", "default_provider", "async"}) public void asyncConnectInvalidFuturePort() throws Throwable { AsyncHttpClient c = getAsyncHttpClient(null); final AtomicBoolean called = new AtomicBoolean(false); final AtomicBoolean rightCause = new AtomicBoolean(false); // pick a random unused local port int port = findFreePort(); try { Response response = c.prepareGet(String.format("http://127.0.0.1:%d/", port)).execute(new AsyncCompletionHandlerAdapter() { @Override public void onThrowable(Throwable t) { called.set(true); if (t instanceof ConnectException) { rightCause.set(true); } } }).get(); assertNull(response, "No ExecutionException was thrown"); } catch (ExecutionException ex) { assertEquals(ex.getCause().getClass(), ConnectException.class); } assertTrue(called.get(), "onThrowable should get called."); assertTrue(rightCause.get(), "onThrowable should get called with ConnectionException"); c.close(); } @Test(groups = {"standalone", "default_provider", "async"}) public void asyncContentLenghtGETTest() throws Throwable { AsyncHttpClient c = getAsyncHttpClient(null); Response response = c.prepareGet(getTargetUrl()).execute(new AsyncCompletionHandlerAdapter() { @Override public void onThrowable(Throwable t) { Assert.fail("Unexpected exception", t); } }).get(); Assert.assertNotNull(response); assertEquals(response.getStatusCode(), 200); c.close(); } @Test(groups = {"standalone", "default_provider", "async"}) public void asyncResponseBodyTooLarge() throws Throwable { AsyncHttpClient c = getAsyncHttpClient(null); Response response = c.preparePost(getTargetUrl()).setBody("0123456789").execute(new AsyncCompletionHandlerAdapter() { @Override public void onThrowable(Throwable t) { Assert.fail("Unexpected exception", t); } }).get(); Assert.assertNotNull(response.getResponseBodyExcerpt(Integer.MAX_VALUE)); c.close(); } @Test(groups = {"standalone", "default_provider", "async"}) public void asyncResponseEmptyBody() throws Throwable { AsyncHttpClient c = getAsyncHttpClient(null); Response response = c.prepareGet(getTargetUrl()).execute(new AsyncCompletionHandlerAdapter() { @Override public void onThrowable(Throwable t) { Assert.fail("Unexpected exception", t); } }).get(); assertEquals(response.getResponseBody(),""); c.close(); } @Test(groups = {"standalone", "default_provider", "asyncAPI"}) public void asyncAPIContentLenghtGETTest() throws Throwable { AsyncHttpClient client = getAsyncHttpClient(null); // Use a l in case the assert fail final CountDownLatch l = new CountDownLatch(1); client.prepareGet(getTargetUrl()).execute(new AsyncCompletionHandlerAdapter() { @Override public Response onCompleted(Response response) throws Exception { try { assertEquals(response.getStatusCode(), 200); } finally { l.countDown(); } return response; } @Override public void onThrowable(Throwable t) { } }); if (!l.await(TIMEOUT, TimeUnit.SECONDS)) { Assert.fail("Timed out"); } client.close(); } @Test(groups = {"standalone", "default_provider", "asyncAPI"}) public void asyncAPIHandlerExceptionTest() throws Throwable { AsyncHttpClient client = getAsyncHttpClient(null); // Use a l in case the assert fail final CountDownLatch l = new CountDownLatch(1); client.prepareGet(getTargetUrl()).execute(new AsyncCompletionHandlerAdapter() { @Override public Response onCompleted(Response response) throws Exception { throw new IllegalStateException("FOO"); } @Override public void onThrowable(Throwable t) { try { if (t.getMessage() != null) { assertEquals(t.getMessage(), "FOO"); } } finally { l.countDown(); } } }); if (!l.await(TIMEOUT, TimeUnit.SECONDS)) { Assert.fail("Timed out"); } client.close(); } @Test(groups = {"standalone", "default_provider", "async"}) public void asyncDoGetDelayHandlerTest() throws Throwable { FluentCaseInsensitiveStringsMap h = new FluentCaseInsensitiveStringsMap(); h.add("LockThread", "true"); AsyncHttpClient client = getAsyncHttpClient(new AsyncHttpClientConfig.Builder().setRequestTimeoutInMs(5 * 1000).build()); // Use a l in case the assert fail final CountDownLatch l = new CountDownLatch(1); client.prepareGet(getTargetUrl()).setHeaders(h).execute(new AsyncCompletionHandlerAdapter() { @Override public Response onCompleted(Response response) throws Exception { try { Assert.fail("Must not receive a response"); } finally { l.countDown(); } return response; } @Override public void onThrowable(Throwable t) { try { if (t instanceof TimeoutException) { Assert.assertTrue(true); } else { Assert.fail("Unexpected exception", t); } } finally { l.countDown(); } } }); if (!l.await(TIMEOUT, TimeUnit.SECONDS)) { Assert.fail("Timed out"); } client.close(); } @Test(groups = {"standalone", "default_provider", "async"}) public void asyncDoGetQueryStringTest() throws Throwable { AsyncHttpClient client = getAsyncHttpClient(null); // Use a l in case the assert fail final CountDownLatch l = new CountDownLatch(1); AsyncCompletionHandler handler = new AsyncCompletionHandlerAdapter() { @Override public Response onCompleted(Response response) throws Exception { try { Assert.assertTrue(response.getHeader("X-pathInfo") != null); Assert.assertTrue(response.getHeader("X-queryString") != null); } finally { l.countDown(); } return response; } }; Request req = new RequestBuilder("GET") .setUrl(getTargetUrl() + "?foo=bar").build(); client.executeRequest(req, handler).get(); if (!l.await(TIMEOUT, TimeUnit.SECONDS)) { Assert.fail("Timed out"); } client.close(); } @Test(groups = {"standalone", "default_provider", "async"}) public void asyncDoGetKeepAliveHandlerTest() throws Throwable { AsyncHttpClient client = getAsyncHttpClient(null); // Use a l in case the assert fail final CountDownLatch l = new CountDownLatch(2); AsyncCompletionHandler handler = new AsyncCompletionHandlerAdapter() { String remoteAddr = null; @Override public Response onCompleted(Response response) throws Exception { assertEquals(response.getStatusCode(), 200); if (remoteAddr == null) { remoteAddr = response.getHeader("X-KEEP-ALIVE"); l.countDown(); } else { assertEquals(response.getHeader("X-KEEP-ALIVE"), remoteAddr); l.countDown(); } return response; } }; client.prepareGet(getTargetUrl()).execute(handler).get(); client.prepareGet(getTargetUrl()).execute(handler); if (!l.await(TIMEOUT, TimeUnit.SECONDS)) { Assert.fail("Timed out"); } client.close(); } @Test(groups = {"online", "default_provider", "async"}) public void asyncDoGetMaxRedirectTest() throws Throwable { AsyncHttpClient client = getAsyncHttpClient(new Builder().setMaximumNumberOfRedirects(0).setFollowRedirects(true).build()); // Use a l in case the assert fail final CountDownLatch l = new CountDownLatch(1); AsyncCompletionHandler handler = new AsyncCompletionHandlerAdapter() { @Override public Response onCompleted(Response response) throws Exception { Assert.fail("Should not be here"); return response; } @Override public void onThrowable(Throwable t) { t.printStackTrace(); try { assertEquals(t.getClass(), MaxRedirectException.class); } finally { l.countDown(); } } }; client.prepareGet("http://google.com/").execute(handler); if (!l.await(TIMEOUT, TimeUnit.SECONDS)) { Assert.fail("Timed out"); } client.close(); } @Test(groups = {"online", "default_provider", "async"}) public void asyncDoGetNestedTest() throws Throwable { AsyncHttpProviderConfig pc = new NettyAsyncHttpProviderConfig(); final AsyncHttpClient client = getAsyncHttpClient(new Builder().setAsyncHttpClientProviderConfig(pc).build()); // Use a l in case the assert fail final CountDownLatch l = new CountDownLatch(2); final AsyncCompletionHandlerAdapter handler = new AsyncCompletionHandlerAdapter() { private final static int MAX_NESTED = 2; private AtomicInteger nestedCount = new AtomicInteger(0); @Override public Response onCompleted(Response response) throws Exception { try { if (nestedCount.getAndIncrement() < MAX_NESTED) { System.out.println("Executing a nested request: " + nestedCount); client.prepareGet("http://google.com/").execute(this); } } finally { l.countDown(); } return response; } @Override public void onThrowable(Throwable t) { t.printStackTrace(); } }; client.prepareGet("http://www.google.com/").execute(handler); if (!l.await(TIMEOUT, TimeUnit.SECONDS)) { Assert.fail("Timed out"); } client.close(); } @Test(groups = {"online", "default_provider", "async"}) public void asyncDoGetStreamAndBodyTest() throws Throwable { final AsyncHttpClient client = getAsyncHttpClient(new Builder().build()); Response r = client.prepareGet("http://www.google.com/").execute().get(); r.getResponseBody(); r.getResponseBodyAsStream(); client.close(); } @Test(groups = {"online", "default_provider", "async"}) public void asyncUrlWithoutPathTest() throws Throwable { final AsyncHttpClient client = getAsyncHttpClient(new Builder().build()); Response r = client.prepareGet("http://www.google.com").execute().get(); r.getResponseBody(); r.getResponseBodyAsStream(); client.close(); } @Test(groups = {"default_provider", "async"}) public void optionsTest() throws Throwable { final AsyncHttpClient client = getAsyncHttpClient(new Builder().build()); Response r = client.prepareOptions(getTargetUrl()).execute().get(); assertEquals(r.getStatusCode(), 200); assertEquals(r.getHeader("Allow"), "GET,HEAD,POST,OPTIONS,TRACE"); client.close(); } @Test(groups = {"online", "default_provider"}) public void testAwsS3() throws Exception { final AsyncHttpClient c = getAsyncHttpClient(new Builder().build()); Response response = c.prepareGet("http://test.s3.amazonaws.com/").execute().get(); if (response.getResponseBody() == null || response.getResponseBody().equals("")) { fail("No response Body"); } else { assertEquals(response.getStatusCode(), 403); } c.close(); } // TODO Netty only @Test(groups = {"online", "default_provider"}) public void testAsyncHttpProviderConfig() throws Exception { NettyAsyncHttpProviderConfig pc = new NettyAsyncHttpProviderConfig(); pc.addProperty("tcpNoDelay", true); // Just make sure Netty still works. final AsyncHttpClient c = getAsyncHttpClient(new Builder().setAsyncHttpClientProviderConfig(pc).build()); Response response = c.prepareGet("http://test.s3.amazonaws.com/").execute().get(); if (response.getResponseBody() == null || response.getResponseBody().equals("")) { fail("No response Body"); } else { assertEquals(response.getStatusCode(), 403); } c.close(); } @Test(groups = {"standalone", "default_provider"}) public void idleRequestTimeoutTest() throws Exception { AsyncHttpClient c = getAsyncHttpClient( new AsyncHttpClientConfig.Builder().setIdleConnectionInPoolTimeoutInMs(5000).setRequestTimeoutInMs(10000).build()); FluentCaseInsensitiveStringsMap h = new FluentCaseInsensitiveStringsMap(); h.add("Content-Type", "application/x-www-form-urlencoded"); h.add("LockThread", "true"); long t1 = System.currentTimeMillis(); try { c.prepareGet(getTargetUrl()).setHeaders(h).setUrl(getTargetUrl()).execute(new AsyncHandlerAdapter() { /* @Override */ public void onThrowable(Throwable t) { // t.printStackTrace(); } }).get(); Assert.fail(); } catch (Throwable ex) { final long elapsedTime = System.currentTimeMillis() - t1; System.out.println("EXPIRED: " + (elapsedTime)); Assert.assertNotNull(ex.getCause()); Assert.assertTrue(elapsedTime >= 10000 && elapsedTime <= 25000); } c.close(); } @Test(groups = {"standalone", "default_provider", "async"}) public void asyncDoPostCancelTest() throws Throwable { AsyncHttpClient c = getAsyncHttpClient(null); FluentCaseInsensitiveStringsMap h = new FluentCaseInsensitiveStringsMap(); h.add("Content-Type", "application/x-www-form-urlencoded"); h.add("LockThread", "true"); StringBuilder sb = new StringBuilder(); sb.append("LockThread=true"); final AtomicReference ex = new AtomicReference(); ex.set(null); try { Future future = c.preparePost(getTargetUrl()).setHeaders(h).setBody(sb.toString()).execute(new AsyncCompletionHandlerAdapter() { @Override public void onThrowable(Throwable t) { if (t instanceof CancellationException) { ex.set((CancellationException)t); } t.printStackTrace(); } }); future.cancel(true); } catch (IllegalStateException ise) { fail(); } Assert.assertNotNull(ex.get()); c.close(); } @Test(groups = {"standalone", "default_provider"}, expectedExceptions = IllegalArgumentException.class) public void getShouldNotAllowBody() throws IllegalArgumentException, IOException { AsyncHttpClient c = getAsyncHttpClient(null); AsyncHttpClient.BoundRequestBuilder builder = c.prepareGet(getTargetUrl()); builder.setBody("Boo!"); builder.execute(); } @Test(groups = {"standalone", "default_provider"}, expectedExceptions = IllegalArgumentException.class) public void headShouldNotAllowBody() throws IllegalArgumentException, IOException { AsyncHttpClient c = getAsyncHttpClient(null); AsyncHttpClient.BoundRequestBuilder builder = c.prepareHead(getTargetUrl()); builder.setBody("Boo!"); builder.execute(); } protected String getBrokenTargetUrl() { return String.format("http:127.0.0.1:%d/foo/test", port1); } @Test(groups = {"standalone", "default_provider"}) public void invalidUri() throws Exception { AsyncHttpClient c = getAsyncHttpClient(null); AsyncHttpClient.BoundRequestBuilder builder = c.prepareGet(getBrokenTargetUrl()); Response r = c.executeRequest(builder.build()).get(); assertEquals(200, r.getStatusCode()); } @Test(groups = {"standalone", "default_provider"}) public void asyncHttpClientConfigBeanTest() throws Exception { AsyncHttpClient c = getAsyncHttpClient(new AsyncHttpClientConfigBean().setUserAgent("test")); AsyncHttpClient.BoundRequestBuilder builder = c.prepareGet(getTargetUrl()); Response r = c.executeRequest(builder.build()).get(); assertEquals(200, r.getStatusCode()); } } async-http-client-1.6.5/src/test/java/com/ning/http/client/async/AsyncStreamHandlerTest.java000066400000000000000000000453251166553056000321150ustar00rootroot00000000000000/* * Copyright 2010 Ning, Inc. * * Ning licenses this file to you 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. */ package com.ning.http.client.async; import com.ning.http.client.AsyncHandler; import com.ning.http.client.AsyncHttpClient; import com.ning.http.client.AsyncHttpClientConfig; import com.ning.http.client.FluentCaseInsensitiveStringsMap; import com.ning.http.client.HttpResponseBodyPart; import com.ning.http.client.HttpResponseHeaders; import com.ning.http.client.HttpResponseStatus; import org.testng.Assert; import org.testng.annotations.Test; import java.util.Arrays; import java.util.Collection; import java.util.HashMap; import java.util.Map; import java.util.concurrent.CountDownLatch; import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; import java.util.concurrent.atomic.AtomicBoolean; public abstract class AsyncStreamHandlerTest extends AbstractBasicTest { private final static String RESPONSE = "param_1_"; private final static String UTF8 = "text/html;charset=utf-8"; @Test(groups = {"standalone", "default_provider"}) public void asyncStreamGETTest() throws Throwable { final CountDownLatch l = new CountDownLatch(1); AsyncHttpClient c = getAsyncHttpClient(null); c.prepareGet(getTargetUrl()).execute(new AsyncHandlerAdapter() { @Override public STATE onHeadersReceived(HttpResponseHeaders content) throws Exception { try { FluentCaseInsensitiveStringsMap h = content.getHeaders(); Assert.assertNotNull(h); Assert.assertEquals(h.getJoinedValue("content-type", ", ").toLowerCase(), UTF8); return STATE.ABORT; } finally { l.countDown(); } } @Override public void onThrowable(Throwable t) { try { Assert.fail("", t); } finally { l.countDown(); } } }); if (!l.await(5, TimeUnit.SECONDS)) { Assert.fail("Timeout out"); } c.close(); } @Test(groups = {"standalone", "default_provider"}) public void asyncStreamPOSTTest() throws Throwable { final CountDownLatch l = new CountDownLatch(1); FluentCaseInsensitiveStringsMap h = new FluentCaseInsensitiveStringsMap(); h.add("Content-Type", "application/x-www-form-urlencoded"); Map> m = new HashMap>(); m.put("param_1", Arrays.asList("value_1")); AsyncHttpClient c = getAsyncHttpClient(null); c.preparePost(getTargetUrl()).setParameters(m).execute(new AsyncHandlerAdapter() { private StringBuilder builder = new StringBuilder(); @Override public STATE onHeadersReceived(HttpResponseHeaders content) throws Exception { FluentCaseInsensitiveStringsMap h = content.getHeaders(); Assert.assertNotNull(h); Assert.assertEquals(h.getJoinedValue("content-type", ", ").toLowerCase(), UTF8); return STATE.CONTINUE; } @Override public STATE onBodyPartReceived(HttpResponseBodyPart content) throws Exception { builder.append(new String(content.getBodyPartBytes())); return STATE.CONTINUE; } @Override public String onCompleted() throws Exception { try { String r = builder.toString().trim(); Assert.assertEquals(r, RESPONSE); return r; } finally { l.countDown(); } } }); if (!l.await(10, TimeUnit.SECONDS)) { Assert.fail("Timeout out"); } c.close(); } @Test(groups = {"standalone", "default_provider"}) public void asyncStreamInterruptTest() throws Throwable { final CountDownLatch l = new CountDownLatch(1); FluentCaseInsensitiveStringsMap h = new FluentCaseInsensitiveStringsMap(); h.add("Content-Type", "application/x-www-form-urlencoded"); Map> m = new HashMap>(); m.put("param_1", Arrays.asList("value_1")); final AtomicBoolean a = new AtomicBoolean(true); AsyncHttpClient c = getAsyncHttpClient(null); c.preparePost(getTargetUrl()).setParameters(m).execute(new AsyncHandlerAdapter() { @Override public STATE onHeadersReceived(HttpResponseHeaders content) throws Exception { FluentCaseInsensitiveStringsMap h = content.getHeaders(); Assert.assertNotNull(h); Assert.assertEquals(h.getJoinedValue("content-type", ", ").toLowerCase(), UTF8); return STATE.ABORT; } @Override public STATE onBodyPartReceived(final HttpResponseBodyPart content) throws Exception { a.set(false); Assert.fail("Interrupted not working"); return STATE.ABORT; } @Override public void onThrowable(Throwable t) { try { Assert.fail("", t); } finally { l.countDown(); } } }); l.await(5, TimeUnit.SECONDS); Assert.assertTrue(a.get()); c.close(); } @Test(groups = {"standalone", "default_provider"}) public void asyncStreamFutureTest() throws Throwable { Map> m = new HashMap>(); m.put("param_1", Arrays.asList("value_1")); AsyncHttpClient c = getAsyncHttpClient(null); Future f = c.preparePost(getTargetUrl()).setParameters(m).execute(new AsyncHandlerAdapter() { private StringBuilder builder = new StringBuilder(); @Override public STATE onHeadersReceived(HttpResponseHeaders content) throws Exception { FluentCaseInsensitiveStringsMap h = content.getHeaders(); Assert.assertNotNull(h); Assert.assertEquals(h.getJoinedValue("content-type", ", ").toLowerCase(), UTF8); return STATE.CONTINUE; } @Override public STATE onBodyPartReceived(HttpResponseBodyPart content) throws Exception { builder.append(new String(content.getBodyPartBytes())); return STATE.CONTINUE; } @Override public String onCompleted() throws Exception { String r = builder.toString().trim(); Assert.assertEquals(r, RESPONSE); return r; } @Override public void onThrowable(Throwable t) { Assert.fail("", t); } }); try { String r = f.get(5, TimeUnit.SECONDS); Assert.assertNotNull(r); Assert.assertEquals(r.trim(), RESPONSE); } catch (TimeoutException ex) { Assert.fail(); } c.close(); } @Test(groups = {"standalone", "default_provider"}) public void asyncStreamThrowableRefusedTest() throws Throwable { final CountDownLatch l = new CountDownLatch(1); AsyncHttpClient c = getAsyncHttpClient(null); c.prepareGet(getTargetUrl()).execute(new AsyncHandlerAdapter() { @Override public STATE onHeadersReceived(HttpResponseHeaders content) throws Exception { throw new RuntimeException("FOO"); } @Override public void onThrowable(Throwable t) { try { if (t.getMessage() != null) { Assert.assertEquals(t.getMessage(), "FOO"); } } finally { l.countDown(); } } }); if (!l.await(10, TimeUnit.SECONDS)) { Assert.fail("Timed out"); } c.close(); } @Test(groups = {"standalone", "default_provider"}) public void asyncStreamReusePOSTTest() throws Throwable { final CountDownLatch l = new CountDownLatch(1); FluentCaseInsensitiveStringsMap h = new FluentCaseInsensitiveStringsMap(); h.add("Content-Type", "application/x-www-form-urlencoded"); Map> m = new HashMap>(); m.put("param_1", Arrays.asList("value_1")); AsyncHttpClient c = getAsyncHttpClient(null); c.preparePost(getTargetUrl()).setParameters(m).execute(new AsyncHandlerAdapter() { private StringBuilder builder = new StringBuilder(); @Override public STATE onHeadersReceived(HttpResponseHeaders content) throws Exception { FluentCaseInsensitiveStringsMap h = content.getHeaders(); Assert.assertNotNull(h); Assert.assertEquals(h.getJoinedValue("content-type", ", ").toLowerCase(), UTF8); return STATE.CONTINUE; } @Override public STATE onBodyPartReceived(HttpResponseBodyPart content) throws Exception { builder.append(new String(content.getBodyPartBytes())); return STATE.CONTINUE; } @Override public String onCompleted() throws Exception { try { String r = builder.toString().trim(); Assert.assertEquals(r, RESPONSE); return r; } finally { l.countDown(); } } }); if (!l.await(20, TimeUnit.SECONDS)) { Assert.fail("Timeout out"); } // Let do the same again c.preparePost(getTargetUrl()).setParameters(m).execute(new AsyncHandlerAdapter() { private StringBuilder builder = new StringBuilder(); @Override public STATE onHeadersReceived(HttpResponseHeaders content) throws Exception { FluentCaseInsensitiveStringsMap h = content.getHeaders(); Assert.assertNotNull(h); Assert.assertEquals(h.getJoinedValue("content-type", ", ").toLowerCase(), UTF8); return STATE.CONTINUE; } @Override public STATE onBodyPartReceived(HttpResponseBodyPart content) throws Exception { builder.append(new String(content.getBodyPartBytes())); return STATE.CONTINUE; } @Override public String onCompleted() throws Exception { try { String r = builder.toString().trim(); Assert.assertEquals(r, RESPONSE); return r; } finally { l.countDown(); } } }); if (!l.await(20, TimeUnit.SECONDS)) { Assert.fail("Timeout out"); } c.close(); } @Test(groups = {"online", "default_provider"}) public void asyncStream301WithBody() throws Throwable { final CountDownLatch l = new CountDownLatch(1); AsyncHttpClient c = getAsyncHttpClient(null); c.prepareGet("http://google.com/").execute(new AsyncHandlerAdapter() { private StringBuilder builder = new StringBuilder(); @Override public STATE onHeadersReceived(HttpResponseHeaders content) throws Exception { FluentCaseInsensitiveStringsMap h = content.getHeaders(); Assert.assertNotNull(h); Assert.assertEquals(h.getJoinedValue("content-type", ", ").toLowerCase(), "text/html; charset=utf-8"); return STATE.CONTINUE; } @Override public STATE onBodyPartReceived(HttpResponseBodyPart content) throws Exception { builder.append(new String(content.getBodyPartBytes())); return STATE.CONTINUE; } @Override public String onCompleted() throws Exception { String r = builder.toString(); Assert.assertTrue(r.contains("301 Moved")); l.countDown(); return r; } }); if (!l.await(20, TimeUnit.SECONDS)) { Assert.fail("Timeout out"); } c.close(); } @Test(groups = {"online", "default_provider"}) public void asyncStream301RedirectWithBody() throws Throwable { final CountDownLatch l = new CountDownLatch(1); AsyncHttpClient c = getAsyncHttpClient(new AsyncHttpClientConfig.Builder().setFollowRedirects(true).build()); c.prepareGet("http://google.com/").execute(new AsyncHandlerAdapter() { private StringBuilder builder = new StringBuilder(); @Override public STATE onHeadersReceived(HttpResponseHeaders content) throws Exception { FluentCaseInsensitiveStringsMap h = content.getHeaders(); Assert.assertNotNull(h); Assert.assertEquals(h.getFirstValue( "server" ), "gws"); // This assertion below is not an invariant, since implicitly contains locale-dependant settings // and fails when run in country having own localized Google site and it's locale relies on something // other than ISO-8859-1. // In Hungary for example, http://google.com/ redirects to http://www.google.hu/, a localized // Google site, that uses ISO-8892-2 encoding (default for HU). Similar is true for other // non-ISO-8859-1 using countries that have "localized" google, like google.hr, google.rs, google.cz, google.sk etc. // // Assert.assertEquals(h.getJoinedValue("content-type", ", "), "text/html; charset=ISO-8859-1"); return STATE.CONTINUE; } @Override public STATE onBodyPartReceived(HttpResponseBodyPart content) throws Exception { builder.append(new String(content.getBodyPartBytes())); return STATE.CONTINUE; } @Override public String onCompleted() throws Exception { String r = builder.toString(); Assert.assertTrue(!r.contains("301 Moved")); l.countDown(); return r; } }); if (!l.await(20, TimeUnit.SECONDS)) { Assert.fail("Timeout out"); } c.close(); } @Test(groups = {"standalone", "default_provider"}, timeOut = 3000, description = "Test behavior of 'read only status line' scenario.") public void asyncStreamJustStatusLine() throws Throwable { final int STATUS = 0; final int COMPLETED = 1; final int OTHER = 2; final boolean[] whatCalled = new boolean[]{false, false, false}; final CountDownLatch latch = new CountDownLatch(1); AsyncHttpClient client = getAsyncHttpClient(null); Future statusCode = client.prepareGet(getTargetUrl()).execute(new AsyncHandler() { private int status = -1; /* @Override */ public void onThrowable(Throwable t) { whatCalled[OTHER] = true; latch.countDown(); } /* @Override */ public STATE onBodyPartReceived(HttpResponseBodyPart bodyPart) throws Exception { whatCalled[OTHER] = true; latch.countDown(); return STATE.ABORT; } /* @Override */ public STATE onStatusReceived(HttpResponseStatus responseStatus) throws Exception { whatCalled[STATUS] = true; System.out.println(responseStatus); status = responseStatus.getStatusCode(); latch.countDown(); return STATE.ABORT; } /* @Override */ public STATE onHeadersReceived(HttpResponseHeaders headers) throws Exception { whatCalled[OTHER] = true; latch.countDown(); return STATE.ABORT; } /* @Override */ public Integer onCompleted() throws Exception { whatCalled[COMPLETED] = true; latch.countDown(); return status; } }); if (!latch.await(2, TimeUnit.SECONDS)) { Assert.fail("Timeout"); return; } Integer status = statusCode.get(TIMEOUT, TimeUnit.SECONDS); Assert.assertEquals((int) status, 200, "Expected status code failed."); if (!whatCalled[STATUS]) { Assert.fail("onStatusReceived not called."); } if (!whatCalled[COMPLETED]) { Assert.fail("onCompleted not called."); } if (whatCalled[OTHER]) { Assert.fail("Other method of AsyncHandler got called."); } client.close(); } @Test(groups = {"online", "default_provider"}) public void asyncOptionsTest() throws Throwable { final CountDownLatch l = new CountDownLatch(1); AsyncHttpClient c = getAsyncHttpClient(null); c.prepareOptions("http://www.apache.org/").execute(new AsyncHandlerAdapter() { @Override public STATE onHeadersReceived(HttpResponseHeaders content) throws Exception { FluentCaseInsensitiveStringsMap h = content.getHeaders(); Assert.assertNotNull(h); Assert.assertEquals(h.getJoinedValue("Allow", ", "), "GET,HEAD,POST,OPTIONS,TRACE"); return STATE.ABORT; } @Override public STATE onBodyPartReceived(HttpResponseBodyPart content) throws Exception { return STATE.CONTINUE; } @Override public String onCompleted() throws Exception { try { return "OK"; } finally { l.countDown(); } } }); if (!l.await(20, TimeUnit.SECONDS)) { Assert.fail("Timeout out"); } c.close(); } } async-http-client-1.6.5/src/test/java/com/ning/http/client/async/AsyncStreamLifecycleTest.java000066400000000000000000000142551166553056000324350ustar00rootroot00000000000000/* * Copyright 2010 Ning, Inc. * * Ning licenses this file to you 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. */ package com.ning.http.client.async; import com.ning.http.client.AsyncHandler; import com.ning.http.client.AsyncHttpClient; import com.ning.http.client.HttpResponseBodyPart; import com.ning.http.client.HttpResponseHeaders; import com.ning.http.client.HttpResponseStatus; import org.eclipse.jetty.continuation.Continuation; import org.eclipse.jetty.continuation.ContinuationSupport; import org.eclipse.jetty.server.Request; import org.eclipse.jetty.server.handler.AbstractHandler; import org.testng.annotations.AfterClass; import org.testng.annotations.Test; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.PrintWriter; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertFalse; import static org.testng.Assert.assertTrue; import static org.testng.Assert.fail; /** * Tests default asynchronous life cycle. * * @author Hubert Iwaniuk */ public abstract class AsyncStreamLifecycleTest extends AbstractBasicTest { private ExecutorService executorService = Executors.newFixedThreadPool(2); @AfterClass @Override public void tearDownGlobal() throws Exception { super.tearDownGlobal(); executorService.shutdownNow(); } @Override public AbstractHandler configureHandler() throws Exception { return new AbstractHandler() { public void handle(String s, Request request, HttpServletRequest req, final HttpServletResponse resp) throws IOException, ServletException { resp.setContentType("text/plain;charset=utf-8"); resp.setStatus(200); final Continuation continuation = ContinuationSupport.getContinuation(req); continuation.suspend(); final PrintWriter writer = resp.getWriter(); executorService.submit(new Runnable() { public void run() { try { Thread.sleep(100); } catch (InterruptedException e) { log.error("Failed to sleep for 100 ms.", e); } log.info("Delivering part1."); writer.write("part1"); writer.flush(); } }); executorService.submit(new Runnable() { public void run() { try { Thread.sleep(200); } catch (InterruptedException e) { log.error("Failed to sleep for 200 ms.", e); } log.info("Delivering part2."); writer.write("part2"); writer.flush(); continuation.complete(); } }); request.setHandled(true); } }; } //TODO Netty only. @Test(groups = {"standalone", "default_provider"}) public void testStream() throws IOException { AsyncHttpClient ahc = getAsyncHttpClient(null); final AtomicBoolean err = new AtomicBoolean(false); final LinkedBlockingQueue queue = new LinkedBlockingQueue(); final AtomicBoolean status = new AtomicBoolean(false); final AtomicInteger headers = new AtomicInteger(0); final CountDownLatch latch = new CountDownLatch(1); ahc.executeRequest(ahc.prepareGet(getTargetUrl()).build(), new AsyncHandler() { public void onThrowable(Throwable t) { fail("Got throwable.", t); err.set(true); } public STATE onBodyPartReceived(HttpResponseBodyPart e) throws Exception { String s = new String(e.getBodyPartBytes()); log.info("got part: {}", s); if (s.equals("")) { //noinspection ThrowableInstanceNeverThrown log.warn("Sampling stacktrace.", new Throwable("trace that, we should not get called for empty body.")); } queue.put(s); return STATE.CONTINUE; } public STATE onStatusReceived(HttpResponseStatus e) throws Exception { status.set(true); return STATE.CONTINUE; } public STATE onHeadersReceived(HttpResponseHeaders e) throws Exception { if (headers.incrementAndGet() == 2) { throw new Exception("Analyze this."); } return STATE.CONTINUE; } public Object onCompleted() throws Exception { latch.countDown(); return null; } }); try { assertTrue(latch.await(1, TimeUnit.SECONDS), "Latch failed."); } catch (InterruptedException e) { fail("Interrupted.", e); } assertFalse(err.get()); assertEquals(queue.size(), 2); assertTrue(queue.contains("part1")); assertTrue(queue.contains("part2")); assertTrue(status.get()); assertEquals(headers.get(), 1); ahc.close(); } } async-http-client-1.6.5/src/test/java/com/ning/http/client/async/AuthTimeoutTest.java000066400000000000000000000225441166553056000306340ustar00rootroot00000000000000/* * Copyright (c) 2010-2011 Sonatype, Inc. All rights reserved. * * This program is licensed to you under the Apache License Version 2.0, * and you may not use this file except in compliance with the Apache License Version 2.0. * You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0. * * Unless required by applicable law or agreed to in writing, * software distributed under the Apache License Version 2.0 is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. */ package com.ning.http.client.async; import com.ning.http.client.AsyncHttpClient; import com.ning.http.client.AsyncHttpClientConfig; import com.ning.http.client.Realm; import com.ning.http.client.Response; import org.apache.log4j.ConsoleAppender; import org.apache.log4j.Level; import org.apache.log4j.Logger; import org.apache.log4j.PatternLayout; import org.eclipse.jetty.http.security.Constraint; import org.eclipse.jetty.security.ConstraintMapping; import org.eclipse.jetty.security.ConstraintSecurityHandler; import org.eclipse.jetty.security.HashLoginService; import org.eclipse.jetty.security.LoginService; import org.eclipse.jetty.security.authentication.BasicAuthenticator; 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.testng.annotations.Test; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.OutputStream; import java.util.Arrays; import java.util.HashSet; import java.util.Set; import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertNotNull; import static org.testng.Assert.fail; public abstract class AuthTimeoutTest extends AbstractBasicTest { private final static String user = "user"; private final static String admin = "admin"; protected AsyncHttpClient client; public void setUpServer(String auth) throws Exception { server = new Server(); Logger root = Logger.getRootLogger(); root.setLevel(Level.DEBUG); root.addAppender(new ConsoleAppender(new PatternLayout(PatternLayout.TTCC_CONVERSION_PATTERN))); port1 = findFreePort(); Connector listener = new SelectChannelConnector(); listener.setHost("127.0.0.1"); listener.setPort(port1); server.addConnector(listener); LoginService loginService = new HashLoginService("MyRealm", "src/test/resources/realm.properties"); server.addBean(loginService); Constraint constraint = new Constraint(); constraint.setName(auth); constraint.setRoles(new String[]{user, admin}); constraint.setAuthenticate(true); ConstraintMapping mapping = new ConstraintMapping(); mapping.setConstraint(constraint); mapping.setPathSpec("/*"); Set knownRoles = new HashSet(); knownRoles.add(user); knownRoles.add(admin); ConstraintSecurityHandler security = new ConstraintSecurityHandler(); security.setConstraintMappings(new ConstraintMapping[]{mapping}, knownRoles); security.setAuthenticator(new BasicAuthenticator()); security.setLoginService(loginService); security.setStrict(false); security.setHandler(configureHandler()); server.setHandler(security); server.start(); log.info("Local HTTP server started successfully"); } private class SimpleHandler extends AbstractHandler { public void handle(String s, Request r, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { // NOTE: handler sends less bytes than are given in Content-Length, which should lead to timeout OutputStream out = response.getOutputStream(); if (request.getHeader("X-Content") != null) { String content = request.getHeader("X-Content"); response.setHeader("Content-Length", String.valueOf(content.getBytes("UTF-8").length)); out.write(content.substring(1).getBytes("UTF-8")); out.flush(); out.close(); return; } response.setStatus(200); out.flush(); out.close(); } } @Test(groups = {"standalone", "default_provider"}, enabled = false) public void basicAuthTimeoutTest() throws Exception { setUpServer(Constraint.__BASIC_AUTH); Future f = execute(false); try { f.get(); fail("expected timeout"); } catch (Exception e) { inspectException(e); } client.close(); } @Test(groups = {"standalone", "default_provider"}, enabled = false) public void basicPreemptiveAuthTimeoutTest() throws Exception { setUpServer(Constraint.__BASIC_AUTH); Future f = execute(true); try { f.get(); fail("expected timeout"); } catch (Exception e) { inspectException(e); } client.close(); } @Test(groups = {"standalone", "default_provider"}, enabled = false) public void digestAuthTimeoutTest() throws Exception { setUpServer(Constraint.__DIGEST_AUTH); Future f = execute(false); try { f.get(); fail("expected timeout"); } catch (Exception e) { inspectException(e); } client.close(); } @Test(groups = {"standalone", "default_provider"}, enabled = false) public void digestPreemptiveAuthTimeoutTest() throws Exception { setUpServer(Constraint.__DIGEST_AUTH); Future f = execute(true); try { f.get(); fail("expected timeout"); } catch (Exception e) { inspectException(e); } client.close(); } @Test(groups = {"standalone", "default_provider"}, enabled = false) public void basicFutureAuthTimeoutTest() throws Exception { setUpServer(Constraint.__BASIC_AUTH); Future f = execute(false); try { f.get(1, TimeUnit.SECONDS); fail("expected timeout"); } catch (Exception e) { inspectException(e); } client.close(); } @Test(groups = {"standalone", "default_provider"}, enabled = false) public void basicFuturePreemptiveAuthTimeoutTest() throws Exception { setUpServer(Constraint.__BASIC_AUTH); Future f = execute(true); try { f.get(1, TimeUnit.SECONDS); fail("expected timeout"); } catch (Exception e) { inspectException(e); } client.close(); } @Test(groups = {"standalone", "default_provider"}, enabled = false) public void digestFutureAuthTimeoutTest() throws Exception { setUpServer(Constraint.__DIGEST_AUTH); Future f = execute(false); try { f.get(1, TimeUnit.SECONDS); fail("expected timeout"); } catch (Exception e) { inspectException(e); } client.close(); } @Test(groups = {"standalone", "default_provider"}, enabled = false) public void digestFuturePreemptiveAuthTimeoutTest() throws Exception { setUpServer(Constraint.__DIGEST_AUTH); Future f = execute(true); try { f.get(1, TimeUnit.SECONDS); fail("expected timeout"); } catch (Exception e) { inspectException(e); } client.close(); } protected void inspectException(Throwable t) { assertNotNull(t.getCause()); assertEquals(t.getCause().getClass(), IOException.class); if (!t.getCause().getMessage().startsWith("Remotely Closed")){ fail(); }; } protected Future execute(boolean preemptive) throws IOException { client = getAsyncHttpClient( new AsyncHttpClientConfig.Builder().setIdleConnectionInPoolTimeoutInMs(2000).setConnectionTimeoutInMs(20000).setRequestTimeoutInMs(2000).build()); AsyncHttpClient.BoundRequestBuilder r = client.prepareGet(getTargetUrl()).setRealm(realm(preemptive)).setHeader("X-Content", "Test"); Future f = r.execute(); return f; } private Realm realm(boolean preemptive) { return (new Realm.RealmBuilder()).setPrincipal(user).setPassword(admin).setUsePreemptiveAuth(preemptive).build(); } @Override protected String getTargetUrl() { return "http://127.0.0.1:" + port1 + "/"; } @Override public AbstractHandler configureHandler() throws Exception { return new SimpleHandler(); } } async-http-client-1.6.5/src/test/java/com/ning/http/client/async/BasicAuthTest.java000066400000000000000000000500161166553056000302220ustar00rootroot00000000000000/* * Copyright 2010 Ning, Inc. * * Ning licenses this file to you 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. */ package com.ning.http.client.async; import com.ning.http.client.AsyncHandler; import com.ning.http.client.AsyncHttpClient; import com.ning.http.client.AsyncHttpClientConfig; import com.ning.http.client.HttpResponseBodyPart; import com.ning.http.client.HttpResponseHeaders; import com.ning.http.client.HttpResponseStatus; import com.ning.http.client.Realm; import com.ning.http.client.Response; import com.ning.http.client.SimpleAsyncHttpClient; import com.ning.http.client.consumers.AppendableBodyConsumer; import com.ning.http.client.generators.InputStreamBodyGenerator; import org.apache.log4j.ConsoleAppender; import org.apache.log4j.Level; import org.apache.log4j.Logger; import org.apache.log4j.PatternLayout; import org.eclipse.jetty.http.security.Constraint; import org.eclipse.jetty.security.ConstraintMapping; import org.eclipse.jetty.security.ConstraintSecurityHandler; import org.eclipse.jetty.security.HashLoginService; import org.eclipse.jetty.security.LoginService; import org.eclipse.jetty.security.authentication.BasicAuthenticator; import org.eclipse.jetty.security.authentication.DigestAuthenticator; 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.testng.annotations.BeforeClass; import org.testng.annotations.Test; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.ByteArrayInputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.net.URL; import java.util.Arrays; import java.util.HashSet; import java.util.Set; import java.util.concurrent.ExecutionException; import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; import java.util.concurrent.atomic.AtomicBoolean; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertNotNull; public abstract class BasicAuthTest extends AbstractBasicTest { protected final static String MY_MESSAGE = "my message"; protected final static String user = "user"; protected final static String admin = "admin"; private Server server2; @BeforeClass(alwaysRun = true) @Override public void setUpGlobal() throws Exception { server = new Server(); Logger root = Logger.getRootLogger(); root.setLevel(Level.DEBUG); root.addAppender(new ConsoleAppender( new PatternLayout(PatternLayout.TTCC_CONVERSION_PATTERN))); port1 = findFreePort(); Connector listener = new SelectChannelConnector(); listener.setHost("127.0.0.1"); listener.setPort(port1); server.addConnector(listener); LoginService loginService = new HashLoginService("MyRealm", "src/test/resources/realm.properties"); server.addBean(loginService); Constraint constraint = new Constraint(); constraint.setName(Constraint.__BASIC_AUTH); constraint.setRoles(new String[]{user, admin}); constraint.setAuthenticate(true); ConstraintMapping mapping = new ConstraintMapping(); mapping.setConstraint(constraint); mapping.setPathSpec("/*"); Set knownRoles = new HashSet(); knownRoles.add(user); knownRoles.add(admin); ConstraintSecurityHandler security = new ConstraintSecurityHandler(); security.setConstraintMappings(new ConstraintMapping[]{mapping}, knownRoles); security.setAuthenticator(new BasicAuthenticator()); security.setLoginService(loginService); security.setStrict(false); security.setHandler(configureHandler()); server.setHandler(security); server.start(); log.info("Local HTTP server started successfully"); } private String getFileContent(final File file) { FileInputStream in = null; try { if (file.exists() && file.canRead()) { final StringBuilder sb = new StringBuilder(128); final byte[] b = new byte[512]; int read; in = new FileInputStream(file); while ((read = in.read(b)) != -1) { sb.append(new String(b, 0, read, "UTF-8")); } return sb.toString(); } throw new IllegalArgumentException("File does not exist or cannot be read: " + file.getCanonicalPath()); } catch (IOException ioe) { throw new IllegalStateException(ioe); } finally { if (in != null) { try { in.close(); } catch (IOException ignored) {} } } } private void setUpSecondServer() throws Exception { server2 = new Server(); port2 = findFreePort(); SelectChannelConnector connector = new SelectChannelConnector(); connector.setHost("127.0.0.1"); connector.setPort(port2); server2.addConnector(connector); LoginService loginService = new HashLoginService("MyRealm", "src/test/resources/realm.properties"); server2.addBean(loginService); Constraint constraint = new Constraint(); constraint.setName(Constraint.__DIGEST_AUTH); constraint.setRoles(new String[]{user, admin}); constraint.setAuthenticate(true); ConstraintMapping mapping = new ConstraintMapping(); mapping.setConstraint(constraint); mapping.setPathSpec("/*"); Set knownRoles = new HashSet(); knownRoles.add(user); knownRoles.add(admin); ConstraintSecurityHandler security = new ConstraintSecurityHandler() { @Override public void handle(String arg0, Request arg1, HttpServletRequest arg2, HttpServletResponse arg3) throws IOException, ServletException { System.err.println("request in security handler"); System.err.println("Authorization: " + arg2.getHeader("Authorization")); System.err.println("RequestUri: " + arg2.getRequestURI()); super.handle(arg0, arg1, arg2, arg3); } }; security.setConstraintMappings(new ConstraintMapping[]{mapping}, knownRoles); security.setAuthenticator(new DigestAuthenticator()); security.setLoginService(loginService); security.setStrict(true); security.setHandler(new RedirectHandler()); server2.setHandler(security); server2.start(); } private void stopSecondServer() throws Exception { server2.stop(); } private class RedirectHandler extends AbstractHandler { private AtomicBoolean redirectOnce = new AtomicBoolean(false); public void handle(String s, Request r, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { System.err.println("redirecthandler"); System.err.println("request: " + request.getRequestURI()); if ("/uff".equals(request.getRequestURI())) { System.err.println("redirect to /bla"); response.setStatus(302); response.setHeader("Location", "/bla"); response.getOutputStream().flush(); response.getOutputStream().close(); return; } else { System.err.println("got redirected" + request.getRequestURI()); response.addHeader("X-Auth", request.getHeader("Authorization")); response.addHeader("X-Content-Length", String.valueOf(request.getContentLength())); response.setStatus(200); response.getOutputStream().write("content".getBytes("UTF-8")); response.getOutputStream().flush(); response.getOutputStream().close(); } } } private class SimpleHandler extends AbstractHandler { public void handle(String s, Request r, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { if (request.getHeader("X-401") != null) { response.setStatus(401); response.getOutputStream().flush(); response.getOutputStream().close(); return; } response.addHeader("X-Auth", request.getHeader("Authorization")); response.addHeader("X-Content-Length", String.valueOf(request.getContentLength())); response.setStatus(200); int size = 10 * 1024; if (request.getContentLength() > 0) { size = request.getContentLength(); } byte[] bytes = new byte[size]; if (bytes.length > 0) { int read = request.getInputStream().read(bytes); if (read > 0) { response.getOutputStream().write(bytes, 0, read); } } response.getOutputStream().flush(); response.getOutputStream().close(); } } @Test(groups = {"standalone", "default_provider"}) public void basicAuthTest() throws IOException, ExecutionException, TimeoutException, InterruptedException { AsyncHttpClient client = getAsyncHttpClient(null); AsyncHttpClient.BoundRequestBuilder r = client.prepareGet(getTargetUrl()) .setRealm((new Realm.RealmBuilder()).setPrincipal(user).setPassword(admin).build()); Future f = r.execute(); Response resp = f.get(3, TimeUnit.SECONDS); assertNotNull(resp); assertNotNull(resp.getHeader("X-Auth")); assertEquals(resp.getStatusCode(), HttpServletResponse.SC_OK); client.close(); } @Test(groups = {"standalone", "default_provider"}) public void redirectAndBasicAuthTest() throws Exception, ExecutionException, TimeoutException, InterruptedException { AsyncHttpClient client = null; try { setUpSecondServer(); client = getAsyncHttpClient(new AsyncHttpClientConfig.Builder().setFollowRedirects(true).setMaximumNumberOfRedirects(10).build()); AsyncHttpClient.BoundRequestBuilder r = client.prepareGet(getTargetUrl2()) // .setHeader( "X-302", "/bla" ) .setRealm((new Realm.RealmBuilder()).setPrincipal(user).setPassword(admin).build()); Future f = r.execute(); Response resp = f.get(3, TimeUnit.SECONDS); assertEquals(resp.getStatusCode(), HttpServletResponse.SC_OK); assertNotNull(resp); assertNotNull(resp.getHeader("X-Auth")); } finally { if (client != null) client.close(); stopSecondServer(); } } @Override protected String getTargetUrl() { return "http://127.0.0.1:" + port1 + "/"; } protected String getTargetUrl2() { return "http://127.0.0.1:" + port2 + "/uff"; } @Test(groups = {"standalone", "default_provider"}) public void basic401Test() throws IOException, ExecutionException, TimeoutException, InterruptedException { AsyncHttpClient client = getAsyncHttpClient(null); AsyncHttpClient.BoundRequestBuilder r = client.prepareGet(getTargetUrl()) .setHeader("X-401", "401").setRealm((new Realm.RealmBuilder()).setPrincipal(user).setPassword(admin).build()); Future f = r.execute(new AsyncHandler() { private HttpResponseStatus status; public void onThrowable(Throwable t) { } public STATE onBodyPartReceived(HttpResponseBodyPart bodyPart) throws Exception { return STATE.CONTINUE; } public STATE onStatusReceived(HttpResponseStatus responseStatus) throws Exception { this.status = responseStatus; if (status.getStatusCode() != 200) { return STATE.ABORT; } return STATE.CONTINUE; } public STATE onHeadersReceived(HttpResponseHeaders headers) throws Exception { return STATE.CONTINUE; } public Integer onCompleted() throws Exception { return status.getStatusCode(); } }); Integer statusCode = f.get(10, TimeUnit.SECONDS); assertNotNull(statusCode); assertEquals(statusCode.intValue(), 401); client.close(); } @Test(groups = {"standalone", "default_provider"}) public void basicAuthTestPreemtiveTest() throws IOException, ExecutionException, TimeoutException, InterruptedException { AsyncHttpClient client = getAsyncHttpClient(null); AsyncHttpClient.BoundRequestBuilder r = client.prepareGet(getTargetUrl()) .setRealm((new Realm.RealmBuilder()).setPrincipal(user).setPassword(admin).setUsePreemptiveAuth(true).build()); Future f = r.execute(); Response resp = f.get(3, TimeUnit.SECONDS); assertNotNull(resp); assertNotNull(resp.getHeader("X-Auth")); assertEquals(resp.getStatusCode(), HttpServletResponse.SC_OK); client.close(); } @Test(groups = {"standalone", "default_provider"}) public void basicAuthNegativeTest() throws IOException, ExecutionException, TimeoutException, InterruptedException { AsyncHttpClient client = getAsyncHttpClient(null); AsyncHttpClient.BoundRequestBuilder r = client.prepareGet(getTargetUrl()) .setRealm((new Realm.RealmBuilder()).setPrincipal("fake").setPassword(admin).build()); Future f = r.execute(); Response resp = f.get(3, TimeUnit.SECONDS); assertNotNull(resp); assertEquals(resp.getStatusCode(), 401); client.close(); } @Test(groups = {"standalone", "default_provider"}) public void basicAuthInputStreamTest() throws IOException, ExecutionException, TimeoutException, InterruptedException { AsyncHttpClient client = getAsyncHttpClient(null); ByteArrayInputStream is = new ByteArrayInputStream("test".getBytes()); AsyncHttpClient.BoundRequestBuilder r = client.preparePost(getTargetUrl()) .setBody(is).setRealm((new Realm.RealmBuilder()).setPrincipal(user).setPassword(admin).build()); Future f = r.execute(); Response resp = f.get(30, TimeUnit.SECONDS); assertNotNull(resp); assertNotNull(resp.getHeader("X-Auth")); assertEquals(resp.getStatusCode(), HttpServletResponse.SC_OK); assertEquals(resp.getResponseBody(), "test"); client.close(); } @Test(groups = {"standalone", "default_provider"}) public void basicAuthFileTest() throws Throwable { AsyncHttpClient client = getAsyncHttpClient(null); ClassLoader cl = getClass().getClassLoader(); // override system properties URL url = cl.getResource("SimpleTextFile.txt"); File file = new File(url.toURI()); final String fileContent = getFileContent(file); AsyncHttpClient.BoundRequestBuilder r = client.preparePost(getTargetUrl()) .setBody(file).setRealm((new Realm.RealmBuilder()).setPrincipal(user).setPassword(admin).build()); Future f = r.execute(); Response resp = f.get(3, TimeUnit.SECONDS); assertNotNull(resp); assertNotNull(resp.getHeader("X-Auth")); assertEquals(resp.getStatusCode(), HttpServletResponse.SC_OK); assertEquals(resp.getResponseBody(), fileContent); client.close(); } @Test(groups = {"standalone", "default_provider"}) public void basicAuthAsyncConfigTest() throws Throwable { AsyncHttpClient client = getAsyncHttpClient(new AsyncHttpClientConfig.Builder() .setRealm((new Realm.RealmBuilder()).setPrincipal(user).setPassword(admin).build()).build()); ClassLoader cl = getClass().getClassLoader(); // override system properties URL url = cl.getResource("SimpleTextFile.txt"); File file = new File(url.toURI()); final String fileContent = getFileContent(file); AsyncHttpClient.BoundRequestBuilder r = client.preparePost(getTargetUrl()).setBody(file); Future f = r.execute(); Response resp = f.get(3, TimeUnit.SECONDS); assertNotNull(resp); assertNotNull(resp.getHeader("X-Auth")); assertEquals(resp.getStatusCode(), HttpServletResponse.SC_OK); assertEquals(resp.getResponseBody(), fileContent); client.close(); } @Test(groups = {"standalone", "default_provider"}) public void basicAuthFileNoKeepAliveTest() throws Throwable { AsyncHttpClient client = getAsyncHttpClient(new AsyncHttpClientConfig.Builder().setAllowPoolingConnection(false).build()); ClassLoader cl = getClass().getClassLoader(); // override system properties URL url = cl.getResource("SimpleTextFile.txt"); File file = new File(url.toURI()); final String fileContent = getFileContent(file); AsyncHttpClient.BoundRequestBuilder r = client.preparePost(getTargetUrl()) .setBody(file).setRealm((new Realm.RealmBuilder()).setPrincipal(user).setPassword(admin).build()); Future f = r.execute(); Response resp = f.get(3, TimeUnit.SECONDS); assertNotNull(resp); assertNotNull(resp.getHeader("X-Auth")); assertEquals(resp.getStatusCode(), HttpServletResponse.SC_OK); assertEquals(resp.getResponseBody(), fileContent); client.close(); } @Override public AbstractHandler configureHandler() throws Exception { return new SimpleHandler(); } @Test(groups = {"standalone", "default_provider"}) public void StringBufferBodyConsumerTest() throws Throwable { SimpleAsyncHttpClient client = new SimpleAsyncHttpClient.Builder() .setRealmPrincipal(user) .setRealmPassword(admin) .setUrl(getTargetUrl()) .setHeader("Content-Type", "text/html").build(); StringBuilder s = new StringBuilder(); Future future = client.post(new InputStreamBodyGenerator(new ByteArrayInputStream(MY_MESSAGE.getBytes())), new AppendableBodyConsumer(s)); System.out.println("waiting for response"); Response response = future.get(); assertEquals(response.getStatusCode(), 200); assertEquals(s.toString(), MY_MESSAGE); assertEquals(response.getStatusCode(), HttpServletResponse.SC_OK); assertNotNull(response.getHeader("X-Auth")); client.close(); } @Test(groups = {"standalone", "default_provider"}) public void noneAuthTest() throws IOException, ExecutionException, TimeoutException, InterruptedException { AsyncHttpClient client = getAsyncHttpClient(null); AsyncHttpClient.BoundRequestBuilder r = client.prepareGet(getTargetUrl()) .setRealm((new Realm.RealmBuilder()).setPrincipal(user).setPassword(admin).build()); Future f = r.execute(); Response resp = f.get(3, TimeUnit.SECONDS); assertNotNull(resp); assertNotNull(resp.getHeader("X-Auth")); assertEquals(resp.getStatusCode(), HttpServletResponse.SC_OK); client.close(); } } async-http-client-1.6.5/src/test/java/com/ning/http/client/async/BasicHttpsTest.java000066400000000000000000000316451166553056000304320ustar00rootroot00000000000000/* * Copyright 2010 Ning, Inc. * * Ning licenses this file to you 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. */ package com.ning.http.client.async; import com.ning.http.client.AsyncHttpClient; import com.ning.http.client.AsyncHttpClientConfig.Builder; import com.ning.http.client.Response; import org.eclipse.jetty.server.Request; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.handler.AbstractHandler; import org.eclipse.jetty.server.ssl.SslSocketConnector; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.testng.annotations.AfterClass; import org.testng.annotations.AfterMethod; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; import javax.net.ssl.KeyManager; import javax.net.ssl.KeyManagerFactory; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLHandshakeException; import javax.net.ssl.TrustManager; import javax.net.ssl.X509TrustManager; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.net.ConnectException; import java.net.ServerSocket; import java.net.URL; import java.security.KeyStore; import java.security.SecureRandom; import java.security.cert.CertificateException; import java.security.cert.X509Certificate; import java.util.Enumeration; import java.util.concurrent.ExecutionException; import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertNotNull; import static org.testng.Assert.assertTrue; public abstract class BasicHttpsTest extends AbstractBasicTest { protected final Logger log = LoggerFactory.getLogger(BasicHttpsTest.class); public static class EchoHandler extends AbstractHandler { /* @Override */ public void handle(String pathInContext, Request r, HttpServletRequest httpRequest, HttpServletResponse httpResponse) throws ServletException, IOException { httpResponse.setContentType("text/html; charset=utf-8"); Enumeration e = httpRequest.getHeaderNames(); String param; while (e.hasMoreElements()) { param = e.nextElement().toString(); if (param.startsWith("LockThread")) { try { Thread.sleep(40 * 1000); } catch (InterruptedException ex) { // nothing to do here } } httpResponse.addHeader("X-" + param, httpRequest.getHeader(param)); } Enumeration i = httpRequest.getParameterNames(); StringBuilder requestBody = new StringBuilder(); while (i.hasMoreElements()) { param = i.nextElement().toString(); httpResponse.addHeader("X-" + param, httpRequest.getParameter(param)); requestBody.append(param); requestBody.append("_"); } String pathInfo = httpRequest.getPathInfo(); if (pathInfo != null) httpResponse.addHeader("X-pathInfo", pathInfo); String queryString = httpRequest.getQueryString(); if (queryString != null) httpResponse.addHeader("X-queryString", queryString); httpResponse.addHeader("X-KEEP-ALIVE", httpRequest.getRemoteAddr() + ":" + httpRequest.getRemotePort()); javax.servlet.http.Cookie[] cs = httpRequest.getCookies(); if (cs != null) { for (javax.servlet.http.Cookie c : cs) { httpResponse.addCookie(c); } } if (requestBody.length() > 0) { httpResponse.getOutputStream().write(requestBody.toString().getBytes()); } int size = 10 * 1024; if (httpRequest.getContentLength() > 0) { size = httpRequest.getContentLength(); } byte[] bytes = new byte[size]; if (bytes.length > 0) { //noinspection ResultOfMethodCallIgnored int read = httpRequest.getInputStream().read(bytes); httpResponse.getOutputStream().write(bytes, 0, read); } httpResponse.setStatus(200); httpResponse.getOutputStream().flush(); httpResponse.getOutputStream().close(); } } @AfterClass(alwaysRun = true) public void tearDownGlobal() throws Exception { server.stop(); } @AfterMethod(alwaysRun = true) public void tearDownProps() throws Exception { System.clearProperty("javax.net.ssl.keyStore"); System.clearProperty("javax.net.ssl.trustStore"); } protected String getTargetUrl() { return String.format("https://127.0.0.1:%d/foo/test", port1); } public AbstractHandler configureHandler() throws Exception { return new EchoHandler(); } protected int findFreePort() throws IOException { ServerSocket socket = null; try { socket = new ServerSocket(0); return socket.getLocalPort(); } finally { if (socket != null) { socket.close(); } } } @BeforeClass(alwaysRun = true) public void setUpGlobal() throws Exception { server = new Server(); port1 = findFreePort(); SslSocketConnector connector = new SslSocketConnector(); connector.setHost("127.0.0.1"); connector.setPort(port1); ClassLoader cl = getClass().getClassLoader(); // override system properties URL cacertsUrl = cl.getResource("ssltest-cacerts.jks"); String trustStoreFile = new File(cacertsUrl.toURI()).getAbsolutePath(); connector.setTruststore(trustStoreFile); connector.setTrustPassword("changeit"); connector.setTruststoreType("JKS"); log.info("SSL certs path: {}", trustStoreFile); // override system properties URL keystoreUrl = cl.getResource("ssltest-keystore.jks"); String keyStoreFile = new File(keystoreUrl.toURI()).getAbsolutePath(); connector.setKeystore(keyStoreFile); connector.setKeyPassword("changeit"); connector.setKeystoreType("JKS"); log.info("SSL keystore path: {}", keyStoreFile); server.addConnector(connector); server.setHandler(configureHandler()); server.start(); log.info("Local HTTP server started successfully"); } @Test(groups = {"standalone", "default_provider"}) public void zeroCopyPostTest() throws Throwable { final AsyncHttpClient client = getAsyncHttpClient(new Builder().setSSLContext(createSSLContext()).build()); ClassLoader cl = getClass().getClassLoader(); // override system properties URL url = cl.getResource("SimpleTextFile.txt"); File file = new File(url.toURI()); Future f = client.preparePost(getTargetUrl()).setBody(file).setHeader("Content-Type", "text/html").execute(); Response resp = f.get(); assertNotNull(resp); assertEquals(resp.getStatusCode(), HttpServletResponse.SC_OK); assertEquals(resp.getResponseBody(), "This is a simple test file"); } @Test(groups = {"standalone", "default_provider"}) public void multipleSSLRequestsTest() throws Throwable { final AsyncHttpClient c = getAsyncHttpClient(new Builder().setSSLContext(createSSLContext()).build()); String body = "hello there"; // once Response response = c.preparePost(getTargetUrl()) .setBody(body) .setHeader("Content-Type", "text/html") .execute().get(TIMEOUT, TimeUnit.SECONDS); assertEquals(response.getResponseBody(), body); // twice response = c.preparePost(getTargetUrl()) .setBody(body) .setHeader("Content-Type", "text/html") .execute().get(TIMEOUT, TimeUnit.SECONDS); assertEquals(response.getResponseBody(), body); c.close(); } @Test(groups = {"standalone", "default_provider"}) public void multipleSSLWithoutCacheTest() throws Throwable { final AsyncHttpClient c = getAsyncHttpClient(new Builder().setSSLContext(createSSLContext()).setAllowSslConnectionPool(false).build()); String body = "hello there"; c.preparePost(getTargetUrl()) .setBody(body) .setHeader("Content-Type", "text/html") .execute(); c.preparePost(getTargetUrl()) .setBody(body) .setHeader("Content-Type", "text/html") .execute(); Response response = c.preparePost(getTargetUrl()) .setBody(body) .setHeader("Content-Type", "text/html") .execute().get(); assertEquals(response.getResponseBody(), body); c.close(); } @Test(groups = {"standalone", "default_provider"}) public void reconnectsAfterFailedCertificationPath() throws Throwable { final AsyncHttpClient c = getAsyncHttpClient(new Builder().setSSLContext(createSSLContext()).build()); final String body = "hello there"; TRUST_SERVER_CERT.set(false); try { // first request fails because server certificate is rejected try { c.preparePost(getTargetUrl()) .setBody(body) .setHeader("Content-Type", "text/html") .execute().get(TIMEOUT, TimeUnit.SECONDS); } catch (final ExecutionException e) { Throwable cause = e.getCause(); if (cause instanceof ConnectException) { assertNotNull(cause.getCause()); assertTrue(cause.getCause() instanceof SSLHandshakeException); } else { assertTrue(cause instanceof SSLHandshakeException); } } TRUST_SERVER_CERT.set(true); // second request should succeed final Response response = c.preparePost(getTargetUrl()) .setBody(body) .setHeader("Content-Type", "text/html") .execute().get(TIMEOUT, TimeUnit.SECONDS); assertEquals(response.getResponseBody(), body); } finally { TRUST_SERVER_CERT.set(true); } c.close(); } private static SSLContext createSSLContext() { try { InputStream keyStoreStream = BasicHttpsTest.class.getResourceAsStream("ssltest-cacerts.jks"); char[] keyStorePassword = "changeit".toCharArray(); KeyStore ks = KeyStore.getInstance("JKS"); ks.load(keyStoreStream, keyStorePassword); // Set up key manager factory to use our key store char[] certificatePassword = "changeit".toCharArray(); KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509"); kmf.init(ks, certificatePassword); // Initialize the SSLContext to work with our key managers. KeyManager[] keyManagers = kmf.getKeyManagers(); TrustManager[] trustManagers = new TrustManager[]{DUMMY_TRUST_MANAGER}; SecureRandom secureRandom = new SecureRandom(); SSLContext sslContext = SSLContext.getInstance("TLS"); sslContext.init(keyManagers, trustManagers, secureRandom); return sslContext; } catch (Exception e) { throw new Error("Failed to initialize the server-side SSLContext", e); } } private static final AtomicBoolean TRUST_SERVER_CERT = new AtomicBoolean(true); private static final TrustManager DUMMY_TRUST_MANAGER = new X509TrustManager() { public X509Certificate[] getAcceptedIssuers() { return new X509Certificate[0]; } public void checkClientTrusted( X509Certificate[] chain, String authType) throws CertificateException { } public void checkServerTrusted( X509Certificate[] chain, String authType) throws CertificateException { if (!TRUST_SERVER_CERT.get()) { throw new CertificateException("Server certificate not trusted."); } } }; } async-http-client-1.6.5/src/test/java/com/ning/http/client/async/BodyChunkTest.java000066400000000000000000000044211166553056000302440ustar00rootroot00000000000000/* * Copyright 2010 Ning, Inc. * * Ning licenses this file to you 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. */ package com.ning.http.client.async; import com.ning.http.client.AsyncHttpClient; import com.ning.http.client.AsyncHttpClientConfig; import com.ning.http.client.RequestBuilder; import com.ning.http.client.Response; import com.ning.http.client.generators.InputStreamBodyGenerator; import org.testng.annotations.Test; import java.io.ByteArrayInputStream; import java.util.concurrent.Future; import static org.testng.Assert.assertEquals; public abstract class BodyChunkTest extends AbstractBasicTest { private final static String MY_MESSAGE = "my message"; @Test(groups = {"standalone", "default_provider"}) public void negativeContentTypeTest() throws Throwable { AsyncHttpClientConfig.Builder confbuilder = new AsyncHttpClientConfig.Builder(); confbuilder = confbuilder.setConnectionTimeoutInMs(100); confbuilder = confbuilder.setMaximumConnectionsTotal(50); confbuilder = confbuilder.setRequestTimeoutInMs(5 * 60 * 1000); // 5 minutes // Create client AsyncHttpClient client = getAsyncHttpClient(confbuilder.build()); RequestBuilder requestBuilder = new RequestBuilder("POST") .setUrl(getTargetUrl()) .setHeader("Content-Type", "message/rfc822"); requestBuilder.setBody(new InputStreamBodyGenerator(new ByteArrayInputStream(MY_MESSAGE.getBytes()))); Future future = client.executeRequest(requestBuilder.build()); System.out.println("waiting for response"); Response response = future.get(); assertEquals(response.getStatusCode(), 200); assertEquals(response.getResponseBody(), MY_MESSAGE); client.close(); } } async-http-client-1.6.5/src/test/java/com/ning/http/client/async/BodyDeferringAsyncHandlerTest.java000066400000000000000000000261261166553056000334030ustar00rootroot00000000000000/* * Copyright (c) 2010-2011 Sonatype, Inc. All rights reserved. * * This program is licensed to you under the Apache License Version 2.0, * and you may not use this file except in compliance with the Apache License Version 2.0. * You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0. * * Unless required by applicable law or agreed to in writing, * software distributed under the Apache License Version 2.0 is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. */ package com.ning.http.client.async; import com.ning.http.client.AsyncHttpClient; import com.ning.http.client.AsyncHttpClientConfig; import com.ning.http.client.BodyDeferringAsyncHandler; import com.ning.http.client.BodyDeferringAsyncHandler.BodyDeferringInputStream; import com.ning.http.client.Response; import org.eclipse.jetty.server.Request; import org.eclipse.jetty.server.handler.AbstractHandler; import org.testng.Assert; import org.testng.annotations.Test; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.PipedInputStream; import java.io.PipedOutputStream; import java.util.concurrent.ExecutionException; import java.util.concurrent.Future; import java.util.concurrent.TimeoutException; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertNotNull; public abstract class BodyDeferringAsyncHandlerTest extends AbstractBasicTest { // not a half gig ;) for test shorter run's sake protected static final int HALF_GIG = 100000; public static class SlowAndBigHandler extends AbstractHandler { public void handle(String pathInContext, Request request, HttpServletRequest httpRequest, HttpServletResponse httpResponse) throws IOException, ServletException { // 512MB large download // 512 * 1024 * 1024 = 536870912 httpResponse.setStatus(200); httpResponse.setContentLength(HALF_GIG); httpResponse.setContentType("application/octet-stream"); httpResponse.flushBuffer(); final boolean wantFailure = httpRequest .getHeader("X-FAIL-TRANSFER") != null; final boolean wantSlow = httpRequest.getHeader("X-SLOW") != null; OutputStream os = httpResponse.getOutputStream(); for (int i = 0; i < HALF_GIG; i++) { os.write(i % 255); if (wantSlow) { try { Thread.sleep(300); } catch (InterruptedException ex) { // nuku } } if (wantFailure) { if (i > HALF_GIG / 2) { // kaboom // yes, response is commited, but Jetty does aborts and // drops connection httpResponse.sendError(500); break; } } } httpResponse.getOutputStream().flush(); httpResponse.getOutputStream().close(); } } // a /dev/null but counting how many bytes it ditched public static class CountingOutputStream extends OutputStream { private int byteCount = 0; @Override public void write(int b) throws IOException { // /dev/null byteCount++; } public int getByteCount() { return byteCount; } } // simple stream copy just to "consume". It closes streams. public static void copy(InputStream in, OutputStream out) throws IOException { byte[] buf = new byte[1024]; int len; while ((len = in.read(buf)) > 0) { out.write(buf, 0, len); } out.flush(); out.close(); in.close(); } public AbstractHandler configureHandler() throws Exception { return new SlowAndBigHandler(); } public AsyncHttpClientConfig getAsyncHttpClientConfig() { // for this test brevity's sake, we are limiting to 1 retries return new AsyncHttpClientConfig.Builder().setMaxRequestRetry(0) .setRequestTimeoutInMs(10000).build(); } @Test(groups = { "standalone", "default_provider" }) public void deferredSimple() throws IOException, ExecutionException, TimeoutException, InterruptedException { AsyncHttpClient client = getAsyncHttpClient(getAsyncHttpClientConfig()); AsyncHttpClient.BoundRequestBuilder r = client .prepareGet("http://127.0.0.1:" + port1 + "/deferredSimple"); CountingOutputStream cos = new CountingOutputStream(); BodyDeferringAsyncHandler bdah = new BodyDeferringAsyncHandler(cos); Future f = r.execute(bdah); Response resp = bdah.getResponse(); assertNotNull(resp); assertEquals(resp.getStatusCode(), HttpServletResponse.SC_OK); assertEquals( true, resp.getHeader("content-length").equals( String.valueOf(HALF_GIG))); // we got headers only, it's probably not all yet here (we have BIG file // downloading) assertEquals(true, HALF_GIG >= cos.getByteCount()); // now be polite and wait for body arrival too (otherwise we would be // dropping the "line" on server) f.get(); // it all should be here now assertEquals(true, HALF_GIG == cos.getByteCount()); client.close(); } @Test(groups = { "standalone", "default_provider" }, enabled = false) public void deferredSimpleWithFailure() throws IOException, ExecutionException, TimeoutException, InterruptedException { AsyncHttpClient client = getAsyncHttpClient(getAsyncHttpClientConfig()); AsyncHttpClient.BoundRequestBuilder r = client.prepareGet( "http://127.0.0.1:" + port1 + "/deferredSimpleWithFailure") .addHeader("X-FAIL-TRANSFER", Boolean.TRUE.toString()); CountingOutputStream cos = new CountingOutputStream(); BodyDeferringAsyncHandler bdah = new BodyDeferringAsyncHandler(cos); Future f = r.execute(bdah); Response resp = bdah.getResponse(); assertNotNull(resp); assertEquals(resp.getStatusCode(), HttpServletResponse.SC_OK); assertEquals( true, resp.getHeader("content-length").equals( String.valueOf(HALF_GIG))); // we got headers only, it's probably not all yet here (we have BIG file // downloading) assertEquals(true, HALF_GIG >= cos.getByteCount()); // now be polite and wait for body arrival too (otherwise we would be // dropping the "line" on server) try { f.get(); Assert.fail("get() should fail with IOException!"); } catch (Exception e) { // good } // it's incomplete, there was an error assertEquals(false, HALF_GIG == cos.getByteCount()); client.close(); } @Test(groups = { "standalone", "default_provider" }) public void deferredInputStreamTrick() throws IOException, ExecutionException, TimeoutException, InterruptedException { AsyncHttpClient client = getAsyncHttpClient(getAsyncHttpClientConfig()); AsyncHttpClient.BoundRequestBuilder r = client .prepareGet("http://127.0.0.1:" + port1 + "/deferredInputStreamTrick"); PipedOutputStream pos = new PipedOutputStream(); PipedInputStream pis = new PipedInputStream(pos); BodyDeferringAsyncHandler bdah = new BodyDeferringAsyncHandler(pos); Future f = r.execute(bdah); BodyDeferringInputStream is = new BodyDeferringInputStream(f, bdah, pis); Response resp = is.getAsapResponse(); assertNotNull(resp); assertEquals(resp.getStatusCode(), HttpServletResponse.SC_OK); assertEquals( true, resp.getHeader("content-length").equals( String.valueOf(HALF_GIG))); // "consume" the body, but our code needs input stream CountingOutputStream cos = new CountingOutputStream(); copy(is, cos); // now we don't need to be polite, since consuming and closing // BodyDeferringInputStream does all. // it all should be here now assertEquals(true, HALF_GIG == cos.getByteCount()); client.close(); } @Test(groups = { "standalone", "default_provider" }) public void deferredInputStreamTrickWithFailure() throws IOException, ExecutionException, TimeoutException, InterruptedException { AsyncHttpClient client = getAsyncHttpClient(getAsyncHttpClientConfig()); AsyncHttpClient.BoundRequestBuilder r = client.prepareGet( "http://127.0.0.1:" + port1 + "/deferredInputStreamTrickWithFailure").addHeader( "X-FAIL-TRANSFER", Boolean.TRUE.toString()); PipedOutputStream pos = new PipedOutputStream(); PipedInputStream pis = new PipedInputStream(pos); BodyDeferringAsyncHandler bdah = new BodyDeferringAsyncHandler(pos); Future f = r.execute(bdah); BodyDeferringInputStream is = new BodyDeferringInputStream(f, bdah, pis); Response resp = is.getAsapResponse(); assertNotNull(resp); assertEquals(resp.getStatusCode(), HttpServletResponse.SC_OK); assertEquals( true, resp.getHeader("content-length").equals( String.valueOf(HALF_GIG))); // "consume" the body, but our code needs input stream CountingOutputStream cos = new CountingOutputStream(); try { copy(is, cos); Assert.fail("InputStream consumption should fail with IOException!"); } catch (IOException e) { // good! } client.close(); } @Test(groups = { "standalone", "default_provider" }) public void testConnectionRefused() throws IOException, ExecutionException, TimeoutException, InterruptedException { int newPortWithoutAnyoneListening = findFreePort(); AsyncHttpClient client = getAsyncHttpClient(getAsyncHttpClientConfig()); AsyncHttpClient.BoundRequestBuilder r = client .prepareGet("http://127.0.0.1:" + newPortWithoutAnyoneListening + "/testConnectionRefused"); CountingOutputStream cos = new CountingOutputStream(); BodyDeferringAsyncHandler bdah = new BodyDeferringAsyncHandler(cos); r.execute(bdah); try { bdah.getResponse(); Assert.fail("IOException should be thrown here!"); } catch (IOException e) { // good } client.close(); } } async-http-client-1.6.5/src/test/java/com/ning/http/client/async/ByteBufferCapacityTest.java000066400000000000000000000120351166553056000320710ustar00rootroot00000000000000/* * Copyright (c) 2010-2011 Sonatype, Inc. All rights reserved. * * This program is licensed to you under the Apache License Version 2.0, * and you may not use this file except in compliance with the Apache License Version 2.0. * You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0. * * Unless required by applicable law or agreed to in writing, * software distributed under the Apache License Version 2.0 is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. */ package com.ning.http.client.async; import com.ning.http.client.AsyncHttpClient; import com.ning.http.client.HttpResponseBodyPart; import com.ning.http.client.Response; import org.eclipse.jetty.server.handler.AbstractHandler; import org.testng.annotations.Test; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.util.Enumeration; import java.util.UUID; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; import static org.testng.Assert.*; public abstract class ByteBufferCapacityTest extends AbstractBasicTest { private static final File TMP = new File(System.getProperty("java.io.tmpdir"), "ahc-tests-" + UUID.randomUUID().toString().substring(0, 8)); private class BasicHandler extends AbstractHandler { public void handle(String s, org.eclipse.jetty.server.Request r, HttpServletRequest httpRequest, HttpServletResponse httpResponse) throws IOException, ServletException { Enumeration e = httpRequest.getHeaderNames(); String param; while (e.hasMoreElements()) { param = e.nextElement().toString(); httpResponse.addHeader("X-" + param, httpRequest.getHeader(param)); } int size = 10 * 1024; if (httpRequest.getContentLength() > 0) { size = httpRequest.getContentLength(); } byte[] bytes = new byte[size]; if (bytes.length > 0) { httpRequest.getInputStream().read(bytes); httpResponse.getOutputStream().write(bytes); } httpResponse.setStatus(200); httpResponse.getOutputStream().flush(); httpResponse.getOutputStream().close(); } } @Override public AbstractHandler configureHandler() throws Exception { return new BasicHandler(); } @Test(groups = {"standalone", "default_provider"}) public void basicByteBufferTest() throws Throwable { AsyncHttpClient c = getAsyncHttpClient(null); final AtomicBoolean completed = new AtomicBoolean(false); byte[] bytes = "RatherLargeFileRatherLargeFileRatherLargeFileRatherLargeFile".getBytes("UTF-16"); long repeats = (1024 * 100 * 10 / bytes.length) + 1; File largeFile = createTempFile(bytes, (int) repeats); final AtomicInteger byteReceived = new AtomicInteger(); try { Response response = c.preparePut(getTargetUrl()).setBody(largeFile) .execute(new AsyncCompletionHandlerAdapter() { /* @Override */ public STATE onBodyPartReceived(final HttpResponseBodyPart content) throws Exception { byteReceived.addAndGet(content.getBodyByteBuffer().capacity()); return super.onBodyPartReceived(content); } }).get(); assertNotNull(response); assertEquals(response.getStatusCode(), 200); assertEquals(response.getResponseBody().length(), largeFile.length()); assertEquals(byteReceived.get(), largeFile.length()); } catch (IOException ex) { fail("Should have timed out"); } c.close(); } public String getTargetUrl() { return String.format("http://127.0.0.1:%d/foo/test", port1); } public static File createTempFile(byte[] pattern, int repeat) throws IOException { TMP.mkdirs(); TMP.deleteOnExit(); File tmpFile = File.createTempFile("tmpfile-", ".data", TMP); write(pattern, repeat, tmpFile); return tmpFile; } public static void write(byte[] pattern, int repeat, File file) throws IOException { file.deleteOnExit(); file.getParentFile().mkdirs(); FileOutputStream out = null; try { out = new FileOutputStream(file); for (int i = 0; i < repeat; i++) { out.write(pattern); } } finally { if (out != null) { out.close(); } } } } async-http-client-1.6.5/src/test/java/com/ning/http/client/async/ChunkingTest.java000066400000000000000000000144421166553056000301300ustar00rootroot00000000000000/* * Copyright (c) 2010-2011 Sonatype, Inc. All rights reserved. * * This program is licensed to you under the Apache License Version 2.0, * and you may not use this file except in compliance with the Apache License Version 2.0. * You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0. * * Unless required by applicable law or agreed to in writing, * software distributed under the Apache License Version 2.0 is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. */ package com.ning.http.client.async; import com.ning.http.client.AsyncHttpClient; import com.ning.http.client.AsyncHttpClientConfig; import com.ning.http.client.ListenableFuture; import com.ning.http.client.RequestBuilder; import com.ning.http.client.Response; import com.ning.http.client.generators.InputStreamBodyGenerator; import org.testng.annotations.Test; import java.io.BufferedInputStream; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.InputStream; import java.net.URL; import java.util.Random; import static org.testng.Assert.assertNotNull; import static org.testng.AssertJUnit.assertEquals; import static org.testng.AssertJUnit.assertTrue; import static org.testng.FileAssert.fail; /** * Test that the url fetcher is able to communicate via a proxy * * @author dominict */ abstract public class ChunkingTest extends AbstractBasicTest { // So we can just test the returned data is the image, // and doesn't contain the chunked delimeters. public static byte[] LARGE_IMAGE_BYTES; static { ByteArrayOutputStream baos = new ByteArrayOutputStream(); InputStream instream = null; try { ClassLoader cl = ChunkingTest.class.getClassLoader(); // override system properties URL url = cl.getResource("300k.png"); File sourceFile = new File(url.toURI()); instream = new FileInputStream(sourceFile); byte[] buf = new byte[8092]; int len = 0; while ((len = instream.read(buf)) > 0) { baos.write(buf, 0, len); } LARGE_IMAGE_BYTES = baos.toByteArray(); } catch (Throwable e) { LARGE_IMAGE_BYTES = new byte[265495]; Random x = new Random(); x.nextBytes(LARGE_IMAGE_BYTES); } } /** * Tests that the custom chunked stream result in success and * content returned that is unchunked */ @Test() public void testCustomChunking() throws Throwable { doTest(true); } private void doTest(boolean customChunkedInputStream) throws Exception { AsyncHttpClient c = null; try { AsyncHttpClientConfig.Builder bc = new AsyncHttpClientConfig.Builder(); bc.setAllowPoolingConnection(true); bc.setMaximumConnectionsPerHost(1); bc.setMaximumConnectionsTotal(1); bc.setConnectionTimeoutInMs(1000); bc.setRequestTimeoutInMs(1000); bc.setFollowRedirects(true); c = getAsyncHttpClient(bc.build()); RequestBuilder builder = new RequestBuilder("POST"); builder.setUrl(getTargetUrl()); if (customChunkedInputStream) { // made buff in stream big enough to mark. builder.setBody(new InputStreamBodyGenerator(new BufferedInputStream(new FileInputStream(getTestFile()), 400000))); } else { // made buff in stream big enough to mark. builder.setBody(new InputStreamBodyGenerator(new BufferedInputStream(new FileInputStream(getTestFile()), 400000))); } com.ning.http.client.Request r = builder.build(); Response res = null; try { ListenableFuture response = c.executeRequest(r); res = response.get(); assertNotNull(res.getResponseBodyAsStream()); if (500 == res.getStatusCode()) { System.out.println("=============="); System.out.println("500 response from call"); System.out.println("Headers:" + res.getHeaders()); System.out.println("=============="); System.out.flush(); assertEquals("Should have 500 status code", 500, res.getStatusCode()); assertTrue("Should have failed due to chunking", res.getHeader("X-Exception").contains("invalid.chunk.length")); fail("HARD Failing the test due to provided InputStreamBodyGenerator, chunking incorrectly:" + res.getHeader("X-Exception")); } else { assertEquals(LARGE_IMAGE_BYTES, readInputStreamToBytes(res.getResponseBodyAsStream())); } } catch (Exception e) { fail("Exception Thrown:" + e.getMessage()); } } finally { if (c != null) c.close(); } } private byte[] readInputStreamToBytes(InputStream stream) { byte[] data = new byte[0]; ByteArrayOutputStream buffer = new ByteArrayOutputStream(); try { int nRead; byte[] tmp = new byte[8192]; while ((nRead = stream.read(tmp, 0, tmp.length)) != -1) { buffer.write(tmp, 0, nRead); } buffer.flush(); data = buffer.toByteArray(); } catch (Exception e) { } finally { try { stream.close(); } catch (Exception e2) { } return data; } } private static File getTestFile() { String testResource1 = "300k.png"; File testResource1File = null; try { ClassLoader cl = ChunkingTest.class.getClassLoader(); URL url = cl.getResource(testResource1); testResource1File = new File(url.toURI()); } catch (Throwable e) { // TODO Auto-generated catch block fail("unable to find " + testResource1); } return testResource1File; } } async-http-client-1.6.5/src/test/java/com/ning/http/client/async/ComplexClientTest.java000066400000000000000000000043211166553056000311230ustar00rootroot00000000000000/* * Copyright 2010 Ning, Inc. * * Ning licenses this file to you 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. */ package com.ning.http.client.async; import com.ning.http.client.AsyncHttpClient; import com.ning.http.client.Response; import org.testng.annotations.Test; import java.util.concurrent.TimeUnit; import static org.testng.Assert.assertEquals; public abstract class ComplexClientTest extends AbstractBasicTest { @Test(groups = {"standalone", "default_provider"}) public void multipleRequestsTest() throws Throwable { AsyncHttpClient c = getAsyncHttpClient(null); String body = "hello there"; // once Response response = c.preparePost(getTargetUrl()) .setBody(body) .setHeader("Content-Type", "text/html") .execute().get(TIMEOUT, TimeUnit.SECONDS); assertEquals(response.getResponseBody(), body); // twice response = c.preparePost(getTargetUrl()) .setBody(body) .setHeader("Content-Type", "text/html") .execute().get(TIMEOUT, TimeUnit.SECONDS); assertEquals(response.getResponseBody(), body); c.close(); } @Test(groups = {"standalone", "default_provider"}) public void urlWithoutSlashTest() throws Throwable { AsyncHttpClient c = getAsyncHttpClient(null); String body = "hello there"; // once Response response = c.preparePost(String.format("http://127.0.0.1:%d/foo/test", port1)) .setBody(body) .setHeader("Content-Type", "text/html") .execute().get(TIMEOUT, TimeUnit.SECONDS); assertEquals(response.getResponseBody(), body); c.close(); } } async-http-client-1.6.5/src/test/java/com/ning/http/client/async/ConnectionPoolTest.java000066400000000000000000000310211166553056000313030ustar00rootroot00000000000000/* * Copyright 2010 Ning, Inc. * * Ning licenses this file to you 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. */ package com.ning.http.client.async; import com.ning.http.client.AsyncCompletionHandler; import com.ning.http.client.AsyncCompletionHandlerBase; import com.ning.http.client.AsyncHttpClient; import com.ning.http.client.AsyncHttpClientConfig; import com.ning.http.client.ConnectionsPool; import com.ning.http.client.Response; import org.jboss.netty.channel.Channel; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.testng.Assert; import org.testng.annotations.Test; import java.io.IOException; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertNotNull; import static org.testng.Assert.assertNull; import static org.testng.Assert.fail; public abstract class ConnectionPoolTest extends AbstractBasicTest { protected final Logger log = LoggerFactory.getLogger(AbstractBasicTest.class); @Test(groups = {"standalone", "default_provider"}) public void testMaxTotalConnections() { AsyncHttpClient client = getAsyncHttpClient( new AsyncHttpClientConfig.Builder() .setAllowPoolingConnection(true) .setMaximumConnectionsTotal(1) .build() ); String url = getTargetUrl(); int i; Exception exception = null; for (i = 0; i < 3; i++) { try { log.info("{} requesting url [{}]...", i, url); Response response = client.prepareGet(url).execute().get(); log.info("{} response [{}].", i, response); } catch (Exception ex) { exception = ex; } } assertNull(exception); } @Test(groups = {"standalone", "default_provider"}) public void testMaxTotalConnectionsException() { AsyncHttpClient client = getAsyncHttpClient( new AsyncHttpClientConfig.Builder() .setAllowPoolingConnection(true) .setMaximumConnectionsTotal(1) .build() ); String url = getTargetUrl(); int i; Exception exception = null; for (i = 0; i < 20; i++) { try { log.info("{} requesting url [{}]...", i, url); if (i < 5) { client.prepareGet(url).execute().get(); } else { client.prepareGet(url).execute(); } } catch (Exception ex) { exception = ex; break; } } assertNotNull(exception); assertNotNull(exception.getMessage()); assertEquals(exception.getMessage(),"Too many connections 1"); } @Test(groups = {"standalone", "default_provider", "async"}, enabled = true, invocationCount = 10, alwaysRun = true) public void asyncDoGetKeepAliveHandlerTest_channelClosedDoesNotFail() throws Throwable { AsyncHttpClient client = getAsyncHttpClient(null); // Use a l in case the assert fail final CountDownLatch l = new CountDownLatch(2); final Map remoteAddresses = new ConcurrentHashMap(); AsyncCompletionHandler handler = new AsyncCompletionHandlerAdapter() { @Override public Response onCompleted(Response response) throws Exception { System.out.println("ON COMPLETED INVOKED " + response.getHeader("X-KEEP-ALIVE")); try { assertEquals(response.getStatusCode(), 200); remoteAddresses.put(response.getHeader("X-KEEP-ALIVE"), true); } finally { l.countDown(); } return response; } }; client.prepareGet(getTargetUrl()).execute(handler).get(); server.stop(); server.start(); client.prepareGet(getTargetUrl()).execute(handler); if (!l.await(TIMEOUT, TimeUnit.SECONDS)) { Assert.fail("Timed out"); } assertEquals(remoteAddresses.size(), 2); client.close(); } @Test(groups = {"standalone", "default_provider"}) public void testInvalidConnectionsPool() { ConnectionsPool cp = new ConnectionsPool() { public boolean offer(String key, Channel connection) { return false; } public Channel poll(String connection) { return null; } public boolean removeAll(Channel connection) { return false; } public boolean canCacheConnection() { return false; } public void destroy() { } }; AsyncHttpClient client = getAsyncHttpClient( new AsyncHttpClientConfig.Builder() .setConnectionsPool(cp) .build() ); Exception exception = null; try { client.prepareGet(getTargetUrl()).execute().get(TIMEOUT, TimeUnit.SECONDS); } catch (Exception ex) { ex.printStackTrace(); exception = ex; } assertNotNull(exception); assertEquals(exception.getMessage(), "Too many connections -1"); client.close(); } @Test(groups = {"standalone", "default_provider"}) public void testValidConnectionsPool() { ConnectionsPool cp = new ConnectionsPool() { public boolean offer(String key, Channel connection) { return true; } public Channel poll(String connection) { return null; } public boolean removeAll(Channel connection) { return false; } public boolean canCacheConnection() { return true; } public void destroy() { } }; AsyncHttpClient client = getAsyncHttpClient( new AsyncHttpClientConfig.Builder() .setConnectionsPool(cp) .build() ); Exception exception = null; try { client.prepareGet(getTargetUrl()).execute().get(TIMEOUT, TimeUnit.SECONDS); } catch (Exception ex) { ex.printStackTrace(); exception = ex; } assertNull(exception); client.close(); } @Test(groups = {"standalone", "default_provider"}) public void multipleMaxConnectionOpenTest() throws Throwable { AsyncHttpClientConfig cg = new AsyncHttpClientConfig.Builder().setAllowPoolingConnection(true) .setConnectionTimeoutInMs(5000).setMaximumConnectionsTotal(1).build(); AsyncHttpClient c = getAsyncHttpClient(cg); String body = "hello there"; // once Response response = c.preparePost(getTargetUrl()) .setBody(body) .execute().get(TIMEOUT, TimeUnit.SECONDS); assertEquals(response.getResponseBody(), body); // twice Exception exception = null; try { c.preparePost(String.format("http://127.0.0.1:%d/foo/test", port2)).setBody(body).execute().get(TIMEOUT, TimeUnit.SECONDS); fail("Should throw exception. Too many connections issued."); } catch (Exception ex) { ex.printStackTrace(); exception = ex; } assertNotNull(exception); assertEquals(exception.getMessage(), "Too many connections 1"); c.close(); } @Test(groups = {"standalone", "default_provider"}) public void multipleMaxConnectionOpenTestWithQuery() throws Throwable { AsyncHttpClientConfig cg = new AsyncHttpClientConfig.Builder().setAllowPoolingConnection(true) .setConnectionTimeoutInMs(5000).setMaximumConnectionsTotal(1).build(); AsyncHttpClient c = getAsyncHttpClient(cg); String body = "hello there"; // once Response response = c.preparePost(getTargetUrl() + "?foo=bar") .setBody(body) .execute().get(TIMEOUT, TimeUnit.SECONDS); assertEquals(response.getResponseBody(), "foo_" + body); // twice Exception exception = null; try { response = c.preparePost(getTargetUrl()).setBody(body).execute().get(TIMEOUT, TimeUnit.SECONDS); } catch (Exception ex) { ex.printStackTrace(); exception = ex; } assertNull(exception); assertNotNull(response); assertEquals(response.getStatusCode(), 200); c.close(); } /** * This test just make sure the hack used to catch disconnected channel under win7 doesn't throw any exception. * The onComplete method must be only called once. * * @throws Throwable if something wrong happens. */ @Test(groups = {"standalone", "default_provider"}) public void win7DisconnectTest() throws Throwable { final AtomicInteger count = new AtomicInteger(0); AsyncHttpClient client = getAsyncHttpClient(new AsyncHttpClientConfig.Builder().build()); AsyncCompletionHandler handler = new AsyncCompletionHandlerAdapter() { @Override public Response onCompleted(Response response) throws Exception { count.incrementAndGet(); StackTraceElement e = new StackTraceElement("sun.nio.ch.SocketDispatcher", "read0", null, -1); IOException t = new IOException(); t.setStackTrace(new StackTraceElement[]{e}); throw t; } }; try { client.prepareGet(getTargetUrl()).execute(handler).get(); fail("Must have received an exception"); } catch (ExecutionException ex) { assertNotNull(ex); assertNotNull(ex.getCause()); assertEquals(ex.getCause().getCause().getClass(), IOException.class); assertEquals(count.get(), 1); } client.close(); } @Test(groups = {"standalone", "default_provider"}) public void asyncHandlerOnThrowableTest() throws Throwable { AsyncHttpClient client = getAsyncHttpClient(new AsyncHttpClientConfig.Builder().build()); final AtomicInteger count = new AtomicInteger(); final String THIS_IS_NOT_FOR_YOU = "This is not for you"; final CountDownLatch latch = new CountDownLatch(16); for (int i = 0; i < 16; i++) { client.prepareGet(getTargetUrl()).execute(new AsyncCompletionHandlerBase() { @Override public Response onCompleted(Response response) throws Exception { throw new Exception(THIS_IS_NOT_FOR_YOU); } }); client.prepareGet(getTargetUrl()).execute(new AsyncCompletionHandlerBase() { /* @Override */ public void onThrowable(Throwable t) { if (t.getMessage() != null && t.getMessage().equalsIgnoreCase(THIS_IS_NOT_FOR_YOU)) { count.incrementAndGet(); } } @Override public Response onCompleted(Response response) throws Exception { latch.countDown(); return response; } }); } latch.await(TIMEOUT, TimeUnit.SECONDS); assertEquals(count.get(), 0); client.close(); } } async-http-client-1.6.5/src/test/java/com/ning/http/client/async/DigestAuthTest.java000066400000000000000000000153531166553056000304250ustar00rootroot00000000000000/* * Copyright (c) 2010-2011 Sonatype, Inc. All rights reserved. * * This program is licensed to you under the Apache License Version 2.0, * and you may not use this file except in compliance with the Apache License Version 2.0. * You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0. * * Unless required by applicable law or agreed to in writing, * software distributed under the Apache License Version 2.0 is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. */ package com.ning.http.client.async; import com.ning.http.client.AsyncHttpClient; import com.ning.http.client.Realm; import com.ning.http.client.Response; import org.apache.log4j.ConsoleAppender; import org.apache.log4j.Level; import org.apache.log4j.Logger; import org.apache.log4j.PatternLayout; import org.eclipse.jetty.http.security.Constraint; import org.eclipse.jetty.security.ConstraintMapping; import org.eclipse.jetty.security.ConstraintSecurityHandler; import org.eclipse.jetty.security.HashLoginService; import org.eclipse.jetty.security.LoginService; import org.eclipse.jetty.security.authentication.DigestAuthenticator; 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.testng.annotations.BeforeClass; import org.testng.annotations.Test; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.util.Arrays; import java.util.HashSet; import java.util.Set; import java.util.concurrent.ExecutionException; import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertNotNull; public abstract class DigestAuthTest extends AbstractBasicTest { private final static String user = "user"; private final static String admin = "admin"; @BeforeClass(alwaysRun = true) @Override public void setUpGlobal() throws Exception { server = new Server(); Logger root = Logger.getRootLogger(); root.setLevel(Level.DEBUG); root.addAppender(new ConsoleAppender( new PatternLayout(PatternLayout.TTCC_CONVERSION_PATTERN))); port1 = findFreePort(); Connector listener = new SelectChannelConnector(); listener.setHost("127.0.0.1"); listener.setPort(port1); server.addConnector(listener); LoginService loginService = new HashLoginService("MyRealm", "src/test/resources/realm.properties"); server.addBean(loginService); Constraint constraint = new Constraint(); constraint.setName(Constraint.__BASIC_AUTH); constraint.setRoles(new String[]{user, admin}); constraint.setAuthenticate(true); ConstraintMapping mapping = new ConstraintMapping(); mapping.setConstraint(constraint); mapping.setPathSpec("/*"); Set knownRoles = new HashSet(); knownRoles.add(user); knownRoles.add(admin); ConstraintSecurityHandler security = new ConstraintSecurityHandler(); security.setConstraintMappings(new ConstraintMapping[]{mapping}, knownRoles); security.setAuthenticator(new DigestAuthenticator()); security.setLoginService(loginService); security.setStrict(false); security.setHandler(configureHandler()); server.setHandler(security); server.start(); log.info("Local HTTP server started successfully"); } private class SimpleHandler extends AbstractHandler { public void handle(String s, Request r, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { response.addHeader("X-Auth", request.getHeader("Authorization")); response.setStatus(200); response.getOutputStream().flush(); response.getOutputStream().close(); } } @Test(groups = {"standalone", "default_provider"}) public void digestAuthTest() throws IOException, ExecutionException, TimeoutException, InterruptedException { AsyncHttpClient client = getAsyncHttpClient(null); AsyncHttpClient.BoundRequestBuilder r = client.prepareGet("http://127.0.0.1:" + port1 + "/") .setRealm((new Realm.RealmBuilder()).setPrincipal(user) .setPassword(admin) .setRealmName("MyRealm") .setScheme(Realm.AuthScheme.DIGEST).build()); Future f = r.execute(); Response resp = f.get(60, TimeUnit.SECONDS); assertNotNull(resp); assertEquals(resp.getStatusCode(), HttpServletResponse.SC_OK); assertNotNull(resp.getHeader("X-Auth")); client.close(); } @Test(groups = {"standalone", "default_provider"}) public void digestAuthTestWithoutScheme() throws IOException, ExecutionException, TimeoutException, InterruptedException { AsyncHttpClient client = getAsyncHttpClient(null); AsyncHttpClient.BoundRequestBuilder r = client.prepareGet("http://127.0.0.1:" + port1 + "/") .setRealm((new Realm.RealmBuilder()).setPrincipal(user) .setPassword(admin) .setRealmName("MyRealm").build()); Future f = r.execute(); Response resp = f.get(60, TimeUnit.SECONDS); assertNotNull(resp); assertEquals(resp.getStatusCode(), HttpServletResponse.SC_OK); assertNotNull(resp.getHeader("X-Auth")); client.close(); } @Test(groups = {"standalone", "default_provider"}) public void digestAuthNegativeTest() throws IOException, ExecutionException, TimeoutException, InterruptedException { AsyncHttpClient client = getAsyncHttpClient(null); AsyncHttpClient.BoundRequestBuilder r = client.prepareGet("http://127.0.0.1:" + port1 + "/") .setRealm((new Realm.RealmBuilder()).setPrincipal("fake").setPassword(admin).setScheme(Realm.AuthScheme.DIGEST).build()); Future f = r.execute(); Response resp = f.get(20, TimeUnit.SECONDS); assertNotNull(resp); assertEquals(resp.getStatusCode(), 401); client.close(); } @Override public AbstractHandler configureHandler() throws Exception { return new SimpleHandler(); } } async-http-client-1.6.5/src/test/java/com/ning/http/client/async/EmptyBodyTest.java000066400000000000000000000123711166553056000302750ustar00rootroot00000000000000/* * Copyright 2010 Ning, Inc. * * Ning licenses this file to you 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. */ package com.ning.http.client.async; import com.ning.http.client.AsyncHandler; import com.ning.http.client.AsyncHttpClient; import com.ning.http.client.HttpResponseBodyPart; import com.ning.http.client.HttpResponseHeaders; import com.ning.http.client.HttpResponseStatus; import com.ning.http.client.Response; import org.eclipse.jetty.server.Request; import org.eclipse.jetty.server.handler.AbstractHandler; import org.testng.annotations.Test; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.InputStream; import java.util.concurrent.CountDownLatch; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertFalse; import static org.testng.Assert.assertTrue; import static org.testng.Assert.assertNotNull; import static org.testng.Assert.fail; /** * Tests case where response doesn't have body. * * @author Hubert Iwaniuk */ public abstract class EmptyBodyTest extends AbstractBasicTest { private class NoBodyResponseHandler extends AbstractHandler { public void handle( String s, Request request, HttpServletRequest req, HttpServletResponse resp) throws IOException, ServletException { if (!req.getMethod().equalsIgnoreCase("PUT")) { resp.setStatus(HttpServletResponse.SC_OK); } else { resp.setStatus(204); } request.setHandled(true); } } @Override public AbstractHandler configureHandler() throws Exception { return new NoBodyResponseHandler(); } @Test(groups = {"standalone", "default_provider"}) public void testEmptyBody() throws IOException { AsyncHttpClient ahc = getAsyncHttpClient(null); final AtomicBoolean err = new AtomicBoolean(false); final LinkedBlockingQueue queue = new LinkedBlockingQueue(); final AtomicBoolean status = new AtomicBoolean(false); final AtomicInteger headers = new AtomicInteger(0); final CountDownLatch latch = new CountDownLatch(1); ahc.executeRequest(ahc.prepareGet(getTargetUrl()).build(), new AsyncHandler() { public void onThrowable(Throwable t) { fail("Got throwable.", t); err.set(true); } public STATE onBodyPartReceived(HttpResponseBodyPart e) throws Exception { String s = new String(e.getBodyPartBytes()); log.info("got part: {}", s); if (s.equals("")) { //noinspection ThrowableInstanceNeverThrown log.warn("Sampling stacktrace.", new Throwable("trace that, we should not get called for empty body.")); } queue.put(s); return STATE.CONTINUE; } public STATE onStatusReceived(HttpResponseStatus e) throws Exception { status.set(true); return AsyncHandler.STATE.CONTINUE; } public STATE onHeadersReceived(HttpResponseHeaders e) throws Exception { if (headers.incrementAndGet() == 2) { throw new Exception("Analyze this."); } return STATE.CONTINUE; } public Object onCompleted() throws Exception { latch.countDown(); return null; } }); try { assertTrue(latch.await(1, TimeUnit.SECONDS), "Latch failed."); } catch (InterruptedException e) { fail("Interrupted.", e); } assertFalse(err.get()); assertEquals(queue.size(), 0); assertTrue(status.get()); assertEquals(headers.get(), 1); ahc.close(); } @Test(groups = {"standalone", "default_provider"}) public void testPutEmptyBody() throws Throwable { AsyncHttpClient ahc = getAsyncHttpClient(null); Response response = ahc.preparePut(getTargetUrl()).setBody("String").execute().get(); assertNotNull(response); assertEquals(response.getStatusCode(), 204); assertEquals(response.getResponseBody(), ""); assertTrue(InputStream.class.isAssignableFrom(response.getResponseBodyAsStream().getClass())); assertEquals(response.getResponseBodyAsStream().read(), -1); ahc.close(); } } async-http-client-1.6.5/src/test/java/com/ning/http/client/async/ErrorResponseTest.java000066400000000000000000000053611166553056000311720ustar00rootroot00000000000000/* * Copyright 2010 Ning, Inc. * * Ning licenses this file to you 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. * */ package com.ning.http.client.async; import com.ning.http.client.AsyncHttpClient; import com.ning.http.client.Response; import org.eclipse.jetty.server.Request; import org.eclipse.jetty.server.handler.AbstractHandler; import org.testng.annotations.Test; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.OutputStream; import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertNotNull; /** * Tests to reproduce issues with handling of error responses * * @author Tatu Saloranta */ public abstract class ErrorResponseTest extends AbstractBasicTest { final static String BAD_REQUEST_STR = "Very Bad Request! No cookies."; private static class ErrorHandler extends AbstractHandler { public void handle(String s, Request r, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { try { Thread.sleep(210L); } catch (InterruptedException e) { } response.setContentType("text/plain"); response.setStatus(400); OutputStream out = response.getOutputStream(); out.write(BAD_REQUEST_STR.getBytes("UTF-8")); out.flush(); } } @Override public AbstractHandler configureHandler() throws Exception { return new ErrorHandler(); } @Test(groups = {"standalone", "default_provider"}) public void testQueryParameters() throws Exception { AsyncHttpClient client = getAsyncHttpClient(null); Future f = client .prepareGet("http://127.0.0.1:" + port1 + "/foo") .addHeader("Accepts", "*/*") .execute(); Response resp = f.get(3, TimeUnit.SECONDS); assertNotNull(resp); assertEquals(resp.getStatusCode(), 400); String respStr = resp.getResponseBody(); assertEquals(BAD_REQUEST_STR, respStr); client.close(); } } async-http-client-1.6.5/src/test/java/com/ning/http/client/async/Expect100ContinueTest.java000066400000000000000000000055621166553056000315430ustar00rootroot00000000000000/* * Copyright 2010 Ning, Inc. * * Ning licenses this file to you 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. */ package com.ning.http.client.async; import com.ning.http.client.AsyncHttpClient; import com.ning.http.client.Response; import org.eclipse.jetty.server.Request; import org.eclipse.jetty.server.handler.AbstractHandler; import org.testng.annotations.Test; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.File; import java.io.IOException; import java.net.URL; import java.util.concurrent.Future; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertNotNull; /** * Test the Expect: 100-Continue. */ public abstract class Expect100ContinueTest extends AbstractBasicTest { private class ZeroCopyHandler extends AbstractHandler { public void handle(String s, Request r, HttpServletRequest httpRequest, HttpServletResponse httpResponse) throws IOException, ServletException { int size = 10 * 1024; if (httpRequest.getContentLength() > 0) { size = httpRequest.getContentLength(); } byte[] bytes = new byte[size]; if (bytes.length > 0) { httpRequest.getInputStream().read(bytes); httpResponse.getOutputStream().write(bytes); } httpResponse.setStatus(200); httpResponse.getOutputStream().flush(); } } @Test(groups = {"standalone", "default_provider"}) public void Expect100Continue() throws Throwable { AsyncHttpClient client = getAsyncHttpClient(null); ClassLoader cl = getClass().getClassLoader(); URL url = cl.getResource("SimpleTextFile.txt"); File file = new File(url.toURI()); Future f = client.preparePut("http://127.0.0.1:" + port1 + "/").setHeader("Expect", "100-continue").setBody(file).execute(); Response resp = f.get(); assertNotNull(resp); assertEquals(resp.getStatusCode(), HttpServletResponse.SC_OK); assertEquals(resp.getResponseBody(), "This is a simple test file"); client.close(); } @Override public AbstractHandler configureHandler() throws Exception { return new ZeroCopyHandler(); } } async-http-client-1.6.5/src/test/java/com/ning/http/client/async/FilePartLargeFileTest.java000066400000000000000000000127331166553056000316440ustar00rootroot00000000000000/* * Copyright (c) 2010-2011 Sonatype, Inc. All rights reserved. * * This program is licensed to you under the Apache License Version 2.0, * and you may not use this file except in compliance with the Apache License Version 2.0. * You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0. * * Unless required by applicable law or agreed to in writing, * software distributed under the Apache License Version 2.0 is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. */ package com.ning.http.client.async; import com.ning.http.client.AsyncHttpClient; import com.ning.http.client.AsyncHttpClient.BoundRequestBuilder; import com.ning.http.client.AsyncHttpClientConfig; import com.ning.http.client.FilePart; import com.ning.http.client.Response; import org.eclipse.jetty.server.Request; import org.eclipse.jetty.server.handler.AbstractHandler; import org.testng.Assert; import org.testng.annotations.AfterMethod; import org.testng.annotations.Test; import javax.servlet.ServletException; import javax.servlet.ServletInputStream; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.net.URL; import java.util.UUID; import static org.testng.FileAssert.fail; public abstract class FilePartLargeFileTest extends AbstractBasicTest { private File largeFile; @Test(groups = {"standalone", "default_provider"}, enabled = true) public void testPutImageFile() throws Exception { largeFile = getTestFile(); AsyncHttpClientConfig config = new AsyncHttpClientConfig.Builder().setRequestTimeoutInMs(100 * 6000).build(); AsyncHttpClient client = getAsyncHttpClient(config); BoundRequestBuilder rb = client.preparePut(getTargetUrl()); rb.addBodyPart(new FilePart("test", largeFile, "application/octet-stream" , "UTF-8")); Response response = rb.execute().get(); Assert.assertEquals(200, response.getStatusCode()); client.close(); } @Test(groups = {"standalone", "default_provider"}, enabled = true) public void testPutLargeTextFile() throws Exception { byte[] bytes = "RatherLargeFileRatherLargeFileRatherLargeFileRatherLargeFile".getBytes("UTF-16"); long repeats = (1024 * 1024 / bytes.length) + 1; largeFile = createTempFile(bytes, (int) repeats); AsyncHttpClientConfig config = new AsyncHttpClientConfig.Builder().build(); AsyncHttpClient client = getAsyncHttpClient(config); BoundRequestBuilder rb = client.preparePut(getTargetUrl()); rb.addBodyPart(new FilePart("test", largeFile, "application/octet-stream" , "UTF-8")); Response response = rb.execute().get(); Assert.assertEquals(200, response.getStatusCode()); client.close(); } private static File getTestFile() { String testResource1 = "300k.png"; File testResource1File = null; try { ClassLoader cl = ChunkingTest.class.getClassLoader(); URL url = cl.getResource(testResource1); testResource1File = new File(url.toURI()); } catch (Throwable e) { // TODO Auto-generated catch block fail("unable to find " + testResource1); } return testResource1File; } @AfterMethod public void after() { largeFile.delete(); } @Override public AbstractHandler configureHandler() throws Exception { return new AbstractHandler() { public void handle(String arg0, Request arg1, HttpServletRequest req, HttpServletResponse resp) throws IOException, ServletException { ServletInputStream in = req.getInputStream(); byte[] b = new byte[8192]; int count = -1; int total = 0; while ((count = in.read(b)) != -1) { b = new byte[8192]; total += count; } System.err.println("consumed " + total + " bytes."); resp.setStatus(200); resp.addHeader("X-TRANFERED", String.valueOf(total)); resp.getOutputStream().flush(); resp.getOutputStream().close(); arg1.setHandled(true); } }; } private static final File TMP = new File(System.getProperty("java.io.tmpdir"), "ahc-tests-" + UUID.randomUUID().toString().substring(0, 8)); public static File createTempFile(byte[] pattern, int repeat) throws IOException { TMP.mkdirs(); TMP.deleteOnExit(); File tmpFile = File.createTempFile("tmpfile-", ".data", TMP); tmpFile.deleteOnExit(); write(pattern, repeat, tmpFile); return tmpFile; } public static void write(byte[] pattern, int repeat, File file) throws IOException { file.deleteOnExit(); file.getParentFile().mkdirs(); FileOutputStream out = null; try { out = new FileOutputStream(file); for (int i = 0; i < repeat; i++) { out.write(pattern); } } finally { if (out != null) { out.close(); } } } } async-http-client-1.6.5/src/test/java/com/ning/http/client/async/FilterTest.java000066400000000000000000000171771166553056000276170ustar00rootroot00000000000000/* * Copyright (c) 2010-2011 Sonatype, Inc. All rights reserved. * * This program is licensed to you under the Apache License Version 2.0, * and you may not use this file except in compliance with the Apache License Version 2.0. * You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0. * * Unless required by applicable law or agreed to in writing, * software distributed under the Apache License Version 2.0 is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. */ package com.ning.http.client.async; import com.ning.http.client.AsyncHttpClient; import com.ning.http.client.AsyncHttpClientConfig; import com.ning.http.client.Request; import com.ning.http.client.RequestBuilder; import com.ning.http.client.Response; import com.ning.http.client.extra.ThrottleRequestFilter; import com.ning.http.client.filter.FilterContext; import com.ning.http.client.filter.FilterException; import com.ning.http.client.filter.ResponseFilter; import org.eclipse.jetty.server.handler.AbstractHandler; import org.testng.annotations.Test; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.util.ArrayList; import java.util.Enumeration; import java.util.List; import java.util.concurrent.Future; import java.util.concurrent.atomic.AtomicBoolean; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertNotNull; import static org.testng.Assert.fail; public abstract class FilterTest extends AbstractBasicTest { private class BasicHandler extends AbstractHandler { public void handle(String s, org.eclipse.jetty.server.Request r, HttpServletRequest httpRequest, HttpServletResponse httpResponse) throws IOException, ServletException { Enumeration e = httpRequest.getHeaderNames(); String param; while (e.hasMoreElements()) { param = e.nextElement().toString(); httpResponse.addHeader(param, httpRequest.getHeader(param)); } httpResponse.setStatus(200); httpResponse.getOutputStream().flush(); httpResponse.getOutputStream().close(); } } @Override public AbstractHandler configureHandler() throws Exception { return new BasicHandler(); } @Test(groups = {"standalone", "default_provider"}) public void basicTest() throws Throwable { AsyncHttpClientConfig.Builder b = new AsyncHttpClientConfig.Builder(); b.addRequestFilter(new ThrottleRequestFilter(100)); AsyncHttpClient c = getAsyncHttpClient(b.build()); Response response = c.preparePost(getTargetUrl()) .execute().get(); assertNotNull(response); assertEquals(response.getStatusCode(), 200); c.close(); } @Test(groups = {"standalone", "default_provider"}) public void loadThrottleTest() throws Throwable { AsyncHttpClientConfig.Builder b = new AsyncHttpClientConfig.Builder(); b.addRequestFilter(new ThrottleRequestFilter(10)); AsyncHttpClient c = getAsyncHttpClient(b.build()); List> futures = new ArrayList>(); for (int i = 0; i < 200; i++) { futures.add(c.preparePost(getTargetUrl()).execute()); } for (Future f : futures) { Response r = f.get(); assertNotNull(f.get()); assertEquals(r.getStatusCode(), 200); } c.close(); } @Test(groups = {"standalone", "default_provider"}) public void maxConnectionsText() throws Throwable { AsyncHttpClientConfig.Builder b = new AsyncHttpClientConfig.Builder(); b.addRequestFilter(new ThrottleRequestFilter(0, 1000)); AsyncHttpClient c = getAsyncHttpClient(b.build()); try { Response response = c.preparePost(getTargetUrl()) .execute().get(); fail("Should have timed out"); } catch (IOException ex) { assertNotNull(ex); assertEquals(ex.getCause().getClass(), FilterException.class); } c.close(); } public String getTargetUrl() { return String.format("http://127.0.0.1:%d/foo/test", port1); } @Test(groups = {"standalone", "default_provider"}) public void basicResponseFilterTest() throws Throwable { AsyncHttpClientConfig.Builder b = new AsyncHttpClientConfig.Builder(); b.addResponseFilter(new ResponseFilter() { public FilterContext filter(FilterContext ctx) throws FilterException { return ctx; } }); AsyncHttpClient c = getAsyncHttpClient(b.build()); try { Response response = c.preparePost(getTargetUrl()) .execute().get(); assertNotNull(response); assertEquals(response.getStatusCode(), 200); } catch (IOException ex) { fail("Should have timed out"); } c.close(); } @Test(groups = {"standalone", "default_provider"}) public void replayResponseFilterTest() throws Throwable { AsyncHttpClientConfig.Builder b = new AsyncHttpClientConfig.Builder(); final AtomicBoolean replay = new AtomicBoolean(true); b.addResponseFilter(new ResponseFilter() { public FilterContext filter(FilterContext ctx) throws FilterException { if (replay.getAndSet(false)) { Request request = new RequestBuilder(ctx.getRequest()).addHeader("X-Replay", "true").build(); return new FilterContext(ctx.getAsyncHandler(), request, true); } return ctx; } }); AsyncHttpClient c = getAsyncHttpClient(b.build()); try { Response response = c.preparePost(getTargetUrl()) .execute().get(); assertNotNull(response); assertEquals(response.getStatusCode(), 200); assertEquals(response.getHeader("X-Replay"), "true"); } catch (IOException ex) { fail("Should have timed out"); } c.close(); } @Test(groups = {"standalone", "default_provider"}) public void replayStatusCodeResponseFilterTest() throws Throwable { AsyncHttpClientConfig.Builder b = new AsyncHttpClientConfig.Builder(); final AtomicBoolean replay = new AtomicBoolean(true); b.addResponseFilter(new ResponseFilter() { public FilterContext filter(FilterContext ctx) throws FilterException { if (ctx.getResponseStatus() != null && ctx.getResponseStatus().getStatusCode() == 200 && replay.getAndSet(false)) { Request request = new RequestBuilder(ctx.getRequest()).addHeader("X-Replay", "true").build(); return new FilterContext(ctx.getAsyncHandler(), request, true); } return ctx; } }); AsyncHttpClient c = getAsyncHttpClient(b.build()); try { Response response = c.preparePost(getTargetUrl()) .execute().get(); assertNotNull(response); assertEquals(response.getStatusCode(), 200); assertEquals(response.getHeader("X-Replay"), "true"); } catch (IOException ex) { fail("Should have timed out"); } c.close(); } } FluentCaseInsensitiveStringsMapTest.java000066400000000000000000000665221166553056000345730ustar00rootroot00000000000000async-http-client-1.6.5/src/test/java/com/ning/http/client/async/* * Copyright 2010 Ning, Inc. * * Ning licenses this file to you 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. */ package com.ning.http.client.async; import com.ning.http.client.FluentCaseInsensitiveStringsMap; import org.testng.annotations.Test; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.LinkedHashMap; import java.util.LinkedHashSet; import java.util.Map; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertNull; import static org.testng.Assert.assertTrue; public class FluentCaseInsensitiveStringsMapTest { @Test public void emptyTest() { FluentCaseInsensitiveStringsMap map = new FluentCaseInsensitiveStringsMap(); assertTrue(map.keySet().isEmpty()); } @Test public void normalTest() { FluentCaseInsensitiveStringsMap map = new FluentCaseInsensitiveStringsMap(); map.add("foo", "bar"); map.add("baz", Arrays.asList("foo", "bar")); assertEquals(map.keySet(), new LinkedHashSet(Arrays.asList("foo", "baz"))); assertEquals(map.getFirstValue("foo"), "bar"); assertEquals(map.getJoinedValue("foo", ", "), "bar"); assertEquals(map.get("foo"), Arrays.asList("bar")); assertEquals(map.getFirstValue("baz"), "foo"); assertEquals(map.getJoinedValue("baz", ", "), "foo, bar"); assertEquals(map.get("baz"), Arrays.asList("foo", "bar")); } @Test public void nameCaseTest() { FluentCaseInsensitiveStringsMap map = new FluentCaseInsensitiveStringsMap(); map.add("fOO", "bAr"); map.add("Baz", Arrays.asList("fOo", "bar")); assertEquals(map.keySet(), new LinkedHashSet(Arrays.asList("fOO", "Baz"))); assertEquals(map.getFirstValue("fOO"), "bAr"); assertEquals(map.getJoinedValue("fOO", ", "), "bAr"); assertEquals(map.get("fOO"), Arrays.asList("bAr")); assertEquals(map.getFirstValue("foo"), "bAr"); assertEquals(map.getJoinedValue("foo", ", "), "bAr"); assertEquals(map.get("foo"), Arrays.asList("bAr")); assertEquals(map.getFirstValue("FOO"), "bAr"); assertEquals(map.getJoinedValue("FOO", ", "), "bAr"); assertEquals(map.get("FOO"), Arrays.asList("bAr")); assertEquals(map.getFirstValue("Baz"), "fOo"); assertEquals(map.getJoinedValue("Baz", ", "), "fOo, bar"); assertEquals(map.get("Baz"), Arrays.asList("fOo", "bar")); assertEquals(map.getFirstValue("baz"), "fOo"); assertEquals(map.getJoinedValue("baz", ", "), "fOo, bar"); assertEquals(map.get("baz"), Arrays.asList("fOo", "bar")); assertEquals(map.getFirstValue("BAZ"), "fOo"); assertEquals(map.getJoinedValue("BAZ", ", "), "fOo, bar"); assertEquals(map.get("BAZ"), Arrays.asList("fOo", "bar")); } @Test public void sameKeyMultipleTimesTest() { FluentCaseInsensitiveStringsMap map = new FluentCaseInsensitiveStringsMap(); map.add("foo", "baz,foo"); map.add("Foo", Arrays.asList("bar")); map.add("fOO", "bla", "blubb"); assertEquals(map.keySet(), new LinkedHashSet(Arrays.asList("foo"))); assertEquals(map.getFirstValue("foo"), "baz,foo"); assertEquals(map.getJoinedValue("foo", ", "), "baz,foo, bar, bla, blubb"); assertEquals(map.get("foo"), Arrays.asList("baz,foo", "bar", "bla", "blubb")); assertEquals(map.getFirstValue("Foo"), "baz,foo"); assertEquals(map.getJoinedValue("Foo", ", "), "baz,foo, bar, bla, blubb"); assertEquals(map.get("Foo"), Arrays.asList("baz,foo", "bar", "bla", "blubb")); assertEquals(map.getFirstValue("fOO"), "baz,foo"); assertEquals(map.getJoinedValue("fOO", ", "), "baz,foo, bar, bla, blubb"); assertEquals(map.get("fOO"), Arrays.asList("baz,foo", "bar", "bla", "blubb")); } @Test public void emptyValueTest() { FluentCaseInsensitiveStringsMap map = new FluentCaseInsensitiveStringsMap(); map.add("foo", ""); assertEquals(map.keySet(), new LinkedHashSet(Arrays.asList("foo"))); assertEquals(map.getFirstValue("foo"), ""); assertEquals(map.getJoinedValue("foo", ", "), ""); assertEquals(map.get("foo"), Arrays.asList("")); } @Test public void nullValueTest() { FluentCaseInsensitiveStringsMap map = new FluentCaseInsensitiveStringsMap(); map.add("foo", (String) null); assertEquals(map.getFirstValue("foo"), ""); assertEquals(map.getJoinedValue("foo", ", "), ""); assertEquals(map.get("foo").size(), 1); } @Test public void mapConstructorTest() { Map> headerMap = new LinkedHashMap>(); headerMap.put("foo", Arrays.asList("baz,foo")); headerMap.put("baz", Arrays.asList("bar")); headerMap.put("bar", Arrays.asList("bla", "blubb")); FluentCaseInsensitiveStringsMap map = new FluentCaseInsensitiveStringsMap(headerMap); headerMap.remove("foo"); headerMap.remove("bar"); headerMap.remove("baz"); assertEquals(map.keySet(), new LinkedHashSet(Arrays.asList("foo", "baz", "bar"))); assertEquals(map.getFirstValue("foo"), "baz,foo"); assertEquals(map.getJoinedValue("foo", ", "), "baz,foo"); assertEquals(map.get("foo"), Arrays.asList("baz,foo")); assertEquals(map.getFirstValue("baz"), "bar"); assertEquals(map.getJoinedValue("baz", ", "), "bar"); assertEquals(map.get("baz"), Arrays.asList("bar")); assertEquals(map.getFirstValue("bar"), "bla"); assertEquals(map.getJoinedValue("bar", ", "), "bla, blubb"); assertEquals(map.get("bar"), Arrays.asList("bla", "blubb")); } @Test public void mapConstructorNullTest() { FluentCaseInsensitiveStringsMap map = new FluentCaseInsensitiveStringsMap((Map>) null); assertEquals(map.keySet().size(), 0); } @Test public void copyConstructorTest() { FluentCaseInsensitiveStringsMap srcHeaders = new FluentCaseInsensitiveStringsMap(); srcHeaders.add("foo", "baz,foo"); srcHeaders.add("baz", Arrays.asList("bar")); srcHeaders.add("bar", "bla", "blubb"); FluentCaseInsensitiveStringsMap map = new FluentCaseInsensitiveStringsMap(srcHeaders); srcHeaders.delete("foo"); srcHeaders.delete("bar"); srcHeaders.delete("baz"); assertTrue(srcHeaders.keySet().isEmpty()); assertEquals(map.keySet(), new LinkedHashSet(Arrays.asList("foo", "baz", "bar"))); assertEquals(map.getFirstValue("foo"), "baz,foo"); assertEquals(map.getJoinedValue("foo", ", "), "baz,foo"); assertEquals(map.get("foo"), Arrays.asList("baz,foo")); assertEquals(map.getFirstValue("baz"), "bar"); assertEquals(map.getJoinedValue("baz", ", "), "bar"); assertEquals(map.get("baz"), Arrays.asList("bar")); assertEquals(map.getFirstValue("bar"), "bla"); assertEquals(map.getJoinedValue("bar", ", "), "bla, blubb"); assertEquals(map.get("bar"), Arrays.asList("bla", "blubb")); } @Test public void copyConstructorNullTest() { FluentCaseInsensitiveStringsMap map = new FluentCaseInsensitiveStringsMap((FluentCaseInsensitiveStringsMap) null); assertEquals(map.keySet().size(), 0); } @Test public void deleteTest() { FluentCaseInsensitiveStringsMap map = new FluentCaseInsensitiveStringsMap(); map.add("foo", "bar"); map.add("baz", Arrays.asList("foo", "bar")); assertEquals(map.keySet(), new LinkedHashSet(Arrays.asList("foo", "baz"))); assertEquals(map.getFirstValue("foo"), "bar"); assertEquals(map.getJoinedValue("foo", ", "), "bar"); assertEquals(map.get("foo"), Arrays.asList("bar")); assertEquals(map.getFirstValue("baz"), "foo"); assertEquals(map.getJoinedValue("baz", ", "), "foo, bar"); assertEquals(map.get("baz"), Arrays.asList("foo", "bar")); map.delete("bAz"); assertEquals(map.keySet(), new LinkedHashSet(Arrays.asList("foo"))); assertEquals(map.getFirstValue("foo"), "bar"); assertEquals(map.getJoinedValue("foo", ", "), "bar"); assertEquals(map.get("foo"), Arrays.asList("bar")); assertNull(map.getFirstValue("baz")); assertNull(map.getJoinedValue("baz", ", ")); assertNull(map.get("baz")); } @Test public void deleteUndefinedKeyTest() { FluentCaseInsensitiveStringsMap map = new FluentCaseInsensitiveStringsMap(); map.add("foo", "bar"); map.add("baz", Arrays.asList("foo", "bar")); assertEquals(map.keySet(), new LinkedHashSet(Arrays.asList("foo", "baz"))); assertEquals(map.getFirstValue("foo"), "bar"); assertEquals(map.getJoinedValue("foo", ", "), "bar"); assertEquals(map.get("foo"), Arrays.asList("bar")); assertEquals(map.getFirstValue("baz"), "foo"); assertEquals(map.getJoinedValue("baz", ", "), "foo, bar"); assertEquals(map.get("baz"), Arrays.asList("foo", "bar")); map.delete("bar"); assertEquals(map.keySet(), new LinkedHashSet(Arrays.asList("foo", "baz"))); assertEquals(map.getFirstValue("foo"), "bar"); assertEquals(map.getJoinedValue("foo", ", "), "bar"); assertEquals(map.get("foo"), Arrays.asList("bar")); assertEquals(map.getFirstValue("baz"), "foo"); assertEquals(map.getJoinedValue("baz", ", "), "foo, bar"); assertEquals(map.get("baz"), Arrays.asList("foo", "bar")); } @Test public void deleteNullTest() { FluentCaseInsensitiveStringsMap map = new FluentCaseInsensitiveStringsMap(); map.add("foo", "bar"); map.add("baz", Arrays.asList("foo", "bar")); assertEquals(map.keySet(), new LinkedHashSet(Arrays.asList("foo", "baz"))); assertEquals(map.getFirstValue("foo"), "bar"); assertEquals(map.getJoinedValue("foo", ", "), "bar"); assertEquals(map.get("foo"), Arrays.asList("bar")); assertEquals(map.getFirstValue("baz"), "foo"); assertEquals(map.getJoinedValue("baz", ", "), "foo, bar"); assertEquals(map.get("baz"), Arrays.asList("foo", "bar")); map.delete(null); assertEquals(map.keySet(), new LinkedHashSet(Arrays.asList("foo", "baz"))); assertEquals(map.getFirstValue("foo"), "bar"); assertEquals(map.getJoinedValue("foo", ", "), "bar"); assertEquals(map.get("foo"), Arrays.asList("bar")); assertEquals(map.getFirstValue("baz"), "foo"); assertEquals(map.getJoinedValue("baz", ", "), "foo, bar"); assertEquals(map.get("baz"), Arrays.asList("foo", "bar")); } @Test public void deleteAllArrayTest() { FluentCaseInsensitiveStringsMap map = new FluentCaseInsensitiveStringsMap(); map.add("foo", "bar"); map.add("baz", Arrays.asList("foo", "bar")); assertEquals(map.keySet(), new LinkedHashSet(Arrays.asList("foo", "baz"))); assertEquals(map.getFirstValue("foo"), "bar"); assertEquals(map.getJoinedValue("foo", ", "), "bar"); assertEquals(map.get("foo"), Arrays.asList("bar")); assertEquals(map.getFirstValue("baz"), "foo"); assertEquals(map.getJoinedValue("baz", ", "), "foo, bar"); assertEquals(map.get("baz"), Arrays.asList("foo", "bar")); map.deleteAll("bAz", "Boo"); assertEquals(map.keySet(), new LinkedHashSet(Arrays.asList("foo"))); assertEquals(map.getFirstValue("foo"), "bar"); assertEquals(map.getJoinedValue("foo", ", "), "bar"); assertEquals(map.get("foo"), Arrays.asList("bar")); assertNull(map.getFirstValue("baz")); assertNull(map.getJoinedValue("baz", ", ")); assertNull(map.get("baz")); } @Test public void deleteAllCollectionTest() { FluentCaseInsensitiveStringsMap map = new FluentCaseInsensitiveStringsMap(); map.add("foo", "bar"); map.add("baz", Arrays.asList("foo", "bar")); assertEquals(map.keySet(), new LinkedHashSet(Arrays.asList("foo", "baz"))); assertEquals(map.getFirstValue("foo"), "bar"); assertEquals(map.getJoinedValue("foo", ", "), "bar"); assertEquals(map.get("foo"), Arrays.asList("bar")); assertEquals(map.getFirstValue("baz"), "foo"); assertEquals(map.getJoinedValue("baz", ", "), "foo, bar"); assertEquals(map.get("baz"), Arrays.asList("foo", "bar")); map.deleteAll(Arrays.asList("bAz", "fOO")); assertEquals(map.keySet(), Collections.emptyList()); assertNull(map.getFirstValue("foo")); assertNull(map.getJoinedValue("foo", ", ")); assertNull(map.get("foo")); assertNull(map.getFirstValue("baz")); assertNull(map.getJoinedValue("baz", ", ")); assertNull(map.get("baz")); } @Test public void deleteAllNullArrayTest() { FluentCaseInsensitiveStringsMap map = new FluentCaseInsensitiveStringsMap(); map.add("foo", "bar"); map.add("baz", Arrays.asList("foo", "bar")); assertEquals(map.keySet(), new LinkedHashSet(Arrays.asList("foo", "baz"))); assertEquals(map.getFirstValue("foo"), "bar"); assertEquals(map.getJoinedValue("foo", ", "), "bar"); assertEquals(map.get("foo"), Arrays.asList("bar")); assertEquals(map.getFirstValue("baz"), "foo"); assertEquals(map.getJoinedValue("baz", ", "), "foo, bar"); assertEquals(map.get("baz"), Arrays.asList("foo", "bar")); map.deleteAll((String[]) null); assertEquals(map.keySet(), new LinkedHashSet(Arrays.asList("foo", "baz"))); assertEquals(map.getFirstValue("foo"), "bar"); assertEquals(map.getJoinedValue("foo", ", "), "bar"); assertEquals(map.get("foo"), Arrays.asList("bar")); assertEquals(map.getFirstValue("baz"), "foo"); assertEquals(map.getJoinedValue("baz", ", "), "foo, bar"); assertEquals(map.get("baz"), Arrays.asList("foo", "bar")); } @Test public void deleteAllNullCollectionTest() { FluentCaseInsensitiveStringsMap map = new FluentCaseInsensitiveStringsMap(); map.add("foo", "bar"); map.add("baz", Arrays.asList("foo", "bar")); assertEquals(map.keySet(), new LinkedHashSet(Arrays.asList("foo", "baz"))); assertEquals(map.getFirstValue("foo"), "bar"); assertEquals(map.getJoinedValue("foo", ", "), "bar"); assertEquals(map.get("foo"), Arrays.asList("bar")); assertEquals(map.getFirstValue("baz"), "foo"); assertEquals(map.getJoinedValue("baz", ", "), "foo, bar"); assertEquals(map.get("baz"), Arrays.asList("foo", "bar")); map.deleteAll((Collection) null); assertEquals(map.keySet(), new LinkedHashSet(Arrays.asList("foo", "baz"))); assertEquals(map.getFirstValue("foo"), "bar"); assertEquals(map.getJoinedValue("foo", ", "), "bar"); assertEquals(map.get("foo"), Arrays.asList("bar")); assertEquals(map.getFirstValue("baz"), "foo"); assertEquals(map.getJoinedValue("baz", ", "), "foo, bar"); assertEquals(map.get("baz"), Arrays.asList("foo", "bar")); } @Test public void replaceTest() { FluentCaseInsensitiveStringsMap map = new FluentCaseInsensitiveStringsMap(); map.add("foo", "bar"); map.add("baz", Arrays.asList("foo", "bar")); assertEquals(map.keySet(), new LinkedHashSet(Arrays.asList("foo", "baz"))); assertEquals(map.getFirstValue("foo"), "bar"); assertEquals(map.getJoinedValue("foo", ", "), "bar"); assertEquals(map.get("foo"), Arrays.asList("bar")); assertEquals(map.getFirstValue("baz"), "foo"); assertEquals(map.getJoinedValue("baz", ", "), "foo, bar"); assertEquals(map.get("baz"), Arrays.asList("foo", "bar")); map.replace("Foo", "blub", "bla"); assertEquals(map.keySet(), new LinkedHashSet(Arrays.asList("Foo", "baz"))); assertEquals(map.getFirstValue("foo"), "blub"); assertEquals(map.getJoinedValue("foo", ", "), "blub, bla"); assertEquals(map.get("foo"), Arrays.asList("blub", "bla")); assertEquals(map.getFirstValue("baz"), "foo"); assertEquals(map.getJoinedValue("baz", ", "), "foo, bar"); assertEquals(map.get("baz"), Arrays.asList("foo", "bar")); } @Test public void replaceUndefinedTest() { FluentCaseInsensitiveStringsMap map = new FluentCaseInsensitiveStringsMap(); map.add("foo", "bar"); map.add("baz", Arrays.asList("foo", "bar")); assertEquals(map.keySet(), new LinkedHashSet(Arrays.asList("foo", "baz"))); assertEquals(map.getFirstValue("foo"), "bar"); assertEquals(map.getJoinedValue("foo", ", "), "bar"); assertEquals(map.get("foo"), Arrays.asList("bar")); assertEquals(map.getFirstValue("baz"), "foo"); assertEquals(map.getJoinedValue("baz", ", "), "foo, bar"); assertEquals(map.get("baz"), Arrays.asList("foo", "bar")); map.replace("bar", Arrays.asList("blub")); assertEquals(map.keySet(), new LinkedHashSet(Arrays.asList("foo", "baz", "bar"))); assertEquals(map.getFirstValue("foo"), "bar"); assertEquals(map.getJoinedValue("foo", ", "), "bar"); assertEquals(map.get("foo"), Arrays.asList("bar")); assertEquals(map.getFirstValue("baz"), "foo"); assertEquals(map.getJoinedValue("baz", ", "), "foo, bar"); assertEquals(map.get("baz"), Arrays.asList("foo", "bar")); assertEquals(map.getFirstValue("bar"), "blub"); assertEquals(map.getJoinedValue("bar", ", "), "blub"); assertEquals(map.get("bar"), Arrays.asList("blub")); } @Test public void replaceNullTest() { FluentCaseInsensitiveStringsMap map = new FluentCaseInsensitiveStringsMap(); map.add("foo", "bar"); map.add("baz", Arrays.asList("foo", "bar")); assertEquals(map.keySet(), new LinkedHashSet(Arrays.asList("foo", "baz"))); assertEquals(map.getFirstValue("foo"), "bar"); assertEquals(map.getJoinedValue("foo", ", "), "bar"); assertEquals(map.get("foo"), Arrays.asList("bar")); assertEquals(map.getFirstValue("baz"), "foo"); assertEquals(map.getJoinedValue("baz", ", "), "foo, bar"); assertEquals(map.get("baz"), Arrays.asList("foo", "bar")); map.replace(null, Arrays.asList("blub")); assertEquals(map.keySet(), new LinkedHashSet(Arrays.asList("foo", "baz"))); assertEquals(map.getFirstValue("foo"), "bar"); assertEquals(map.getJoinedValue("foo", ", "), "bar"); assertEquals(map.get("foo"), Arrays.asList("bar")); assertEquals(map.getFirstValue("baz"), "foo"); assertEquals(map.getJoinedValue("baz", ", "), "foo, bar"); assertEquals(map.get("baz"), Arrays.asList("foo", "bar")); } @Test public void replaceValueWithNullTest() { FluentCaseInsensitiveStringsMap map = new FluentCaseInsensitiveStringsMap(); map.add("foo", "bar"); map.add("baz", Arrays.asList("foo", "bar")); assertEquals(map.keySet(), new LinkedHashSet(Arrays.asList("foo", "baz"))); assertEquals(map.getFirstValue("foo"), "bar"); assertEquals(map.getJoinedValue("foo", ", "), "bar"); assertEquals(map.get("foo"), Arrays.asList("bar")); assertEquals(map.getFirstValue("baz"), "foo"); assertEquals(map.getJoinedValue("baz", ", "), "foo, bar"); assertEquals(map.get("baz"), Arrays.asList("foo", "bar")); map.replace("baZ", (Collection) null); assertEquals(map.keySet(), new LinkedHashSet(Arrays.asList("foo"))); assertEquals(map.getFirstValue("foo"), "bar"); assertEquals(map.getJoinedValue("foo", ", "), "bar"); assertEquals(map.get("foo"), Arrays.asList("bar")); assertNull(map.getFirstValue("baz")); assertNull(map.getJoinedValue("baz", ", ")); assertNull(map.get("baz")); } @Test public void replaceAllMapTest1() { FluentCaseInsensitiveStringsMap map = new FluentCaseInsensitiveStringsMap(); map.add("foo", "bar"); map.add("bar", "foo, bar", "baz"); map.add("baz", Arrays.asList("foo", "bar")); assertEquals(map.keySet(), new LinkedHashSet(Arrays.asList("foo", "bar", "baz"))); assertEquals(map.getFirstValue("foo"), "bar"); assertEquals(map.getJoinedValue("foo", ", "), "bar"); assertEquals(map.get("foo"), Arrays.asList("bar")); assertEquals(map.getFirstValue("bar"), "foo, bar"); assertEquals(map.getJoinedValue("bar", ", "), "foo, bar, baz"); assertEquals(map.get("bar"), Arrays.asList("foo, bar", "baz")); assertEquals(map.getFirstValue("baz"), "foo"); assertEquals(map.getJoinedValue("baz", ", "), "foo, bar"); assertEquals(map.get("baz"), Arrays.asList("foo", "bar")); map.replaceAll(new FluentCaseInsensitiveStringsMap().add("Bar", "baz").add("Boo", "blub", "bla")); assertEquals(map.keySet(), new LinkedHashSet(Arrays.asList("foo", "Bar", "baz", "Boo"))); assertEquals(map.getFirstValue("foo"), "bar"); assertEquals(map.getJoinedValue("foo", ", "), "bar"); assertEquals(map.get("foo"), Arrays.asList("bar")); assertEquals(map.getFirstValue("bar"), "baz"); assertEquals(map.getJoinedValue("bar", ", "), "baz"); assertEquals(map.get("bar"), Arrays.asList("baz")); assertEquals(map.getFirstValue("baz"), "foo"); assertEquals(map.getJoinedValue("baz", ", "), "foo, bar"); assertEquals(map.get("baz"), Arrays.asList("foo", "bar")); assertEquals(map.getFirstValue("Boo"), "blub"); assertEquals(map.getJoinedValue("Boo", ", "), "blub, bla"); assertEquals(map.get("Boo"), Arrays.asList("blub", "bla")); } @Test public void replaceAllTest2() { FluentCaseInsensitiveStringsMap map = new FluentCaseInsensitiveStringsMap(); map.add("foo", "bar"); map.add("bar", "foo, bar", "baz"); map.add("baz", Arrays.asList("foo", "bar")); assertEquals(map.keySet(), new LinkedHashSet(Arrays.asList("foo", "bar", "baz"))); assertEquals(map.getFirstValue("foo"), "bar"); assertEquals(map.getJoinedValue("foo", ", "), "bar"); assertEquals(map.get("foo"), Arrays.asList("bar")); assertEquals(map.getFirstValue("bar"), "foo, bar"); assertEquals(map.getJoinedValue("bar", ", "), "foo, bar, baz"); assertEquals(map.get("bar"), Arrays.asList("foo, bar", "baz")); assertEquals(map.getFirstValue("baz"), "foo"); assertEquals(map.getJoinedValue("baz", ", "), "foo, bar"); assertEquals(map.get("baz"), Arrays.asList("foo", "bar")); LinkedHashMap> newValues = new LinkedHashMap>(); newValues.put("Bar", Arrays.asList("baz")); newValues.put("Foo", null); map.replaceAll(newValues); assertEquals(map.keySet(), new LinkedHashSet(Arrays.asList("Bar", "baz"))); assertNull(map.getFirstValue("foo")); assertNull(map.getJoinedValue("foo", ", ")); assertNull(map.get("foo")); assertEquals(map.getFirstValue("bar"), "baz"); assertEquals(map.getJoinedValue("bar", ", "), "baz"); assertEquals(map.get("bar"), Arrays.asList("baz")); assertEquals(map.getFirstValue("baz"), "foo"); assertEquals(map.getJoinedValue("baz", ", "), "foo, bar"); assertEquals(map.get("baz"), Arrays.asList("foo", "bar")); } @Test public void replaceAllNullTest1() { FluentCaseInsensitiveStringsMap map = new FluentCaseInsensitiveStringsMap(); map.add("foo", "bar"); map.add("bar", "foo, bar", "baz"); map.add("baz", Arrays.asList("foo", "bar")); assertEquals(map.keySet(), new LinkedHashSet(Arrays.asList("foo", "bar", "baz"))); assertEquals(map.getFirstValue("foo"), "bar"); assertEquals(map.getJoinedValue("foo", ", "), "bar"); assertEquals(map.get("foo"), Arrays.asList("bar")); assertEquals(map.getFirstValue("bar"), "foo, bar"); assertEquals(map.getJoinedValue("bar", ", "), "foo, bar, baz"); assertEquals(map.get("bar"), Arrays.asList("foo, bar", "baz")); assertEquals(map.getFirstValue("baz"), "foo"); assertEquals(map.getJoinedValue("baz", ", "), "foo, bar"); assertEquals(map.get("baz"), Arrays.asList("foo", "bar")); map.replaceAll((FluentCaseInsensitiveStringsMap) null); assertEquals(map.keySet(), new LinkedHashSet(Arrays.asList("foo", "bar", "baz"))); assertEquals(map.getFirstValue("foo"), "bar"); assertEquals(map.getJoinedValue("foo", ", "), "bar"); assertEquals(map.get("foo"), Arrays.asList("bar")); assertEquals(map.getFirstValue("bar"), "foo, bar"); assertEquals(map.getJoinedValue("bar", ", "), "foo, bar, baz"); assertEquals(map.get("bar"), Arrays.asList("foo, bar", "baz")); assertEquals(map.getFirstValue("baz"), "foo"); assertEquals(map.getJoinedValue("baz", ", "), "foo, bar"); assertEquals(map.get("baz"), Arrays.asList("foo", "bar")); } @Test public void replaceAllNullTest2() { FluentCaseInsensitiveStringsMap map = new FluentCaseInsensitiveStringsMap(); map.add("foo", "bar"); map.add("bar", "foo, bar", "baz"); map.add("baz", Arrays.asList("foo", "bar")); assertEquals(map.keySet(), new LinkedHashSet(Arrays.asList("foo", "bar", "baz"))); assertEquals(map.getFirstValue("foo"), "bar"); assertEquals(map.getJoinedValue("foo", ", "), "bar"); assertEquals(map.get("foo"), Arrays.asList("bar")); assertEquals(map.getFirstValue("bar"), "foo, bar"); assertEquals(map.getJoinedValue("bar", ", "), "foo, bar, baz"); assertEquals(map.get("bar"), Arrays.asList("foo, bar", "baz")); assertEquals(map.getFirstValue("baz"), "foo"); assertEquals(map.getJoinedValue("baz", ", "), "foo, bar"); assertEquals(map.get("baz"), Arrays.asList("foo", "bar")); map.replaceAll((Map>) null); assertEquals(map.keySet(), new LinkedHashSet(Arrays.asList("foo", "bar", "baz"))); assertEquals(map.getFirstValue("foo"), "bar"); assertEquals(map.getJoinedValue("foo", ", "), "bar"); assertEquals(map.get("foo"), Arrays.asList("bar")); assertEquals(map.getFirstValue("bar"), "foo, bar"); assertEquals(map.getJoinedValue("bar", ", "), "foo, bar, baz"); assertEquals(map.get("bar"), Arrays.asList("foo, bar", "baz")); assertEquals(map.getFirstValue("baz"), "foo"); assertEquals(map.getJoinedValue("baz", ", "), "foo, bar"); assertEquals(map.get("baz"), Arrays.asList("foo", "bar")); } } async-http-client-1.6.5/src/test/java/com/ning/http/client/async/FluentStringsMapTest.java000066400000000000000000000773741166553056000316440ustar00rootroot00000000000000/* * Copyright 2010 Ning, Inc. * * Ning licenses this file to you 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. */ package com.ning.http.client.async; import com.ning.http.client.FluentStringsMap; import org.testng.annotations.Test; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.LinkedHashMap; import java.util.LinkedHashSet; import java.util.Map; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertNull; import static org.testng.Assert.assertTrue; public class FluentStringsMapTest { @Test public void emptyTest() { FluentStringsMap map = new FluentStringsMap(); assertTrue(map.keySet().isEmpty()); } @Test public void normalTest() { FluentStringsMap map = new FluentStringsMap(); map.add("fOO", "bAr"); map.add("Baz", Arrays.asList("fOo", "bar")); assertEquals(map.keySet(), new LinkedHashSet(Arrays.asList("fOO", "Baz"))); assertEquals(map.getFirstValue("fOO"), "bAr"); assertEquals(map.getJoinedValue("fOO", ", "), "bAr"); assertEquals(map.get("fOO"), Arrays.asList("bAr")); assertNull(map.getFirstValue("foo")); assertNull(map.getJoinedValue("foo", ", ")); assertNull(map.get("foo")); assertEquals(map.getFirstValue("Baz"), "fOo"); assertEquals(map.getJoinedValue("Baz", ", "), "fOo, bar"); assertEquals(map.get("Baz"), Arrays.asList("fOo", "bar")); assertNull(map.getFirstValue("baz")); assertNull(map.getJoinedValue("baz", ", ")); assertNull(map.get("baz")); } @Test public void addNullTest() { FluentStringsMap map = new FluentStringsMap(); map.add("fOO", "bAr"); map.add(null, Arrays.asList("fOo", "bar")); assertEquals(map.keySet(), new LinkedHashSet(Arrays.asList("fOO"))); assertEquals(map.getFirstValue("fOO"), "bAr"); assertEquals(map.getJoinedValue("fOO", ", "), "bAr"); assertEquals(map.get("fOO"), Arrays.asList("bAr")); assertNull(map.getFirstValue("foo")); assertNull(map.getJoinedValue("foo", ", ")); assertNull(map.get("foo")); assertNull(map.getFirstValue(null)); assertNull(map.getJoinedValue("Baz", ", ")); assertNull(map.get(null)); } @Test public void sameKeyMultipleTimesTest() { FluentStringsMap map = new FluentStringsMap(); map.add("foo", "baz,foo"); map.add("foo", Arrays.asList("bar")); map.add("foo", "bla", "blubb"); map.add("fOO", "duh"); assertEquals(map.keySet(), new LinkedHashSet(Arrays.asList("foo", "fOO"))); assertEquals(map.getFirstValue("foo"), "baz,foo"); assertEquals(map.getJoinedValue("foo", ", "), "baz,foo, bar, bla, blubb"); assertEquals(map.get("foo"), Arrays.asList("baz,foo", "bar", "bla", "blubb")); assertEquals(map.getFirstValue("fOO"), "duh"); assertEquals(map.getJoinedValue("fOO", ", "), "duh"); assertEquals(map.get("fOO"), Arrays.asList("duh")); } @Test public void emptyValueTest() { FluentStringsMap map = new FluentStringsMap(); map.add("foo", ""); assertEquals(map.keySet(), new LinkedHashSet(Arrays.asList("foo"))); assertEquals(map.getFirstValue("foo"), ""); assertEquals(map.getJoinedValue("foo", ", "), ""); assertEquals(map.get("foo"), Arrays.asList("")); } @Test public void nullValueTest() { FluentStringsMap map = new FluentStringsMap(); map.add("foo", (String) null); assertEquals(map.getFirstValue("foo"), ""); assertEquals(map.getJoinedValue("foo", ", "), ""); assertEquals(map.get("foo").size(), 1); } @Test public void mapConstructorTest() { Map> headerMap = new LinkedHashMap>(); headerMap.put("foo", Arrays.asList("baz,foo")); headerMap.put("baz", Arrays.asList("bar")); headerMap.put("bar", Arrays.asList("bla", "blubb")); FluentStringsMap map = new FluentStringsMap(headerMap); headerMap.remove("foo"); headerMap.remove("bar"); headerMap.remove("baz"); assertEquals(map.keySet(), new LinkedHashSet(Arrays.asList("foo", "baz", "bar"))); assertEquals(map.getFirstValue("foo"), "baz,foo"); assertEquals(map.getJoinedValue("foo", ", "), "baz,foo"); assertEquals(map.get("foo"), Arrays.asList("baz,foo")); assertEquals(map.getFirstValue("baz"), "bar"); assertEquals(map.getJoinedValue("baz", ", "), "bar"); assertEquals(map.get("baz"), Arrays.asList("bar")); assertEquals(map.getFirstValue("bar"), "bla"); assertEquals(map.getJoinedValue("bar", ", "), "bla, blubb"); assertEquals(map.get("bar"), Arrays.asList("bla", "blubb")); } @Test public void mapConstructorNullTest() { FluentStringsMap map = new FluentStringsMap((Map>) null); assertEquals(map.keySet().size(), 0); } @Test public void copyConstructorTest() { FluentStringsMap srcHeaders = new FluentStringsMap(); srcHeaders.add("foo", "baz,foo"); srcHeaders.add("baz", Arrays.asList("bar")); srcHeaders.add("bar", "bla", "blubb"); FluentStringsMap map = new FluentStringsMap(srcHeaders); srcHeaders.delete("foo"); srcHeaders.delete("bar"); srcHeaders.delete("baz"); assertTrue(srcHeaders.keySet().isEmpty()); assertEquals(map.keySet(), new LinkedHashSet(Arrays.asList("foo", "baz", "bar"))); assertEquals(map.getFirstValue("foo"), "baz,foo"); assertEquals(map.getJoinedValue("foo", ", "), "baz,foo"); assertEquals(map.get("foo"), Arrays.asList("baz,foo")); assertEquals(map.getFirstValue("baz"), "bar"); assertEquals(map.getJoinedValue("baz", ", "), "bar"); assertEquals(map.get("baz"), Arrays.asList("bar")); assertEquals(map.getFirstValue("bar"), "bla"); assertEquals(map.getJoinedValue("bar", ", "), "bla, blubb"); assertEquals(map.get("bar"), Arrays.asList("bla", "blubb")); } @Test public void copyConstructorNullTest() { FluentStringsMap map = new FluentStringsMap((FluentStringsMap) null); assertEquals(map.keySet().size(), 0); } @Test public void deleteTest() { FluentStringsMap map = new FluentStringsMap(); map.add("foo", "bar"); map.add("baz", Arrays.asList("foo", "bar")); assertEquals(map.keySet(), new LinkedHashSet(Arrays.asList("foo", "baz"))); assertEquals(map.getFirstValue("foo"), "bar"); assertEquals(map.getJoinedValue("foo", ", "), "bar"); assertEquals(map.get("foo"), Arrays.asList("bar")); assertEquals(map.getFirstValue("baz"), "foo"); assertEquals(map.getJoinedValue("baz", ", "), "foo, bar"); assertEquals(map.get("baz"), Arrays.asList("foo", "bar")); map.delete("baz"); assertEquals(map.keySet(), new LinkedHashSet(Arrays.asList("foo"))); assertEquals(map.getFirstValue("foo"), "bar"); assertEquals(map.getJoinedValue("foo", ", "), "bar"); assertEquals(map.get("foo"), Arrays.asList("bar")); assertNull(map.getFirstValue("baz")); assertNull(map.getJoinedValue("baz", ", ")); assertNull(map.get("baz")); } @Test public void deleteTestDifferentCase() { FluentStringsMap map = new FluentStringsMap(); map.add("foo", "bar"); map.add("baz", Arrays.asList("foo", "bar")); assertEquals(map.keySet(), new LinkedHashSet(Arrays.asList("foo", "baz"))); assertEquals(map.getFirstValue("foo"), "bar"); assertEquals(map.getJoinedValue("foo", ", "), "bar"); assertEquals(map.get("foo"), Arrays.asList("bar")); assertEquals(map.getFirstValue("baz"), "foo"); assertEquals(map.getJoinedValue("baz", ", "), "foo, bar"); assertEquals(map.get("baz"), Arrays.asList("foo", "bar")); map.delete("bAz"); assertEquals(map.keySet(), new LinkedHashSet(Arrays.asList("foo", "baz"))); assertEquals(map.getFirstValue("foo"), "bar"); assertEquals(map.getJoinedValue("foo", ", "), "bar"); assertEquals(map.get("foo"), Arrays.asList("bar")); assertEquals(map.getFirstValue("baz"), "foo"); assertEquals(map.getJoinedValue("baz", ", "), "foo, bar"); assertEquals(map.get("baz"), Arrays.asList("foo", "bar")); } @Test public void deleteUndefinedKeyTest() { FluentStringsMap map = new FluentStringsMap(); map.add("foo", "bar"); map.add("baz", Arrays.asList("foo", "bar")); assertEquals(map.keySet(), new LinkedHashSet(Arrays.asList("foo", "baz"))); assertEquals(map.getFirstValue("foo"), "bar"); assertEquals(map.getJoinedValue("foo", ", "), "bar"); assertEquals(map.get("foo"), Arrays.asList("bar")); assertEquals(map.getFirstValue("baz"), "foo"); assertEquals(map.getJoinedValue("baz", ", "), "foo, bar"); assertEquals(map.get("baz"), Arrays.asList("foo", "bar")); map.delete("bar"); assertEquals(map.keySet(), new LinkedHashSet(Arrays.asList("foo", "baz"))); assertEquals(map.getFirstValue("foo"), "bar"); assertEquals(map.getJoinedValue("foo", ", "), "bar"); assertEquals(map.get("foo"), Arrays.asList("bar")); assertEquals(map.getFirstValue("baz"), "foo"); assertEquals(map.getJoinedValue("baz", ", "), "foo, bar"); assertEquals(map.get("baz"), Arrays.asList("foo", "bar")); } @Test public void deleteNullTest() { FluentStringsMap map = new FluentStringsMap(); map.add("foo", "bar"); map.add("baz", Arrays.asList("foo", "bar")); assertEquals(map.keySet(), new LinkedHashSet(Arrays.asList("foo", "baz"))); assertEquals(map.getFirstValue("foo"), "bar"); assertEquals(map.getJoinedValue("foo", ", "), "bar"); assertEquals(map.get("foo"), Arrays.asList("bar")); assertEquals(map.getFirstValue("baz"), "foo"); assertEquals(map.getJoinedValue("baz", ", "), "foo, bar"); assertEquals(map.get("baz"), Arrays.asList("foo", "bar")); map.delete(null); assertEquals(map.keySet(), new LinkedHashSet(Arrays.asList("foo", "baz"))); assertEquals(map.getFirstValue("foo"), "bar"); assertEquals(map.getJoinedValue("foo", ", "), "bar"); assertEquals(map.get("foo"), Arrays.asList("bar")); assertEquals(map.getFirstValue("baz"), "foo"); assertEquals(map.getJoinedValue("baz", ", "), "foo, bar"); assertEquals(map.get("baz"), Arrays.asList("foo", "bar")); } @Test public void deleteAllArrayTest() { FluentStringsMap map = new FluentStringsMap(); map.add("foo", "bar"); map.add("baz", Arrays.asList("foo", "bar")); assertEquals(map.keySet(), new LinkedHashSet(Arrays.asList("foo", "baz"))); assertEquals(map.getFirstValue("foo"), "bar"); assertEquals(map.getJoinedValue("foo", ", "), "bar"); assertEquals(map.get("foo"), Arrays.asList("bar")); assertEquals(map.getFirstValue("baz"), "foo"); assertEquals(map.getJoinedValue("baz", ", "), "foo, bar"); assertEquals(map.get("baz"), Arrays.asList("foo", "bar")); map.deleteAll("baz", "Boo"); assertEquals(map.keySet(), new LinkedHashSet(Arrays.asList("foo"))); assertEquals(map.getFirstValue("foo"), "bar"); assertEquals(map.getJoinedValue("foo", ", "), "bar"); assertEquals(map.get("foo"), Arrays.asList("bar")); assertNull(map.getFirstValue("baz")); assertNull(map.getJoinedValue("baz", ", ")); assertNull(map.get("baz")); } @Test public void deleteAllArrayDifferentCaseTest() { FluentStringsMap map = new FluentStringsMap(); map.add("foo", "bar"); map.add("baz", Arrays.asList("foo", "bar")); assertEquals(map.keySet(), new LinkedHashSet(Arrays.asList("foo", "baz"))); assertEquals(map.getFirstValue("foo"), "bar"); assertEquals(map.getJoinedValue("foo", ", "), "bar"); assertEquals(map.get("foo"), Arrays.asList("bar")); assertEquals(map.getFirstValue("baz"), "foo"); assertEquals(map.getJoinedValue("baz", ", "), "foo, bar"); assertEquals(map.get("baz"), Arrays.asList("foo", "bar")); map.deleteAll("Foo", "baz"); assertEquals(map.keySet(), new LinkedHashSet(Arrays.asList("foo"))); assertEquals(map.getFirstValue("foo"), "bar"); assertEquals(map.getJoinedValue("foo", ", "), "bar"); assertEquals(map.get("foo"), Arrays.asList("bar")); assertNull(map.getFirstValue("baz")); assertNull(map.getJoinedValue("baz", ", ")); assertNull(map.get("baz")); } @Test public void deleteAllCollectionTest() { FluentStringsMap map = new FluentStringsMap(); map.add("foo", "bar"); map.add("baz", Arrays.asList("foo", "bar")); assertEquals(map.keySet(), new LinkedHashSet(Arrays.asList("foo", "baz"))); assertEquals(map.getFirstValue("foo"), "bar"); assertEquals(map.getJoinedValue("foo", ", "), "bar"); assertEquals(map.get("foo"), Arrays.asList("bar")); assertEquals(map.getFirstValue("baz"), "foo"); assertEquals(map.getJoinedValue("baz", ", "), "foo, bar"); assertEquals(map.get("baz"), Arrays.asList("foo", "bar")); map.deleteAll(Arrays.asList("baz", "foo")); assertEquals(map.keySet(), Collections.emptyList()); assertNull(map.getFirstValue("foo")); assertNull(map.getJoinedValue("foo", ", ")); assertNull(map.get("foo")); assertNull(map.getFirstValue("baz")); assertNull(map.getJoinedValue("baz", ", ")); assertNull(map.get("baz")); } @Test public void deleteAllCollectionDifferentCaseTest() { FluentStringsMap map = new FluentStringsMap(); map.add("foo", "bar"); map.add("baz", Arrays.asList("foo", "bar")); assertEquals(map.keySet(), new LinkedHashSet(Arrays.asList("foo", "baz"))); assertEquals(map.getFirstValue("foo"), "bar"); assertEquals(map.getJoinedValue("foo", ", "), "bar"); assertEquals(map.get("foo"), Arrays.asList("bar")); assertEquals(map.getFirstValue("baz"), "foo"); assertEquals(map.getJoinedValue("baz", ", "), "foo, bar"); assertEquals(map.get("baz"), Arrays.asList("foo", "bar")); map.deleteAll(Arrays.asList("bAz", "fOO")); assertEquals(map.keySet(), new LinkedHashSet(Arrays.asList("foo", "baz"))); assertEquals(map.getFirstValue("foo"), "bar"); assertEquals(map.getJoinedValue("foo", ", "), "bar"); assertEquals(map.get("foo"), Arrays.asList("bar")); assertEquals(map.getFirstValue("baz"), "foo"); assertEquals(map.getJoinedValue("baz", ", "), "foo, bar"); assertEquals(map.get("baz"), Arrays.asList("foo", "bar")); } @Test public void deleteAllNullArrayTest() { FluentStringsMap map = new FluentStringsMap(); map.add("foo", "bar"); map.add("baz", Arrays.asList("foo", "bar")); assertEquals(map.keySet(), new LinkedHashSet(Arrays.asList("foo", "baz"))); assertEquals(map.getFirstValue("foo"), "bar"); assertEquals(map.getJoinedValue("foo", ", "), "bar"); assertEquals(map.get("foo"), Arrays.asList("bar")); assertEquals(map.getFirstValue("baz"), "foo"); assertEquals(map.getJoinedValue("baz", ", "), "foo, bar"); assertEquals(map.get("baz"), Arrays.asList("foo", "bar")); map.deleteAll((String[]) null); assertEquals(map.keySet(), new LinkedHashSet(Arrays.asList("foo", "baz"))); assertEquals(map.getFirstValue("foo"), "bar"); assertEquals(map.getJoinedValue("foo", ", "), "bar"); assertEquals(map.get("foo"), Arrays.asList("bar")); assertEquals(map.getFirstValue("baz"), "foo"); assertEquals(map.getJoinedValue("baz", ", "), "foo, bar"); assertEquals(map.get("baz"), Arrays.asList("foo", "bar")); } @Test public void deleteAllNullCollectionTest() { FluentStringsMap map = new FluentStringsMap(); map.add("foo", "bar"); map.add("baz", Arrays.asList("foo", "bar")); assertEquals(map.keySet(), new LinkedHashSet(Arrays.asList("foo", "baz"))); assertEquals(map.getFirstValue("foo"), "bar"); assertEquals(map.getJoinedValue("foo", ", "), "bar"); assertEquals(map.get("foo"), Arrays.asList("bar")); assertEquals(map.getFirstValue("baz"), "foo"); assertEquals(map.getJoinedValue("baz", ", "), "foo, bar"); assertEquals(map.get("baz"), Arrays.asList("foo", "bar")); map.deleteAll((Collection) null); assertEquals(map.keySet(), new LinkedHashSet(Arrays.asList("foo", "baz"))); assertEquals(map.getFirstValue("foo"), "bar"); assertEquals(map.getJoinedValue("foo", ", "), "bar"); assertEquals(map.get("foo"), Arrays.asList("bar")); assertEquals(map.getFirstValue("baz"), "foo"); assertEquals(map.getJoinedValue("baz", ", "), "foo, bar"); assertEquals(map.get("baz"), Arrays.asList("foo", "bar")); } @Test public void replaceArrayTest() { FluentStringsMap map = new FluentStringsMap(); map.add("foo", "bar"); map.add("baz", Arrays.asList("foo", "bar")); assertEquals(map.keySet(), new LinkedHashSet(Arrays.asList("foo", "baz"))); assertEquals(map.getFirstValue("foo"), "bar"); assertEquals(map.getJoinedValue("foo", ", "), "bar"); assertEquals(map.get("foo"), Arrays.asList("bar")); assertEquals(map.getFirstValue("baz"), "foo"); assertEquals(map.getJoinedValue("baz", ", "), "foo, bar"); assertEquals(map.get("baz"), Arrays.asList("foo", "bar")); map.replace("foo", "blub", "bla"); assertEquals(map.keySet(), new LinkedHashSet(Arrays.asList("foo", "baz"))); assertEquals(map.getFirstValue("foo"), "blub"); assertEquals(map.getJoinedValue("foo", ", "), "blub, bla"); assertEquals(map.get("foo"), Arrays.asList("blub", "bla")); assertEquals(map.getFirstValue("baz"), "foo"); assertEquals(map.getJoinedValue("baz", ", "), "foo, bar"); assertEquals(map.get("baz"), Arrays.asList("foo", "bar")); } @Test public void replaceCollectionTest() { FluentStringsMap map = new FluentStringsMap(); map.add("foo", "bar"); map.add("baz", Arrays.asList("foo", "bar")); assertEquals(map.keySet(), new LinkedHashSet(Arrays.asList("foo", "baz"))); assertEquals(map.getFirstValue("foo"), "bar"); assertEquals(map.getJoinedValue("foo", ", "), "bar"); assertEquals(map.get("foo"), Arrays.asList("bar")); assertEquals(map.getFirstValue("baz"), "foo"); assertEquals(map.getJoinedValue("baz", ", "), "foo, bar"); assertEquals(map.get("baz"), Arrays.asList("foo", "bar")); map.replace("foo", Arrays.asList("blub", "bla")); assertEquals(map.keySet(), new LinkedHashSet(Arrays.asList("foo", "baz"))); assertEquals(map.getFirstValue("foo"), "blub"); assertEquals(map.getJoinedValue("foo", ", "), "blub, bla"); assertEquals(map.get("foo"), Arrays.asList("blub", "bla")); assertEquals(map.getFirstValue("baz"), "foo"); assertEquals(map.getJoinedValue("baz", ", "), "foo, bar"); assertEquals(map.get("baz"), Arrays.asList("foo", "bar")); } @Test public void replaceDifferentCaseTest() { FluentStringsMap map = new FluentStringsMap(); map.add("foo", "bar"); map.add("baz", Arrays.asList("foo", "bar")); assertEquals(map.keySet(), new LinkedHashSet(Arrays.asList("foo", "baz"))); assertEquals(map.getFirstValue("foo"), "bar"); assertEquals(map.getJoinedValue("foo", ", "), "bar"); assertEquals(map.get("foo"), Arrays.asList("bar")); assertEquals(map.getFirstValue("baz"), "foo"); assertEquals(map.getJoinedValue("baz", ", "), "foo, bar"); assertEquals(map.get("baz"), Arrays.asList("foo", "bar")); map.replace("Foo", Arrays.asList("blub", "bla")); assertEquals(map.keySet(), new LinkedHashSet(Arrays.asList("foo", "baz", "Foo"))); assertEquals(map.getFirstValue("foo"), "bar"); assertEquals(map.getJoinedValue("foo", ", "), "bar"); assertEquals(map.get("foo"), Arrays.asList("bar")); assertEquals(map.getFirstValue("baz"), "foo"); assertEquals(map.getJoinedValue("baz", ", "), "foo, bar"); assertEquals(map.get("baz"), Arrays.asList("foo", "bar")); assertEquals(map.getFirstValue("Foo"), "blub"); assertEquals(map.getJoinedValue("Foo", ", "), "blub, bla"); assertEquals(map.get("Foo"), Arrays.asList("blub", "bla")); } @Test public void replaceUndefinedTest() { FluentStringsMap map = new FluentStringsMap(); map.add("foo", "bar"); map.add("baz", Arrays.asList("foo", "bar")); assertEquals(map.keySet(), new LinkedHashSet(Arrays.asList("foo", "baz"))); assertEquals(map.getFirstValue("foo"), "bar"); assertEquals(map.getJoinedValue("foo", ", "), "bar"); assertEquals(map.get("foo"), Arrays.asList("bar")); assertEquals(map.getFirstValue("baz"), "foo"); assertEquals(map.getJoinedValue("baz", ", "), "foo, bar"); assertEquals(map.get("baz"), Arrays.asList("foo", "bar")); map.replace("bar", Arrays.asList("blub")); assertEquals(map.keySet(), new LinkedHashSet(Arrays.asList("foo", "baz", "bar"))); assertEquals(map.getFirstValue("foo"), "bar"); assertEquals(map.getJoinedValue("foo", ", "), "bar"); assertEquals(map.get("foo"), Arrays.asList("bar")); assertEquals(map.getFirstValue("baz"), "foo"); assertEquals(map.getJoinedValue("baz", ", "), "foo, bar"); assertEquals(map.get("baz"), Arrays.asList("foo", "bar")); assertEquals(map.getFirstValue("bar"), "blub"); assertEquals(map.getJoinedValue("bar", ", "), "blub"); assertEquals(map.get("bar"), Arrays.asList("blub")); } @Test public void replaceNullTest() { FluentStringsMap map = new FluentStringsMap(); map.add("foo", "bar"); map.add("baz", Arrays.asList("foo", "bar")); assertEquals(map.keySet(), new LinkedHashSet(Arrays.asList("foo", "baz"))); assertEquals(map.getFirstValue("foo"), "bar"); assertEquals(map.getJoinedValue("foo", ", "), "bar"); assertEquals(map.get("foo"), Arrays.asList("bar")); assertEquals(map.getFirstValue("baz"), "foo"); assertEquals(map.getJoinedValue("baz", ", "), "foo, bar"); assertEquals(map.get("baz"), Arrays.asList("foo", "bar")); map.replace(null, Arrays.asList("blub")); assertEquals(map.keySet(), new LinkedHashSet(Arrays.asList("foo", "baz"))); assertEquals(map.getFirstValue("foo"), "bar"); assertEquals(map.getJoinedValue("foo", ", "), "bar"); assertEquals(map.get("foo"), Arrays.asList("bar")); assertEquals(map.getFirstValue("baz"), "foo"); assertEquals(map.getJoinedValue("baz", ", "), "foo, bar"); assertEquals(map.get("baz"), Arrays.asList("foo", "bar")); } @Test public void replaceValueWithNullTest() { FluentStringsMap map = new FluentStringsMap(); map.add("foo", "bar"); map.add("baz", Arrays.asList("foo", "bar")); assertEquals(map.keySet(), new LinkedHashSet(Arrays.asList("foo", "baz"))); assertEquals(map.getFirstValue("foo"), "bar"); assertEquals(map.getJoinedValue("foo", ", "), "bar"); assertEquals(map.get("foo"), Arrays.asList("bar")); assertEquals(map.getFirstValue("baz"), "foo"); assertEquals(map.getJoinedValue("baz", ", "), "foo, bar"); assertEquals(map.get("baz"), Arrays.asList("foo", "bar")); map.replace("baz", (Collection) null); assertEquals(map.keySet(), new LinkedHashSet(Arrays.asList("foo"))); assertEquals(map.getFirstValue("foo"), "bar"); assertEquals(map.getJoinedValue("foo", ", "), "bar"); assertEquals(map.get("foo"), Arrays.asList("bar")); assertNull(map.getFirstValue("baz")); assertNull(map.getJoinedValue("baz", ", ")); assertNull(map.get("baz")); } @Test public void replaceAllMapTest1() { FluentStringsMap map = new FluentStringsMap(); map.add("foo", "bar"); map.add("bar", "foo, bar", "baz"); map.add("baz", Arrays.asList("foo", "bar")); assertEquals(map.keySet(), new LinkedHashSet(Arrays.asList("foo", "bar", "baz"))); assertEquals(map.getFirstValue("foo"), "bar"); assertEquals(map.getJoinedValue("foo", ", "), "bar"); assertEquals(map.get("foo"), Arrays.asList("bar")); assertEquals(map.getFirstValue("bar"), "foo, bar"); assertEquals(map.getJoinedValue("bar", ", "), "foo, bar, baz"); assertEquals(map.get("bar"), Arrays.asList("foo, bar", "baz")); assertEquals(map.getFirstValue("baz"), "foo"); assertEquals(map.getJoinedValue("baz", ", "), "foo, bar"); assertEquals(map.get("baz"), Arrays.asList("foo", "bar")); map.replaceAll(new FluentStringsMap().add("bar", "baz").add("Foo", "blub", "bla")); assertEquals(map.keySet(), new LinkedHashSet(Arrays.asList("foo", "bar", "baz", "Foo"))); assertEquals(map.getFirstValue("foo"), "bar"); assertEquals(map.getJoinedValue("foo", ", "), "bar"); assertEquals(map.get("foo"), Arrays.asList("bar")); assertEquals(map.getFirstValue("bar"), "baz"); assertEquals(map.getJoinedValue("bar", ", "), "baz"); assertEquals(map.get("bar"), Arrays.asList("baz")); assertEquals(map.getFirstValue("baz"), "foo"); assertEquals(map.getJoinedValue("baz", ", "), "foo, bar"); assertEquals(map.get("baz"), Arrays.asList("foo", "bar")); assertEquals(map.getFirstValue("Foo"), "blub"); assertEquals(map.getJoinedValue("Foo", ", "), "blub, bla"); assertEquals(map.get("Foo"), Arrays.asList("blub", "bla")); } @Test public void replaceAllTest2() { FluentStringsMap map = new FluentStringsMap(); map.add("foo", "bar"); map.add("bar", "foo, bar", "baz"); map.add("baz", Arrays.asList("foo", "bar")); assertEquals(map.keySet(), new LinkedHashSet(Arrays.asList("foo", "bar", "baz"))); assertEquals(map.getFirstValue("foo"), "bar"); assertEquals(map.getJoinedValue("foo", ", "), "bar"); assertEquals(map.get("foo"), Arrays.asList("bar")); assertEquals(map.getFirstValue("bar"), "foo, bar"); assertEquals(map.getJoinedValue("bar", ", "), "foo, bar, baz"); assertEquals(map.get("bar"), Arrays.asList("foo, bar", "baz")); assertEquals(map.getFirstValue("baz"), "foo"); assertEquals(map.getJoinedValue("baz", ", "), "foo, bar"); assertEquals(map.get("baz"), Arrays.asList("foo", "bar")); LinkedHashMap> newValues = new LinkedHashMap>(); newValues.put("bar", Arrays.asList("baz")); newValues.put("foo", null); map.replaceAll(newValues); assertEquals(map.keySet(), new LinkedHashSet(Arrays.asList("bar", "baz"))); assertNull(map.getFirstValue("foo")); assertNull(map.getJoinedValue("foo", ", ")); assertNull(map.get("foo")); assertEquals(map.getFirstValue("bar"), "baz"); assertEquals(map.getJoinedValue("bar", ", "), "baz"); assertEquals(map.get("bar"), Arrays.asList("baz")); assertEquals(map.getFirstValue("baz"), "foo"); assertEquals(map.getJoinedValue("baz", ", "), "foo, bar"); assertEquals(map.get("baz"), Arrays.asList("foo", "bar")); } @Test public void replaceAllNullTest1() { FluentStringsMap map = new FluentStringsMap(); map.add("foo", "bar"); map.add("bar", "foo, bar", "baz"); map.add("baz", Arrays.asList("foo", "bar")); assertEquals(map.keySet(), new LinkedHashSet(Arrays.asList("foo", "bar", "baz"))); assertEquals(map.getFirstValue("foo"), "bar"); assertEquals(map.getJoinedValue("foo", ", "), "bar"); assertEquals(map.get("foo"), Arrays.asList("bar")); assertEquals(map.getFirstValue("bar"), "foo, bar"); assertEquals(map.getJoinedValue("bar", ", "), "foo, bar, baz"); assertEquals(map.get("bar"), Arrays.asList("foo, bar", "baz")); assertEquals(map.getFirstValue("baz"), "foo"); assertEquals(map.getJoinedValue("baz", ", "), "foo, bar"); assertEquals(map.get("baz"), Arrays.asList("foo", "bar")); map.replaceAll((FluentStringsMap) null); assertEquals(map.keySet(), new LinkedHashSet(Arrays.asList("foo", "bar", "baz"))); assertEquals(map.getFirstValue("foo"), "bar"); assertEquals(map.getJoinedValue("foo", ", "), "bar"); assertEquals(map.get("foo"), Arrays.asList("bar")); assertEquals(map.getFirstValue("bar"), "foo, bar"); assertEquals(map.getJoinedValue("bar", ", "), "foo, bar, baz"); assertEquals(map.get("bar"), Arrays.asList("foo, bar", "baz")); assertEquals(map.getFirstValue("baz"), "foo"); assertEquals(map.getJoinedValue("baz", ", "), "foo, bar"); assertEquals(map.get("baz"), Arrays.asList("foo", "bar")); } @Test public void replaceAllNullTest2() { FluentStringsMap map = new FluentStringsMap(); map.add("foo", "bar"); map.add("bar", "foo, bar", "baz"); map.add("baz", Arrays.asList("foo", "bar")); assertEquals(map.keySet(), new LinkedHashSet(Arrays.asList("foo", "bar", "baz"))); assertEquals(map.getFirstValue("foo"), "bar"); assertEquals(map.getJoinedValue("foo", ", "), "bar"); assertEquals(map.get("foo"), Arrays.asList("bar")); assertEquals(map.getFirstValue("bar"), "foo, bar"); assertEquals(map.getJoinedValue("bar", ", "), "foo, bar, baz"); assertEquals(map.get("bar"), Arrays.asList("foo, bar", "baz")); assertEquals(map.getFirstValue("baz"), "foo"); assertEquals(map.getJoinedValue("baz", ", "), "foo, bar"); assertEquals(map.get("baz"), Arrays.asList("foo", "bar")); map.replaceAll((Map>) null); assertEquals(map.keySet(), new LinkedHashSet(Arrays.asList("foo", "bar", "baz"))); assertEquals(map.getFirstValue("foo"), "bar"); assertEquals(map.getJoinedValue("foo", ", "), "bar"); assertEquals(map.get("foo"), Arrays.asList("bar")); assertEquals(map.getFirstValue("bar"), "foo, bar"); assertEquals(map.getJoinedValue("bar", ", "), "foo, bar, baz"); assertEquals(map.get("bar"), Arrays.asList("foo, bar", "baz")); assertEquals(map.getFirstValue("baz"), "foo"); assertEquals(map.getJoinedValue("baz", ", "), "foo, bar"); assertEquals(map.get("baz"), Arrays.asList("foo", "bar")); } } async-http-client-1.6.5/src/test/java/com/ning/http/client/async/FollowingThreadTest.java000066400000000000000000000073621166553056000314550ustar00rootroot00000000000000/* * Copyright 2010 Ning, Inc. * * Ning licenses this file to you 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. */ package com.ning.http.client.async; import com.ning.http.client.AsyncHandler; import com.ning.http.client.AsyncHttpClient; import com.ning.http.client.AsyncHttpClientConfig; import com.ning.http.client.HttpResponseBodyPart; import com.ning.http.client.HttpResponseHeaders; import com.ning.http.client.HttpResponseStatus; import org.testng.annotations.Test; import java.io.IOException; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeoutException; /** * Simple stress test for exercising the follow redirect. */ public abstract class FollowingThreadTest extends AbstractBasicTest { private final static int COUNT = 10; @Test(timeOut = 30 * 1000, groups = {"online", "default_provider", "scalability"}) public void testFollowRedirect() throws IOException, ExecutionException, TimeoutException, InterruptedException { final CountDownLatch countDown = new CountDownLatch(COUNT); ExecutorService pool = Executors.newCachedThreadPool(); for (int i = 0; i < COUNT; i++) { pool.submit(new Runnable() { private int status; public void run() { final CountDownLatch l = new CountDownLatch(1); final AsyncHttpClient ahc = getAsyncHttpClient( new AsyncHttpClientConfig.Builder().setFollowRedirects(true).build()); try { ahc.prepareGet("http://www.google.com/").execute(new AsyncHandler() { public void onThrowable(Throwable t) { t.printStackTrace(); } public STATE onBodyPartReceived(HttpResponseBodyPart bodyPart) throws Exception { System.out.println(new String(bodyPart.getBodyPartBytes())); return STATE.CONTINUE; } public STATE onStatusReceived(HttpResponseStatus responseStatus) throws Exception { status = responseStatus.getStatusCode(); System.out.println(responseStatus.getStatusText()); return STATE.CONTINUE; } public STATE onHeadersReceived(HttpResponseHeaders headers) throws Exception { return STATE.CONTINUE; } public Integer onCompleted() throws Exception { l.countDown(); return status; } }); l.await(); } catch (Exception e) { e.printStackTrace(); } finally { ahc.close(); countDown.countDown(); } } }); } countDown.await(); } }async-http-client-1.6.5/src/test/java/com/ning/http/client/async/Head302Test.java000066400000000000000000000066461166553056000274570ustar00rootroot00000000000000/* * Copyright 2010 Ning, Inc. * * Ning licenses this file to you 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. */ package com.ning.http.client.async; import com.ning.http.client.AsyncCompletionHandlerBase; import com.ning.http.client.AsyncHttpClient; import com.ning.http.client.Request; import com.ning.http.client.RequestBuilder; import com.ning.http.client.Response; import org.eclipse.jetty.server.handler.AbstractHandler; import org.omg.CORBA.TIMEOUT; import org.testng.Assert; import org.testng.annotations.Test; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.util.concurrent.BrokenBarrierException; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; /** * Tests HEAD request that gets 302 response. * * @author Hubert Iwaniuk */ public abstract class Head302Test extends AbstractBasicTest { /** * Handler that does Found (302) in response to HEAD method. */ private class Head302handler extends AbstractHandler { public void handle(String s, org.eclipse.jetty.server.Request r, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { if ("HEAD".equalsIgnoreCase(request.getMethod())) { if (request.getPathInfo().endsWith("_moved")) { response.setStatus(HttpServletResponse.SC_OK); } else { response.setStatus(HttpServletResponse.SC_FOUND); // 302 response.setHeader("Location", request.getPathInfo() + "_moved"); } } else { // this handler is to handle HEAD reqeust response.setStatus(HttpServletResponse.SC_FORBIDDEN); } } } @Test(groups = {"standalone", "default_provider"}) public void testHEAD302() throws IOException, BrokenBarrierException, InterruptedException, ExecutionException, TimeoutException { AsyncHttpClient client = getAsyncHttpClient(null); final CountDownLatch l = new CountDownLatch(1); Request request = new RequestBuilder("HEAD").setUrl("http://127.0.0.1:" + port1 + "/Test").build(); client.executeRequest(request, new AsyncCompletionHandlerBase() { @Override public Response onCompleted(Response response) throws Exception { l.countDown(); return super.onCompleted(response); } }).get(3, TimeUnit.SECONDS); if (!l.await(TIMEOUT, TimeUnit.SECONDS)) { Assert.fail("Timeout out"); } client.close(); } @Override public AbstractHandler configureHandler() throws Exception { return new Head302handler(); } } async-http-client-1.6.5/src/test/java/com/ning/http/client/async/HostnameVerifierTest.java000066400000000000000000000307531166553056000316370ustar00rootroot00000000000000/* * Copyright (c) 2010-2011 Sonatype, Inc. All rights reserved. * * This program is licensed to you under the Apache License Version 2.0, * and you may not use this file except in compliance with the Apache License Version 2.0. * You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0. * * Unless required by applicable law or agreed to in writing, * software distributed under the Apache License Version 2.0 is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. */ package com.ning.http.client.async; import com.ning.http.client.AsyncHttpClient; import com.ning.http.client.AsyncHttpClientConfig.Builder; import com.ning.http.client.Response; import org.eclipse.jetty.server.Request; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.handler.AbstractHandler; import org.eclipse.jetty.server.ssl.SslSocketConnector; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.testng.annotations.AfterClass; import org.testng.annotations.AfterMethod; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; import javax.net.ssl.*; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.net.ConnectException; import java.net.ServerSocket; import java.net.URL; import java.security.KeyStore; import java.security.SecureRandom; import java.security.cert.CertificateException; import java.security.cert.X509Certificate; import java.util.Enumeration; import java.util.concurrent.Future; import java.util.concurrent.atomic.AtomicBoolean; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertNotNull; public abstract class HostnameVerifierTest extends AbstractBasicTest { protected final Logger log = LoggerFactory.getLogger(HostnameVerifierTest.class); public static class EchoHandler extends AbstractHandler { /* @Override */ public void handle(String pathInContext, Request r, HttpServletRequest httpRequest, HttpServletResponse httpResponse) throws ServletException, IOException { httpResponse.setContentType("text/html; charset=utf-8"); Enumeration e = httpRequest.getHeaderNames(); String param; while (e.hasMoreElements()) { param = e.nextElement().toString(); if (param.startsWith("LockThread")) { try { Thread.sleep(40 * 1000); } catch (InterruptedException ex) { // nothing to do here } } httpResponse.addHeader("X-" + param, httpRequest.getHeader(param)); } Enumeration i = httpRequest.getParameterNames(); StringBuilder requestBody = new StringBuilder(); while (i.hasMoreElements()) { param = i.nextElement().toString(); httpResponse.addHeader("X-" + param, httpRequest.getParameter(param)); requestBody.append(param); requestBody.append("_"); } String pathInfo = httpRequest.getPathInfo(); if (pathInfo != null) httpResponse.addHeader("X-pathInfo", pathInfo); String queryString = httpRequest.getQueryString(); if (queryString != null) httpResponse.addHeader("X-queryString", queryString); httpResponse.addHeader("X-KEEP-ALIVE", httpRequest.getRemoteAddr() + ":" + httpRequest.getRemotePort()); javax.servlet.http.Cookie[] cs = httpRequest.getCookies(); if (cs != null) { for (javax.servlet.http.Cookie c : cs) { httpResponse.addCookie(c); } } if (requestBody.length() > 0) { httpResponse.getOutputStream().write(requestBody.toString().getBytes()); } int size = 10 * 1024; if (httpRequest.getContentLength() > 0) { size = httpRequest.getContentLength(); } byte[] bytes = new byte[size]; if (bytes.length > 0) { //noinspection ResultOfMethodCallIgnored int read = httpRequest.getInputStream().read(bytes); httpResponse.getOutputStream().write(bytes, 0, read); } httpResponse.setStatus(200); httpResponse.getOutputStream().flush(); httpResponse.getOutputStream().close(); } } @AfterClass(alwaysRun = true) public void tearDownGlobal() throws Exception { server.stop(); } @AfterMethod(alwaysRun = true) public void tearDownProps() throws Exception { System.clearProperty("javax.net.ssl.keyStore"); System.clearProperty("javax.net.ssl.trustStore"); } protected String getTargetUrl() { return String.format("https://127.0.0.1:%d/foo/test", port1); } public AbstractHandler configureHandler() throws Exception { return new EchoHandler(); } protected int findFreePort() throws IOException { ServerSocket socket = null; try { socket = new ServerSocket(0); return socket.getLocalPort(); } finally { if (socket != null) { socket.close(); } } } @BeforeClass(alwaysRun = true) public void setUpGlobal() throws Exception { server = new Server(); port1 = findFreePort(); SslSocketConnector connector = new SslSocketConnector(); connector.setHost("127.0.0.1"); connector.setPort(port1); ClassLoader cl = getClass().getClassLoader(); // override system properties URL cacertsUrl = cl.getResource("ssltest-cacerts.jks"); String trustStoreFile = new File(cacertsUrl.toURI()).getAbsolutePath(); connector.setTruststore(trustStoreFile); connector.setTrustPassword("changeit"); connector.setTruststoreType("JKS"); log.info("SSL certs path: {}", trustStoreFile); // override system properties URL keystoreUrl = cl.getResource("ssltest-keystore.jks"); String keyStoreFile = new File(keystoreUrl.toURI()).getAbsolutePath(); connector.setKeystore(keyStoreFile); connector.setKeyPassword("changeit"); connector.setKeystoreType("JKS"); log.info("SSL keystore path: {}", keyStoreFile); server.addConnector(connector); server.setHandler(configureHandler()); server.start(); log.info("Local HTTP server started successfully"); } @Test(groups = {"standalone", "default_provider"}) public void positiveHostnameVerifierTest() throws Throwable { final AsyncHttpClient client = getAsyncHttpClient(new Builder().setHostnameVerifier(new PositiveHostVerifier()).setSSLContext(createSSLContext()).build()); ClassLoader cl = getClass().getClassLoader(); // override system properties URL url = cl.getResource("SimpleTextFile.txt"); File file = new File(url.toURI()); Future f = client.preparePost(getTargetUrl()).setBody(file).setHeader("Content-Type", "text/html").execute(); Response resp = f.get(); assertNotNull(resp); assertEquals(resp.getStatusCode(), HttpServletResponse.SC_OK); assertEquals(resp.getResponseBody(), "This is a simple test file"); } @Test(groups = {"standalone", "default_provider"}) public void negativeHostnameVerifierTest() throws Throwable { final AsyncHttpClient client = getAsyncHttpClient(new Builder().setHostnameVerifier(new NegativeHostVerifier()).setSSLContext(createSSLContext()).build()); ClassLoader cl = getClass().getClassLoader(); // override system properties URL url = cl.getResource("SimpleTextFile.txt"); File file = new File(url.toURI()); try { Future f = client.preparePost(getTargetUrl()).setBody(file).setHeader("Content-Type", "text/html").execute(); } catch (ConnectException ex) { assertEquals(ConnectException.class, ex.getClass()); } } @Test(groups = {"standalone", "default_provider"}) public void remoteIDHostnameVerifierTest() throws Throwable { final AsyncHttpClient client = getAsyncHttpClient(new Builder().setHostnameVerifier(new CheckHost("bouette")).setSSLContext(createSSLContext()).build()); ClassLoader cl = getClass().getClassLoader(); // override system properties URL url = cl.getResource("SimpleTextFile.txt"); File file = new File(url.toURI()); try { Future f = client.preparePost(getTargetUrl()).setBody(file).setHeader("Content-Type", "text/html").execute(); } catch (ConnectException ex) { assertEquals(ConnectException.class, ex.getClass()); } } @Test(groups = {"standalone", "default_provider"}) public void remotePosHostnameVerifierTest() throws Throwable { final AsyncHttpClient client = getAsyncHttpClient(new Builder().setHostnameVerifier(new CheckHost("localhost")).setSSLContext(createSSLContext()).build()); ClassLoader cl = getClass().getClassLoader(); // override system properties URL url = cl.getResource("SimpleTextFile.txt"); File file = new File(url.toURI()); try { Future f = client.preparePost(getTargetUrl()).setBody(file).setHeader("Content-Type", "text/html").execute(); } catch (ConnectException ex) { assertEquals(ConnectException.class, ex.getClass()); } } public static class PositiveHostVerifier implements HostnameVerifier { public boolean verify(String s, SSLSession sslSession) { return true; } } public static class NegativeHostVerifier implements HostnameVerifier { public boolean verify(String s, SSLSession sslSession) { return true; } } public static class CheckHost implements HostnameVerifier { private final String hostName; public CheckHost(String hostName) { this.hostName = hostName; } public boolean verify(String s, SSLSession sslSession) { if (s != null && s.equalsIgnoreCase(hostName)) { return true; } return false; } } private static SSLContext createSSLContext() { try { InputStream keyStoreStream = HostnameVerifierTest.class.getResourceAsStream("ssltest-cacerts.jks"); char[] keyStorePassword = "changeit".toCharArray(); KeyStore ks = KeyStore.getInstance("JKS"); ks.load(keyStoreStream, keyStorePassword); // Set up key manager factory to use our key store char[] certificatePassword = "changeit".toCharArray(); KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509"); kmf.init(ks, certificatePassword); // Initialize the SSLContext to work with our key managers. KeyManager[] keyManagers = kmf.getKeyManagers(); TrustManager[] trustManagers = new TrustManager[]{DUMMY_TRUST_MANAGER}; SecureRandom secureRandom = new SecureRandom(); SSLContext sslContext = SSLContext.getInstance("TLS"); sslContext.init(keyManagers, trustManagers, secureRandom); return sslContext; } catch (Exception e) { throw new Error("Failed to initialize the server-side SSLContext", e); } } private static final AtomicBoolean TRUST_SERVER_CERT = new AtomicBoolean(true); private static final TrustManager DUMMY_TRUST_MANAGER = new X509TrustManager() { public X509Certificate[] getAcceptedIssuers() { return new X509Certificate[0]; } public void checkClientTrusted( X509Certificate[] chain, String authType) throws CertificateException { } public void checkServerTrusted( X509Certificate[] chain, String authType) throws CertificateException { if (!TRUST_SERVER_CERT.get()) { throw new CertificateException("Server certificate not trusted."); } } }; } async-http-client-1.6.5/src/test/java/com/ning/http/client/async/HttpToHttpsRedirectTest.java000066400000000000000000000165161166553056000323150ustar00rootroot00000000000000/* * Copyright 2010 Ning, Inc. * * Ning licenses this file to you 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. */ package com.ning.http.client.async; import com.ning.http.client.AsyncHttpClient; import com.ning.http.client.AsyncHttpClientConfig; import com.ning.http.client.Response; 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.server.ssl.SslSocketConnector; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.File; import java.io.IOException; import java.net.URI; import java.net.URL; import java.util.Enumeration; import java.util.concurrent.atomic.AtomicBoolean; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertNotNull; public abstract class HttpToHttpsRedirectTest extends AbstractBasicTest { private final AtomicBoolean isSet = new AtomicBoolean(false); private class Relative302Handler extends AbstractHandler { public void handle(String s, Request r, HttpServletRequest httpRequest, HttpServletResponse httpResponse) throws IOException, ServletException { String param; httpResponse.setContentType("text/html; charset=utf-8"); Enumeration e = httpRequest.getHeaderNames(); while (e.hasMoreElements()) { param = e.nextElement().toString(); if (param.startsWith("X-redirect") && !isSet.getAndSet(true)) { httpResponse.addHeader("Location", httpRequest.getHeader(param)); httpResponse.setStatus(302); httpResponse.getOutputStream().flush(); httpResponse.getOutputStream().close(); return; } } if (r.getScheme().equalsIgnoreCase("https")) { httpResponse.addHeader("X-httpToHttps", "PASS"); isSet.getAndSet(false); } httpResponse.setStatus(200); httpResponse.getOutputStream().flush(); httpResponse.getOutputStream().close(); } } @BeforeClass(alwaysRun = true) public void setUpGlobal() throws Exception { server = new Server(); port1 = findFreePort(); port2 = findFreePort(); Connector listener = new SelectChannelConnector(); listener.setHost("127.0.0.1"); listener.setPort(port1); server.addConnector(listener); SslSocketConnector connector = new SslSocketConnector(); connector.setHost("127.0.0.1"); connector.setPort(port2); ClassLoader cl = getClass().getClassLoader(); // override system properties URL cacertsUrl = cl.getResource("ssltest-cacerts.jks"); String trustStoreFile = new File(cacertsUrl.toURI()).getAbsolutePath(); connector.setTruststore(trustStoreFile); connector.setTrustPassword("changeit"); connector.setTruststoreType("JKS"); log.info("SSL certs path: {}", trustStoreFile); // override system properties URL keystoreUrl = cl.getResource("ssltest-keystore.jks"); String keyStoreFile = new File(keystoreUrl.toURI()).getAbsolutePath(); connector.setKeystore(keyStoreFile); connector.setKeyPassword("changeit"); connector.setKeystoreType("JKS"); log.info("SSL keystore path: {}", keyStoreFile); server.addConnector(connector); server.setHandler(new Relative302Handler()); server.start(); log.info("Local HTTP server started successfully"); } private String getBaseUrl(URI uri) { String url = uri.toString(); int port = uri.getPort(); if (port == -1) { port = getPort(uri); url = url.substring(0, url.length() - 1) + ":" + port; } return url.substring(0, url.lastIndexOf(":") + String.valueOf(port).length() + 1); } private static int getPort(URI uri) { int port = uri.getPort(); if (port == -1) port = uri.getScheme().equals("http") ? 80 : 443; return port; } @Test(groups = {"standalone", "default_provider"}) public void httpToHttpsRedirect() throws Throwable { isSet.getAndSet(false); AsyncHttpClientConfig cg = new AsyncHttpClientConfig.Builder().setMaximumNumberOfRedirects(5).setFollowRedirects(true).build(); AsyncHttpClient c = getAsyncHttpClient(cg); Response response = c.prepareGet(getTargetUrl()) .setHeader("X-redirect", getTargetUrl2()) .execute().get(); assertNotNull(response); assertEquals(response.getStatusCode(), 200); assertEquals(response.getHeader("X-httpToHttps"), "PASS"); c.close(); } public String getTargetUrl2() { return String.format("https://127.0.0.1:%d/foo/test", port2); } @Test(groups = {"standalone", "default_provider"}) public void httpToHttpsProperConfig() throws Throwable { isSet.getAndSet(false); AsyncHttpClientConfig cg = new AsyncHttpClientConfig.Builder().setMaximumNumberOfRedirects(5).setFollowRedirects(true).build(); AsyncHttpClient c = getAsyncHttpClient(cg); Response response = c.prepareGet(getTargetUrl()) .setHeader("X-redirect", getTargetUrl2() + "/test2") .execute().get(); assertNotNull(response); assertEquals(response.getStatusCode(), 200); assertEquals(response.getHeader("X-httpToHttps"), "PASS"); // Test if the internal channel is downgraded to clean http. response = c.prepareGet(getTargetUrl()) .setHeader("X-redirect", getTargetUrl2() + "/foo2") .execute().get(); assertNotNull(response); assertEquals(response.getStatusCode(), 200); assertEquals(response.getHeader("X-httpToHttps"), "PASS"); c.close(); } @Test(groups = {"standalone", "default_provider"}) public void relativeLocationUrl() throws Throwable { isSet.getAndSet(false); AsyncHttpClientConfig cg = new AsyncHttpClientConfig.Builder().setMaximumNumberOfRedirects(5).setFollowRedirects(true).build(); AsyncHttpClient c = getAsyncHttpClient(cg); Response response = c.prepareGet(getTargetUrl()) .setHeader("X-redirect", "/foo/test") .execute().get(); assertNotNull(response); assertEquals(response.getStatusCode(), 302); assertEquals(response.getUri().toString(), getTargetUrl()); c.close(); } } async-http-client-1.6.5/src/test/java/com/ning/http/client/async/IdleStateHandlerTest.java000066400000000000000000000061201166553056000315300ustar00rootroot00000000000000/* * Copyright 2010 Ning, Inc. * * Ning licenses this file to you 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. */ package com.ning.http.client.async; import com.ning.http.client.AsyncHttpClient; import com.ning.http.client.AsyncHttpClientConfig; 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.testng.annotations.BeforeClass; import org.testng.annotations.Test; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.util.concurrent.ExecutionException; import java.util.concurrent.atomic.AtomicBoolean; import static org.testng.Assert.fail; public abstract class IdleStateHandlerTest extends AbstractBasicTest { private final AtomicBoolean isSet = new AtomicBoolean(false); private class IdleStateHandler extends AbstractHandler { public void handle(String s, Request r, HttpServletRequest httpRequest, HttpServletResponse httpResponse) throws IOException, ServletException { try { Thread.sleep(20 * 1000); } catch (InterruptedException e) { e.printStackTrace(); } httpResponse.setStatus(200); httpResponse.getOutputStream().flush(); httpResponse.getOutputStream().close(); } } @BeforeClass(alwaysRun = true) public void setUpGlobal() throws Exception { server = new Server(); port1 = findFreePort(); Connector listener = new SelectChannelConnector(); listener.setHost("127.0.0.1"); listener.setPort(port1); server.addConnector(listener); server.setHandler(new IdleStateHandler()); server.start(); log.info("Local HTTP server started successfully"); } @Test(groups = {"online", "default_provider"}) public void idleStateTest() throws Throwable { isSet.getAndSet(false); AsyncHttpClientConfig cg = new AsyncHttpClientConfig.Builder().setIdleConnectionInPoolTimeoutInMs(10 * 1000).build(); AsyncHttpClient c = getAsyncHttpClient(cg); try { c.prepareGet(getTargetUrl()).execute().get(); } catch (ExecutionException e) { fail("Should allow to finish processing request.", e); } finally { c.close(); } } } async-http-client-1.6.5/src/test/java/com/ning/http/client/async/InputStreamTest.java000066400000000000000000000071121166553056000306310ustar00rootroot00000000000000/* * Copyright 2010 Ning, Inc. * * Ning licenses this file to you 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. */ package com.ning.http.client.async; import com.ning.http.client.AsyncHttpClient; import com.ning.http.client.FluentCaseInsensitiveStringsMap; import com.ning.http.client.Response; import org.eclipse.jetty.server.Request; import org.eclipse.jetty.server.handler.AbstractHandler; import org.testng.annotations.Test; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.InputStream; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeoutException; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertNotNull; public abstract class InputStreamTest extends AbstractBasicTest { private class InputStreamHandler extends AbstractHandler { public void handle(String s, Request r, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { if ("POST".equalsIgnoreCase(request.getMethod())) { byte[] b = new byte[3]; request.getInputStream().read(b, 0, 3); response.setStatus(HttpServletResponse.SC_OK); response.addHeader("X-Param", new String(b)); } else { // this handler is to handle POST request response.sendError(HttpServletResponse.SC_FORBIDDEN); } response.getOutputStream().flush(); response.getOutputStream().close(); } } @Test(groups = {"standalone", "default_provider"}) public void testInvalidInputStream() throws IOException, ExecutionException, TimeoutException, InterruptedException { AsyncHttpClient c = getAsyncHttpClient(null); FluentCaseInsensitiveStringsMap h = new FluentCaseInsensitiveStringsMap(); h.add("Content-Type", "application/x-www-form-urlencoded"); InputStream is = new InputStream() { public int readAllowed; @Override public int available() { return 1; // Fake } @Override public int read() throws IOException { int fakeCount = readAllowed++; if (fakeCount == 0) { return (int) 'a'; } else if (fakeCount == 1) { return (int) 'b'; } else if (fakeCount == 2) { return (int) 'c'; } else { return -1; } } }; Response resp = c.preparePost(getTargetUrl()).setHeaders(h).setBody(is).execute().get(); assertNotNull(resp); assertEquals(resp.getStatusCode(), HttpServletResponse.SC_OK); assertEquals(resp.getHeader("X-Param"), "abc"); c.close(); } @Override public AbstractHandler configureHandler() throws Exception { return new InputStreamHandler(); } } async-http-client-1.6.5/src/test/java/com/ning/http/client/async/ListenableFutureTest.java000066400000000000000000000042341166553056000316350ustar00rootroot00000000000000/* * Copyright (c) 2010-2011 Sonatype, Inc. All rights reserved. * * This program is licensed to you under the Apache License Version 2.0, * and you may not use this file except in compliance with the Apache License Version 2.0. * You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0. * * Unless required by applicable law or agreed to in writing, * software distributed under the Apache License Version 2.0 is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. */ package com.ning.http.client.async; import com.ning.http.client.AsyncHttpClient; import com.ning.http.client.ListenableFuture; import com.ning.http.client.Response; import org.testng.annotations.Test; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutionException; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; import static org.testng.Assert.assertEquals; public abstract class ListenableFutureTest extends AbstractBasicTest { @Test(groups = {"standalone", "default_provider"}) public void testListenableFuture() throws Throwable { final AtomicInteger statusCode = new AtomicInteger(500); AsyncHttpClient ahc = getAsyncHttpClient(null); final CountDownLatch latch = new CountDownLatch(1); final ListenableFuture future = ahc.prepareGet(getTargetUrl()).execute(); future.addListener(new Runnable(){ public void run() { try { statusCode.set(future.get().getStatusCode()); latch.countDown(); } catch (InterruptedException e) { e.printStackTrace(); } catch (ExecutionException e) { e.printStackTrace(); } } }, Executors.newFixedThreadPool(1)); latch.await(10, TimeUnit.SECONDS); assertEquals(statusCode.get(), 200); ahc.close(); } } async-http-client-1.6.5/src/test/java/com/ning/http/client/async/MaxConnectionsInThreads.java000066400000000000000000000160171166553056000322540ustar00rootroot00000000000000/* * Copyright 2010 Ning, Inc. * * Ning licenses this file to you 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. * */ package com.ning.http.client.async; import com.ning.http.client.AsyncHttpClient; import com.ning.http.client.AsyncHttpClientConfig; import org.eclipse.jetty.server.Connector; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.nio.SelectChannelConnector; import org.eclipse.jetty.servlet.ServletContextHandler; import org.eclipse.jetty.servlet.ServletHolder; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.OutputStream; import java.net.URI; import java.net.URISyntaxException; import java.util.ArrayList; import java.util.List; import static org.testng.AssertJUnit.assertTrue; abstract public class MaxConnectionsInThreads extends AbstractBasicTest { private static URI servletEndpointUri; @Test(groups = {"online", "default_provider"}) public void testMaxConnectionsWithinThreads() { String[] urls = new String[]{ servletEndpointUri.toString(), servletEndpointUri.toString()}; final AsyncHttpClient client = new AsyncHttpClient(new AsyncHttpClientConfig.Builder() .setConnectionTimeoutInMs(1000) .setRequestTimeoutInMs(5000) .setAllowPoolingConnection(true) .setMaximumConnectionsTotal(1) .setMaximumConnectionsPerHost(1) .build()); final Boolean[] caughtError = new Boolean[]{Boolean.FALSE}; List ts = new ArrayList(); for (int i = 0; i < urls.length; i++) { final String url = urls[i]; Thread t = new Thread() { public void run() { try { client.prepareGet(url).execute(); } catch (IOException e) { // assert that 2nd request fails, because maxTotalConnections=1 // System.out.println(i); caughtError[0] = true; System.err.println("============"); e.printStackTrace(); System.err.println("============"); } } }; t.start(); ts.add(t); } for (Thread t : ts) { try { t.join(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } // Let the threads finish try { Thread.sleep(4500); } catch (InterruptedException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } assertTrue("Max Connections should have been reached", caughtError[0]); boolean errorInNotThread = false; for (int i = 0; i < urls.length; i++) { final String url = urls[i]; try { client.prepareGet(url).execute(); // client.prepareGet(url).execute(); } catch (IOException e) { // assert that 2nd request fails, because maxTotalConnections=1 // System.out.println(i); errorInNotThread = true; System.err.println("============"); e.printStackTrace(); System.err.println("============"); } } // Let the request finish try { Thread.sleep(2500); } catch (InterruptedException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } assertTrue("Max Connections should have been reached", errorInNotThread); client.close(); } @Override @BeforeClass public void setUpGlobal() throws Exception { server = new Server(); port1 = findFreePort(); Connector listener = new SelectChannelConnector(); listener.setHost("127.0.0.1"); listener.setPort(port1); server.addConnector(listener); ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS); context.setContextPath("/"); server.setHandler(context); context.addServlet(new ServletHolder(new MockTimeoutHttpServlet()), "/timeout/*"); server.start(); String endpoint = "http://127.0.0.1:" + port1 + "/timeout/"; servletEndpointUri = new URI(endpoint); } public String getTargetUrl() { String s = "http://127.0.0.1:" + port1 + "/timeout/"; try { servletEndpointUri = new URI(s); } catch (URISyntaxException e) { e.printStackTrace(); } return s; } public static class MockTimeoutHttpServlet extends HttpServlet { private static final String contentType = "text/plain"; public static long DEFAULT_TIMEOUT = 2000; public void service(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException { res.setStatus(200); res.addHeader("Content-Type", contentType); long sleepTime = DEFAULT_TIMEOUT; try { sleepTime = Integer.parseInt(req.getParameter("timeout")); } catch (NumberFormatException e) { sleepTime = DEFAULT_TIMEOUT; } try { System.out.println("======================================="); System.out.println("Servlet is sleeping for: " + sleepTime); System.out.println("======================================="); System.out.flush(); Thread.sleep(sleepTime); System.out.println("======================================="); System.out.println("Servlet is awake for"); System.out.println("======================================="); System.out.flush(); } catch (Exception e) { } res.setHeader("XXX", "TripleX"); byte[] retVal = "1".getBytes(); OutputStream os = res.getOutputStream(); res.setContentLength(retVal.length); os.write(retVal); os.close(); } } } async-http-client-1.6.5/src/test/java/com/ning/http/client/async/MaxTotalConnectionTest.java000066400000000000000000000125631166553056000321350ustar00rootroot00000000000000/* * Copyright 2010 Ning, Inc. * * Ning licenses this file to you 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. */ package com.ning.http.client.async; import com.ning.http.client.AsyncHttpClient; import com.ning.http.client.AsyncHttpClientConfig; import com.ning.http.client.Response; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.testng.Assert; import org.testng.annotations.Test; import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.util.concurrent.ExecutionException; import java.util.concurrent.Future; public abstract class MaxTotalConnectionTest extends AbstractBasicTest { protected final Logger log = LoggerFactory.getLogger(AbstractBasicTest.class); @Test(groups = {"standalone", "default_provider"}) public void testMaxTotalConnectionsExceedingException() { String[] urls = new String[]{ "http://google.com", "http://github.com/"}; AsyncHttpClient client = getAsyncHttpClient( new AsyncHttpClientConfig.Builder() .setConnectionTimeoutInMs(1000) .setRequestTimeoutInMs(5000) .setAllowPoolingConnection(false) .setMaximumConnectionsTotal(1) .setMaximumConnectionsPerHost(1) .build() ); boolean caughtError = false; for (int i = 0; i < urls.length; i++) { try { client.prepareGet(urls[i]).execute(); } catch (IOException e) { // assert that 2nd request fails, because maxTotalConnections=1 Assert.assertEquals(1, i); caughtError = true; } } Assert.assertTrue(caughtError); client.close(); } @Test public void testMaxTotalConnections() { String[] urls = new String[]{ "http://google.com", "http://lenta.ru"}; AsyncHttpClient client = getAsyncHttpClient( new AsyncHttpClientConfig.Builder() .setConnectionTimeoutInMs(1000) .setRequestTimeoutInMs(5000) .setAllowPoolingConnection(false) .setMaximumConnectionsTotal(2) .setMaximumConnectionsPerHost(1) .build() ); for (String url : urls) { try { client.prepareGet(url).execute(); } catch (IOException e) { Assert.fail("Smth wrong with connections handling!"); } } client.close(); } /** * JFA: Disable this test for 1.2.0 release as it can easily fail because a request may complete * before the second one is made, hence failing. The issue occurs frequently on Linux. */ @Test(enabled = false) public void testMaxTotalConnectionsCorrectExceptionHandling() { String[] urls = new String[]{ "http://google.com", "http://github.com/"}; AsyncHttpClient client = getAsyncHttpClient( new AsyncHttpClientConfig.Builder() .setConnectionTimeoutInMs(1000) .setRequestTimeoutInMs(5000) .setAllowPoolingConnection(false) .setMaximumConnectionsTotal(1) .setMaximumConnectionsPerHost(1) .build() ); List futures = new ArrayList(); boolean caughtError = false; for (int i = 0; i < urls.length; i++) { try { Future future = client.prepareGet(urls[i]).execute(); if (future != null) { futures.add(future); } } catch (IOException e) { // assert that 2nd request fails, because maxTotalConnections=1 Assert.assertEquals(i, 1); caughtError = true; } } Assert.assertTrue(caughtError); // get results of executed requests for (Future future : futures) { try { Object res = future.get(); } catch (InterruptedException e) { log.error("Error!", e); } catch (ExecutionException e) { log.error("Error!", e); } } // try to execute once again, expecting that 1 connection is released caughtError = false; for (int i = 0; i < urls.length; i++) { try { client.prepareGet(urls[i]).execute(); } catch (IOException e) { // assert that 2nd request fails, because maxTotalConnections=1 Assert.assertEquals(i, 1); caughtError = true; } } Assert.assertTrue(caughtError); client.close(); } } async-http-client-1.6.5/src/test/java/com/ning/http/client/async/MultipartUploadTest.java000066400000000000000000000420541166553056000315100ustar00rootroot00000000000000/* * Copyright (c) 2010-2011 Sonatype, Inc. All rights reserved. * * This program is licensed to you under the Apache License Version 2.0, * and you may not use this file except in compliance with the Apache License Version 2.0. * You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0. * * Unless required by applicable law or agreed to in writing, * software distributed under the Apache License Version 2.0 is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. */ package com.ning.http.client.async; import com.ning.http.client.AsyncHttpClient; import com.ning.http.client.AsyncHttpClientConfig; import com.ning.http.client.ByteArrayPart; import com.ning.http.client.FilePart; import com.ning.http.client.RequestBuilder; import com.ning.http.client.Response; import com.ning.http.client.StringPart; import com.ning.http.util.AsyncHttpProviderUtils; import org.apache.commons.fileupload.FileItemIterator; import org.apache.commons.fileupload.FileItemStream; import org.apache.commons.fileupload.FileUploadException; import org.apache.commons.fileupload.servlet.ServletFileUpload; import org.apache.commons.fileupload.util.Streams; import org.apache.commons.io.FileUtils; import org.apache.commons.io.IOUtils; import org.eclipse.jetty.server.Connector; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.nio.SelectChannelConnector; import org.eclipse.jetty.servlet.ServletContextHandler; import org.eclipse.jetty.servlet.ServletHolder; import org.testng.annotations.AfterClass; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.Writer; import java.net.URI; import java.net.URISyntaxException; import java.net.URL; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.UUID; import java.util.zip.GZIPInputStream; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertNotNull; import static org.testng.Assert.assertTrue; import static org.testng.Assert.fail; /** * @author dominict */ public abstract class MultipartUploadTest extends AbstractBasicTest { private String BASE_URL; private String servletEndpointRedirectUrl; public static byte GZIPTEXT[] = new byte[]{31, -117, 8, 8, 11, 43, 79, 75, 0, 3, 104, 101, 108, 108, 111, 46, 116, 120, 116, 0, -53, 72, -51, -55, -55, -25, 2, 0, 32, 48, 58, 54, 6, 0, 0, 0}; @BeforeClass public void setUp() throws Exception { server = new Server(); port1 = findFreePort(); Connector listener = new SelectChannelConnector(); listener.setHost("localhost"); listener.setPort(port1); server.addConnector(listener); ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS); context.setContextPath("/"); context.addServlet(new ServletHolder(new MockMultipartUploadServlet()), "/upload/*"); server.setHandler(context); server.start(); servletEndpointRedirectUrl = "http://localhost" + ":" + port1; } @AfterClass public void stop() { try { if (server != null) { server.stop(); } } catch (Exception e) { System.err.print("Error stopping servlet tester"); e.printStackTrace(); } } private File getClasspathFile(String file) throws FileNotFoundException { ClassLoader cl = null; try { cl = Thread.currentThread().getContextClassLoader(); } catch (Throwable ex) { } if (cl == null) { cl = MultipartUploadTest.class.getClassLoader(); } URL resourceUrl = cl.getResource(file); try { return new File(new URI(resourceUrl.toString()).getSchemeSpecificPart()); } catch (URISyntaxException e) { throw new FileNotFoundException(file); } } /** * Tests that the streaming of a file works. */ @Test (enabled = true) public void testSendingSmallFilesAndByteArray() { String expectedContents = "filecontent: hello"; String expectedContents2 = "gzipcontent: hello"; String expectedContents3 = "filecontent: hello2"; String testResource1 = "textfile.txt"; String testResource2 = "gzip.txt.gz"; String testResource3 = "textfile2.txt"; File testResource1File = null; try { testResource1File = getClasspathFile(testResource1); } catch (FileNotFoundException e) { // TODO Auto-generated catch block fail("unable to find " + testResource1); } File testResource2File = null; try { testResource2File = getClasspathFile(testResource2); } catch (FileNotFoundException e) { // TODO Auto-generated catch block fail("unable to find " + testResource2); } File testResource3File = null; try { testResource3File = getClasspathFile(testResource3); } catch (FileNotFoundException e) { // TODO Auto-generated catch block fail("unable to find " + testResource3); } List testFiles = new ArrayList(); testFiles.add(testResource1File); testFiles.add(testResource2File); testFiles.add(testResource3File); List expected = new ArrayList(); expected.add(expectedContents); expected.add(expectedContents2); expected.add(expectedContents3); List gzipped = new ArrayList(); gzipped.add(false); gzipped.add(true); gzipped.add(false); boolean tmpFileCreated = false; File tmpFile = null; FileOutputStream os = null; try { tmpFile = File.createTempFile("textbytearray", ".txt"); os = new FileOutputStream(tmpFile); IOUtils.write(expectedContents.getBytes("UTF-8"), os); tmpFileCreated = true; testFiles.add(tmpFile); expected.add(expectedContents); gzipped.add(false); } catch (FileNotFoundException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } catch (IOException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } finally { if (os != null) { IOUtils.closeQuietly(os); } } if (!tmpFileCreated) { fail("Unable to test ByteArrayMultiPart, as unable to write to filesystem the tmp test content"); } AsyncHttpClientConfig.Builder bc = new AsyncHttpClientConfig.Builder(); bc.setFollowRedirects(true); AsyncHttpClient c = new AsyncHttpClient(bc.build()); try { RequestBuilder builder = new RequestBuilder("POST"); builder.setUrl(servletEndpointRedirectUrl + "/upload/bob"); builder.addBodyPart(new FilePart("file1", testResource1File, "text/plain", "UTF-8")); builder.addBodyPart(new FilePart("file2", testResource2File, "application/x-gzip", null)); builder.addBodyPart(new StringPart("Name", "Dominic")); builder.addBodyPart(new FilePart("file3", testResource3File, "text/plain", "UTF-8")); builder.addBodyPart(new StringPart("Age", "3", AsyncHttpProviderUtils.DEFAULT_CHARSET)); builder.addBodyPart(new StringPart("Height", "shrimplike", AsyncHttpProviderUtils.DEFAULT_CHARSET)); builder.addBodyPart(new StringPart("Hair", "ridiculous", AsyncHttpProviderUtils.DEFAULT_CHARSET)); builder.addBodyPart(new ByteArrayPart("file4", "bytearray.txt", expectedContents.getBytes("UTF-8") ,"text/plain", "UTF-8")); com.ning.http.client.Request r = builder.build(); Response res = c.executeRequest(r).get(); assertEquals(200, res.getStatusCode()); testSentFile(expected, testFiles, res, gzipped); c.close(); } catch (Exception e) { e.printStackTrace(); fail("Download Exception"); } finally { FileUtils.deleteQuietly(tmpFile); } } /** * Test that the files were sent, based on the response from the servlet * * @param expectedContents * @param sourceFiles * @param r * @param deflate */ private void testSentFile(List expectedContents, List sourceFiles, Response r, List deflate) { String content = null; try { content = r.getResponseBody(); assertNotNull("===>" + content); System.out.println(content); } catch (IOException e) { fail("Unable to obtain content"); } String[] contentArray = content.split("\\|\\|"); // TODO: this fail on win32 assertEquals(2, contentArray.length); String tmpFiles = contentArray[1]; assertNotNull(tmpFiles); assertTrue(tmpFiles.trim().length() > 2); tmpFiles = tmpFiles.substring(1, tmpFiles.length() - 1); String[] responseFiles = tmpFiles.split(","); assertNotNull(responseFiles); assertEquals( sourceFiles.size(), responseFiles.length); System.out.println(Arrays.toString(responseFiles)); //assertTrue("File should exist: " + tmpFile.getAbsolutePath(),tmpFile.exists()); int i = 0; for (File sourceFile : sourceFiles) { FileInputStream instream = null; File tmp = null; try { ByteArrayOutputStream baos = new ByteArrayOutputStream(); byte[] sourceBytes = null; try { instream = new FileInputStream(sourceFile); byte[] buf = new byte[8092]; int len = 0; while ((len = instream.read(buf)) > 0) { baos.write(buf, 0, len); } System.out.println("================"); System.out.println("Length of file: " + baos.toByteArray().length); System.out.println("Contents: " + Arrays.toString(baos.toByteArray())); System.out.println("================"); System.out.flush(); sourceBytes = baos.toByteArray(); } finally { IOUtils.closeQuietly(instream); } tmp = new File(responseFiles[i].trim()); System.out.println("=============================="); System.out.println(tmp.getAbsolutePath()); System.out.println("=============================="); System.out.flush(); assertTrue(tmp.exists()); instream = new FileInputStream(tmp); ByteArrayOutputStream baos2 = new ByteArrayOutputStream(); byte[] buf = new byte[8092]; int len = 0; while ((len = instream.read(buf)) > 0) { baos2.write(buf, 0, len); } IOUtils.closeQuietly(instream); assertEquals(sourceBytes, baos2.toByteArray()); if (!deflate.get(i)) { String helloString = new String(baos2.toByteArray()); assertEquals(expectedContents.get(i), helloString); } else { instream = new FileInputStream(tmp); GZIPInputStream deflater = new GZIPInputStream(instream); ByteArrayOutputStream baos3 = new ByteArrayOutputStream(); byte[] buf3 = new byte[8092]; int len3 = 0; while ((len3 = deflater.read(buf3)) > 0) { baos3.write(buf3, 0, len3); } String helloString = new String(baos3.toByteArray()); assertEquals(expectedContents.get(i), helloString); } } catch (Exception e) { e.printStackTrace(); fail("Download Exception"); } finally { if (tmp != null) FileUtils.deleteQuietly(tmp); IOUtils.closeQuietly(instream); i++; } } } /** * Takes the content that is being passed to it, and streams to a file on disk * * @author dominict */ public static class MockMultipartUploadServlet extends HttpServlet { /** * */ private static final long serialVersionUID = 1L; private int filesProcessed = 0; private int stringsProcessed = 0; public MockMultipartUploadServlet() { } public synchronized void resetFilesProcessed() { filesProcessed = 0; } private synchronized int incrementFilesProcessed() { return ++filesProcessed; } public int getFilesProcessed() { return filesProcessed; } public synchronized void resetStringsProcessed() { stringsProcessed = 0; } private synchronized int incrementStringsProcessed() { return ++stringsProcessed; } public int getStringsProcessed() { return stringsProcessed; } @Override public void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // Check that we have a file upload request boolean isMultipart = ServletFileUpload.isMultipartContent(request); if (isMultipart) { List files = new ArrayList(); ServletFileUpload upload = new ServletFileUpload(); // Parse the request FileItemIterator iter = null; try { iter = upload.getItemIterator(request); while (iter.hasNext()) { FileItemStream item = iter.next(); String name = item.getFieldName(); InputStream stream = null; try { stream = item.openStream(); if (item.isFormField()) { System.out.println("Form field " + name + " with value " + Streams.asString(stream) + " detected."); incrementStringsProcessed(); } else { System.out.println("File field " + name + " with file name " + item.getName() + " detected."); // Process the input stream OutputStream os = null; try { File tmpFile = File.createTempFile(UUID.randomUUID().toString() + "_MockUploadServlet", ".tmp"); tmpFile.deleteOnExit(); os = new FileOutputStream(tmpFile); byte[] buffer = new byte[4096]; int bytesRead; while ((bytesRead = stream.read(buffer)) != -1) { os.write(buffer, 0, bytesRead); } incrementFilesProcessed(); files.add(tmpFile.getAbsolutePath()); } finally { IOUtils.closeQuietly(os); } } } finally { IOUtils.closeQuietly(stream); } } } catch (FileUploadException e) { } Writer w = response.getWriter(); w.write(Integer.toString(getFilesProcessed())); resetFilesProcessed(); resetStringsProcessed(); w.write("||"); w.write(files.toString()); w.close(); } else { Writer w = response.getWriter(); w.write(Integer.toString(getFilesProcessed())); resetFilesProcessed(); resetStringsProcessed(); w.write("||"); w.close(); } } } } async-http-client-1.6.5/src/test/java/com/ning/http/client/async/MultipleHeaderTest.java000066400000000000000000000204711166553056000312650ustar00rootroot00000000000000/* * Copyright (c) 2010-2011 Sonatype, Inc. All rights reserved. * * This program is licensed to you under the Apache License Version 2.0, * and you may not use this file except in compliance with the Apache License Version 2.0. * You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0. * * Unless required by applicable law or agreed to in writing, * software distributed under the Apache License Version 2.0 is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. */ package com.ning.http.client.async; import com.ning.http.client.AsyncHandler; import com.ning.http.client.AsyncHttpClient; import com.ning.http.client.HttpResponseBodyPart; import com.ning.http.client.HttpResponseHeaders; import com.ning.http.client.HttpResponseStatus; import com.ning.http.client.Request; import com.ning.http.client.RequestBuilder; import org.testng.Assert; import org.testng.annotations.AfterClass; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.net.ServerSocket; import java.net.Socket; import java.util.concurrent.Callable; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; /** * @author Hubert Iwaniuk */ public abstract class MultipleHeaderTest extends AbstractBasicTest{ private ExecutorService executorService; private ServerSocket serverSocket; private Future voidFuture; @Test(groups = {"standalone", "default_provider"}) public void testMultipleOtherHeaders() throws IOException, ExecutionException, TimeoutException, InterruptedException { final String[] xffHeaders = new String[]{null, null}; AsyncHttpClient ahc = getAsyncHttpClient(null); Request req = new RequestBuilder("GET").setUrl("http://localhost:" + port1 + "/MultiOther").build(); final CountDownLatch latch = new CountDownLatch(1); ahc.executeRequest(req, new AsyncHandler() { public void onThrowable(Throwable t) { t.printStackTrace(System.out); } public STATE onBodyPartReceived(HttpResponseBodyPart objectHttpResponseBodyPart) throws Exception { return STATE.CONTINUE; } public STATE onStatusReceived(HttpResponseStatus objectHttpResponseStatus) throws Exception { return STATE.CONTINUE; } public STATE onHeadersReceived(HttpResponseHeaders response) throws Exception { int i = 0; for (String header : response.getHeaders().get("X-Forwarded-For")) { xffHeaders[i++] = header; } latch.countDown(); return STATE.CONTINUE; } public Void onCompleted() throws Exception { return null; } }).get(3, TimeUnit.SECONDS); if (!latch.await(2, TimeUnit.SECONDS)) { Assert.fail("Time out"); } Assert.assertNotNull(xffHeaders[0]); Assert.assertNotNull(xffHeaders[1]); try { Assert.assertEquals(xffHeaders[0], "abc"); Assert.assertEquals(xffHeaders[1], "def"); } catch (AssertionError ex) { Assert.assertEquals(xffHeaders[1], "abc"); Assert.assertEquals(xffHeaders[0], "def"); } ahc.close(); } @Test(groups = {"standalone", "default_provider"}) public void testMultipleEntityHeaders() throws IOException, ExecutionException, TimeoutException, InterruptedException { final String[] clHeaders = new String[]{null, null}; AsyncHttpClient ahc = getAsyncHttpClient(null); Request req = new RequestBuilder("GET").setUrl("http://localhost:" + port1 + "/MultiEnt").build(); final CountDownLatch latch = new CountDownLatch(1); ahc.executeRequest(req, new AsyncHandler() { public void onThrowable(Throwable t) { t.printStackTrace(System.out); } public STATE onBodyPartReceived(HttpResponseBodyPart objectHttpResponseBodyPart) throws Exception { return STATE.CONTINUE; } public STATE onStatusReceived(HttpResponseStatus objectHttpResponseStatus) throws Exception { return STATE.CONTINUE; } public STATE onHeadersReceived(HttpResponseHeaders response) throws Exception { try { int i = 0; for (String header : response.getHeaders().get("Content-Length")) { clHeaders[i++] = header; } } finally { latch.countDown(); } return STATE.CONTINUE; } public Void onCompleted() throws Exception { return null; } }).get(3, TimeUnit.SECONDS); if (!latch.await(2, TimeUnit.SECONDS)) { Assert.fail("Time out"); } Assert.assertNotNull(clHeaders[0]); Assert.assertNotNull(clHeaders[1]); // We can predict the order try { Assert.assertEquals(clHeaders[0], "2"); Assert.assertEquals(clHeaders[1], "1"); } catch (Throwable ex) { Assert.assertEquals(clHeaders[0], "1"); Assert.assertEquals(clHeaders[1], "2"); } ahc.close(); } @BeforeClass(alwaysRun = true) public void setUpGlobal() throws Exception { port1 = findFreePort(); serverSocket = new ServerSocket(port1); executorService = Executors.newFixedThreadPool(1); voidFuture = executorService.submit(new Callable() { public Void call() throws Exception { Socket socket; while ((socket = serverSocket.accept()) != null) { InputStream inputStream = socket.getInputStream(); BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream)); String req = reader.readLine().split(" ")[1]; int i = inputStream.available(); long l = inputStream.skip(i); Assert.assertEquals(l, i); socket.shutdownInput(); if (req.endsWith("MultiEnt")) { OutputStreamWriter outputStreamWriter = new OutputStreamWriter(socket.getOutputStream()); outputStreamWriter.append("HTTP/1.0 200 OK\n" + "Connection: close\n" + "Content-Type: text/plain; charset=iso-8859-1\n" + "Content-Length: 2\n" + "Content-Length: 1\n" + "\n0\n"); outputStreamWriter.flush(); socket.shutdownOutput(); } else if (req.endsWith("MultiOther")) { OutputStreamWriter outputStreamWriter = new OutputStreamWriter(socket.getOutputStream()); outputStreamWriter.append("HTTP/1.0 200 OK\n" + "Connection: close\n" + "Content-Type: text/plain; charset=iso-8859-1\n" + "Content-Length: 1\n" + "X-Forwarded-For: abc\n" + "X-Forwarded-For: def\n" + "\n0\n"); outputStreamWriter.flush(); socket.shutdownOutput(); } } return null; } }); } @AfterClass(alwaysRun = true) public void tearDownGlobal() throws Exception { voidFuture.cancel(true); executorService.shutdownNow(); serverSocket.close(); } } async-http-client-1.6.5/src/test/java/com/ning/http/client/async/NoNullResponseTest.java000066400000000000000000000067201166553056000313100ustar00rootroot00000000000000/* * Copyright 2010 Ning, Inc. * * Ning licenses this file to you 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. * */ package com.ning.http.client.async; import com.ning.http.client.AsyncHttpClient; import com.ning.http.client.AsyncHttpClient.BoundRequestBuilder; import com.ning.http.client.AsyncHttpClientConfig; import com.ning.http.client.Response; import org.testng.Assert; import org.testng.annotations.Test; import javax.net.ssl.SSLContext; import javax.net.ssl.TrustManager; import javax.net.ssl.X509TrustManager; import java.security.GeneralSecurityException; import java.security.cert.CertificateException; import java.security.cert.X509Certificate; public abstract class NoNullResponseTest extends AbstractBasicTest { private static final String VERISIGN_HTTPS_URL = "https://www.verisign.com"; @Test(invocationCount = 4, groups = {"online", "default_provider"}) public void multipleSslRequestsWithDelayAndKeepAlive() throws Throwable { final AsyncHttpClient client = create(); final BoundRequestBuilder builder = client.prepareGet(VERISIGN_HTTPS_URL); final Response response1 = builder.execute().get(); Thread.sleep(5000); final Response response2 = builder.execute().get(); if (response2 != null) { System.out.println("Success (2nd response was not null)."); } else { System.out.println("Failed (2nd response was null)."); } Assert.assertNotNull(response1); Assert.assertNotNull(response2); client.close(); } private AsyncHttpClient create() throws GeneralSecurityException { final AsyncHttpClientConfig.Builder configBuilder = new AsyncHttpClientConfig.Builder() .setCompressionEnabled(true) .setFollowRedirects(true) .setSSLContext(getSSLContext()) .setAllowPoolingConnection(true) .setConnectionTimeoutInMs(10000) .setIdleConnectionInPoolTimeoutInMs(60000) .setRequestTimeoutInMs(10000) .setMaximumConnectionsPerHost(-1) .setMaximumConnectionsTotal(-1); return getAsyncHttpClient(configBuilder.build()); } private SSLContext getSSLContext() throws GeneralSecurityException { final SSLContext sslContext = SSLContext.getInstance("TLS"); sslContext.init(null, new TrustManager[]{new MockTrustManager()}, null); return sslContext; } private static class MockTrustManager implements X509TrustManager { public X509Certificate[] getAcceptedIssuers() { throw new UnsupportedOperationException(); } public void checkClientTrusted(final X509Certificate[] chain, final String authType) throws CertificateException { throw new UnsupportedOperationException(); } public void checkServerTrusted(final X509Certificate[] chain, final String authType) throws CertificateException { // Do nothing. } } } async-http-client-1.6.5/src/test/java/com/ning/http/client/async/NonAsciiContentLengthTest.java000066400000000000000000000067421166553056000325660ustar00rootroot00000000000000/* * Copyright (c) 2010-2011 Sonatype, Inc. All rights reserved. * * This program is licensed to you under the Apache License Version 2.0, * and you may not use this file except in compliance with the Apache License Version 2.0. * You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0. * * Unless required by applicable law or agreed to in writing, * software distributed under the Apache License Version 2.0 is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. */ package com.ning.http.client.async; import com.ning.http.client.AsyncHttpClient; import com.ning.http.client.AsyncHttpClient.BoundRequestBuilder; import com.ning.http.client.AsyncHttpClientConfig; import com.ning.http.client.Response; 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.testng.annotations.Test; import javax.servlet.ServletException; import javax.servlet.ServletInputStream; import javax.servlet.ServletOutputStream; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.util.concurrent.ExecutionException; import java.util.concurrent.Future; import static org.testng.Assert.assertEquals; public abstract class NonAsciiContentLengthTest extends AbstractBasicTest { public void setUpServer() throws Exception { server = new Server(); port1 = findFreePort(); Connector listener = new SelectChannelConnector(); listener.setHost("127.0.0.1"); listener.setPort(port1); server.addConnector(listener); server.setHandler(new AbstractHandler() { public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { int MAX_BODY_SIZE = 1024; //Can only handle bodies of up to 1024 bytes. byte[] b = new byte[MAX_BODY_SIZE]; int offset = 0; int numBytesRead; ServletInputStream is = request.getInputStream(); try { while ((numBytesRead = is.read(b, offset, MAX_BODY_SIZE - offset)) != -1) { offset += numBytesRead; } } finally { is.close(); } assertEquals(request.getContentLength(), offset); response.setStatus(200); response.setCharacterEncoding(request.getCharacterEncoding()); response.setContentLength(request.getContentLength()); ServletOutputStream os = response.getOutputStream(); try { os.write(b, 0, offset); } finally { os.close(); } } }); server.start(); } @Test(groups = { "standalone", "default_provider" }) public void testNonAsciiContentLength() throws Exception { setUpServer(); execute("test"); execute("\u4E00"); // Unicode CJK ideograph for one } protected void execute(String body) throws IOException, InterruptedException, ExecutionException { AsyncHttpClient client = getAsyncHttpClient(new AsyncHttpClientConfig.Builder().build()); BoundRequestBuilder r = client.preparePost(getTargetUrl()).setBody(body).setBodyEncoding("UTF-8"); Future f = r.execute(); Response resp = f.get(); assertEquals(resp.getStatusCode(), 200); assertEquals(body, resp.getResponseBody("UTF-8")); client.close(); } } async-http-client-1.6.5/src/test/java/com/ning/http/client/async/ParamEncodingTest.java000066400000000000000000000062161166553056000310710ustar00rootroot00000000000000/* * Copyright 2010 Ning, Inc. * * Ning licenses this file to you 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. */ package com.ning.http.client.async; import com.ning.http.client.AsyncHttpClient; import com.ning.http.client.Response; import org.eclipse.jetty.server.Request; import org.eclipse.jetty.server.handler.AbstractHandler; import org.testng.annotations.Test; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.util.concurrent.ExecutionException; import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertNotNull; public abstract class ParamEncodingTest extends AbstractBasicTest { private class ParamEncoding extends AbstractHandler { public void handle(String s, Request r, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { if ("POST".equalsIgnoreCase(request.getMethod())) { String p = request.getParameter("test"); if (p != null && !p.equals("")) { response.setStatus(HttpServletResponse.SC_OK); response.addHeader("X-Param", p); } else { response.sendError(HttpServletResponse.SC_NOT_ACCEPTABLE); } } else { // this handler is to handle POST request response.sendError(HttpServletResponse.SC_FORBIDDEN); } response.getOutputStream().flush(); response.getOutputStream().close(); } } @Test(groups = {"standalone", "default_provider"}) public void testParameters() throws IOException, ExecutionException, TimeoutException, InterruptedException { String value = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKQLMNOPQRSTUVWXYZ1234567809`~!@#$%^&*()_+-=,.<>/?;:'\"[]{}\\| "; AsyncHttpClient client = getAsyncHttpClient(null); Future f = client .preparePost("http://127.0.0.1:" + port1) .addParameter("test", value) .execute(); Response resp = f.get(10, TimeUnit.SECONDS); assertNotNull(resp); assertEquals(resp.getStatusCode(), HttpServletResponse.SC_OK); assertEquals(resp.getHeader("X-Param"), value.trim()); client.close(); } @Override public AbstractHandler configureHandler() throws Exception { return new ParamEncoding(); } } async-http-client-1.6.5/src/test/java/com/ning/http/client/async/PerRequestRelative302Test.java000066400000000000000000000142051166553056000323770ustar00rootroot00000000000000/* * Copyright 2010 Ning, Inc. * * Ning licenses this file to you 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. */ package com.ning.http.client.async; import com.ning.http.client.AsyncHttpClient; import com.ning.http.client.AsyncHttpClientConfig; import com.ning.http.client.Response; 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.testng.annotations.BeforeClass; import org.testng.annotations.Test; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.net.ConnectException; import java.net.URI; import java.util.Enumeration; import java.util.concurrent.ExecutionException; import java.util.concurrent.atomic.AtomicBoolean; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertNotNull; import static org.testng.Assert.assertTrue; public abstract class PerRequestRelative302Test extends AbstractBasicTest { private final AtomicBoolean isSet = new AtomicBoolean(false); private class Relative302Handler extends AbstractHandler { public void handle(String s, Request r, HttpServletRequest httpRequest, HttpServletResponse httpResponse) throws IOException, ServletException { String param; httpResponse.setContentType("text/html; charset=utf-8"); Enumeration e = httpRequest.getHeaderNames(); while (e.hasMoreElements()) { param = e.nextElement().toString(); if (param.startsWith("X-redirect") && !isSet.getAndSet(true)) { httpResponse.addHeader("Location", httpRequest.getHeader(param)); httpResponse.setStatus(302); httpResponse.getOutputStream().flush(); httpResponse.getOutputStream().close(); return; } } httpResponse.setStatus(200); httpResponse.getOutputStream().flush(); httpResponse.getOutputStream().close(); } } @BeforeClass(alwaysRun = true) public void setUpGlobal() throws Exception { server = new Server(); port1 = findFreePort(); port2 = findFreePort(); Connector listener = new SelectChannelConnector(); listener.setHost("127.0.0.1"); listener.setPort(port1); server.addConnector(listener); server.setHandler(new Relative302Handler()); server.start(); log.info("Local HTTP server started successfully"); } @Test(groups = {"online", "default_provider"}) public void redirected302Test() throws Throwable { isSet.getAndSet(false); AsyncHttpClientConfig cg = new AsyncHttpClientConfig.Builder().build(); AsyncHttpClient c = getAsyncHttpClient(cg); // once Response response = c.prepareGet(getTargetUrl()) .setFollowRedirects(true) .setHeader("X-redirect", "http://www.microsoft.com/") .execute().get(); assertNotNull(response); assertEquals(response.getStatusCode(), 200); String anyMicrosoftPage = "http://www.microsoft.com[^:]*:80"; String baseUrl = getBaseUrl(response.getUri()); c.close(); assertTrue(baseUrl.matches(anyMicrosoftPage), "response does not show redirection to " + anyMicrosoftPage); } private String getBaseUrl(URI uri) { String url = uri.toString(); int port = uri.getPort(); if (port == -1) { port = getPort(uri); url = url.substring(0, url.length() - 1) + ":" + port; } return url.substring(0, url.lastIndexOf(":") + String.valueOf(port).length() + 1); } private static int getPort(URI uri) { int port = uri.getPort(); if (port == -1) port = uri.getScheme().equals("http") ? 80 : 443; return port; } @Test(groups = {"standalone", "default_provider"}) public void redirected302InvalidTest() throws Throwable { isSet.getAndSet(false); AsyncHttpClientConfig cg = new AsyncHttpClientConfig.Builder().build(); AsyncHttpClient c = getAsyncHttpClient(cg); // If the test hit a proxy, no ConnectException will be thrown and instead of 404 will be returned. try { Response response = c.preparePost(getTargetUrl()) .setFollowRedirects(true) .setHeader("X-redirect", String.format("http://127.0.0.1:%d/", port2)) .execute().get(); assertNotNull(response); assertEquals(response.getStatusCode(), 404); } catch (ExecutionException ex) { assertEquals(ex.getCause().getClass(), ConnectException.class); } c.close(); } @Test(groups = {"standalone", "default_provider"}) public void relativeLocationUrl() throws Throwable { isSet.getAndSet(false); AsyncHttpClientConfig cg = new AsyncHttpClientConfig.Builder().build(); AsyncHttpClient c = getAsyncHttpClient(cg); Response response = c.preparePost(getTargetUrl()) .setFollowRedirects(true) .setHeader("X-redirect", "/foo/test") .execute().get(); assertNotNull(response); assertEquals(response.getStatusCode(), 302); assertEquals(response.getUri().toString(), getTargetUrl()); c.close(); } } async-http-client-1.6.5/src/test/java/com/ning/http/client/async/PerRequestTimeoutTest.java000066400000000000000000000175241166553056000320340ustar00rootroot00000000000000/* * Copyright 2010 Ning, Inc. * * Ning licenses this file to you 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. */ package com.ning.http.client.async; import com.ning.http.client.AsyncCompletionHandler; import com.ning.http.client.AsyncHttpClient; import com.ning.http.client.AsyncHttpClientConfig; import com.ning.http.client.HttpResponseBodyPart; import com.ning.http.client.PerRequestConfig; import com.ning.http.client.Response; import org.eclipse.jetty.continuation.Continuation; import org.eclipse.jetty.continuation.ContinuationSupport; import org.eclipse.jetty.server.Request; import org.eclipse.jetty.server.handler.AbstractHandler; import org.testng.annotations.Test; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.util.concurrent.ExecutionException; import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertNotNull; import static org.testng.Assert.assertNull; import static org.testng.Assert.assertTrue; import static org.testng.Assert.fail; /** * Per request timeout configuration test. * * @author Hubert Iwaniuk */ public abstract class PerRequestTimeoutTest extends AbstractBasicTest { private static final String MSG = "Enough is enough."; @Override public AbstractHandler configureHandler() throws Exception { return new SlowHandler(); } private class SlowHandler extends AbstractHandler { public void handle(String target, Request baseRequest, HttpServletRequest request, final HttpServletResponse response) throws IOException, ServletException { response.setStatus(HttpServletResponse.SC_OK); final Continuation continuation = ContinuationSupport.getContinuation(request); continuation.suspend(); new Thread(new Runnable() { public void run() { try { Thread.sleep(1500); response.getOutputStream().print(MSG); response.getOutputStream().flush(); } catch (InterruptedException e) { log.error(e.getMessage(), e); } catch (IOException e) { log.error(e.getMessage(), e); } } }).start(); new Thread(new Runnable() { public void run() { try { Thread.sleep(3000); response.getOutputStream().print(MSG); response.getOutputStream().flush(); continuation.complete(); } catch (InterruptedException e) { log.error(e.getMessage(), e); } catch (IOException e) { log.error(e.getMessage(), e); } } }).start(); baseRequest.setHandled(true); } } @Test(groups = {"standalone", "default_provider"}) public void testRequestTimeout() throws IOException { AsyncHttpClient client = getAsyncHttpClient(null); PerRequestConfig requestConfig = new PerRequestConfig(); requestConfig.setRequestTimeoutInMs(100); Future responseFuture = client.prepareGet(getTargetUrl()).setPerRequestConfig(requestConfig).execute(); try { Response response = responseFuture.get(2000, TimeUnit.MILLISECONDS); assertNull(response); client.close(); } catch (InterruptedException e) { fail("Interrupted.", e); } catch (ExecutionException e) { assertTrue(e.getCause() instanceof TimeoutException); assertEquals(e.getCause().getMessage(), "No response received after 100"); } catch (TimeoutException e) { fail("Timeout.", e); } client.close(); } @Test(groups = {"standalone", "default_provider"}) public void testGlobalDefaultPerRequestInfiniteTimeout() throws IOException { AsyncHttpClient client = getAsyncHttpClient(new AsyncHttpClientConfig.Builder().setRequestTimeoutInMs(100).build()); PerRequestConfig requestConfig = new PerRequestConfig(); requestConfig.setRequestTimeoutInMs(-1); Future responseFuture = client.prepareGet(getTargetUrl()).setPerRequestConfig(requestConfig).execute(); try { Response response = responseFuture.get(); assertNotNull(response); client.close(); } catch (InterruptedException e) { fail("Interrupted.", e); } catch (ExecutionException e) { assertTrue(e.getCause() instanceof TimeoutException); assertEquals(e.getCause().getMessage(), "No response received after 100"); } client.close(); } @Test(groups = {"standalone", "default_provider"}) public void testGlobalRequestTimeout() throws IOException { AsyncHttpClient client = getAsyncHttpClient(new AsyncHttpClientConfig.Builder().setRequestTimeoutInMs(100).build()); Future responseFuture = client.prepareGet(getTargetUrl()).execute(); try { Response response = responseFuture.get(2000, TimeUnit.MILLISECONDS); assertNull(response); client.close(); } catch (InterruptedException e) { fail("Interrupted.", e); } catch (ExecutionException e) { assertTrue(e.getCause() instanceof TimeoutException); assertEquals(e.getCause().getMessage(), "No response received after 100"); } catch (TimeoutException e) { fail("Timeout.", e); } client.close(); } @Test(groups = {"standalone", "default_provider"}) public void testGlobalIdleTimeout() throws IOException { final long times[] = new long[]{-1, -1}; AsyncHttpClient client = getAsyncHttpClient(new AsyncHttpClientConfig.Builder().setIdleConnectionInPoolTimeoutInMs(2000).build()); Future responseFuture = client.prepareGet(getTargetUrl()).execute(new AsyncCompletionHandler() { @Override public Response onCompleted(Response response) throws Exception { return response; } @Override public STATE onBodyPartReceived(HttpResponseBodyPart content) throws Exception { times[0] = System.currentTimeMillis(); return super.onBodyPartReceived(content); } @Override public void onThrowable(Throwable t) { times[1] = System.currentTimeMillis(); super.onThrowable(t); } }); try { Response response = responseFuture.get(); assertNotNull(response); assertEquals(response.getResponseBody(), MSG + MSG); } catch (InterruptedException e) { fail("Interrupted.", e); } catch (ExecutionException e) { log.info(String.format("\n@%dms Last body part received\n@%dms Connection killed\n %dms difference.", times[0], times[1], (times[1] - times[0]))); fail("Timeouted on idle.", e); } client.close(); } } async-http-client-1.6.5/src/test/java/com/ning/http/client/async/PostWithQSTest.java000066400000000000000000000126201166553056000304030ustar00rootroot00000000000000/* * Copyright 2010 Ning, Inc. * * Ning licenses this file to you 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. */ package com.ning.http.client.async; import com.ning.http.client.AsyncCompletionHandlerBase; import com.ning.http.client.AsyncHttpClient; import com.ning.http.client.HttpResponseStatus; import com.ning.http.client.Response; import org.eclipse.jetty.server.Request; import org.eclipse.jetty.server.handler.AbstractHandler; import org.testng.annotations.Test; import javax.servlet.ServletException; import javax.servlet.ServletInputStream; import javax.servlet.ServletOutputStream; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.util.concurrent.ExecutionException; import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertNotNull; /** * Tests POST request with Query String. * * @author Hubert Iwaniuk */ public abstract class PostWithQSTest extends AbstractBasicTest { /** * POST with QS server part. */ private class PostWithQSHandler extends AbstractHandler { public void handle(String s, Request r, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { if ("POST".equalsIgnoreCase(request.getMethod())) { String qs = request.getQueryString(); if (qs != null && !qs.equals("") && request.getContentLength() == 3) { ServletInputStream is = request.getInputStream(); response.setStatus(HttpServletResponse.SC_OK); byte buf[] = new byte[is.available()]; is.readLine(buf, 0, is.available()); ServletOutputStream os = response.getOutputStream(); os.println(new String(buf)); os.flush(); os.close(); } else { response.sendError(HttpServletResponse.SC_NOT_ACCEPTABLE); } } else { // this handler is to handle POST request response.sendError(HttpServletResponse.SC_FORBIDDEN); } } } @Test(groups = {"standalone", "default_provider"}) public void postWithQS() throws IOException, ExecutionException, TimeoutException, InterruptedException { AsyncHttpClient client = getAsyncHttpClient(null); Future f = client.preparePost("http://127.0.0.1:" + port1 + "/?a=b").setBody("abc".getBytes()).execute(); Response resp = f.get(3, TimeUnit.SECONDS); assertNotNull(resp); assertEquals(resp.getStatusCode(), HttpServletResponse.SC_OK); client.close(); } @Test(groups = {"standalone", "default_provider"}) public void postWithNulParamQS() throws IOException, ExecutionException, TimeoutException, InterruptedException { AsyncHttpClient client = getAsyncHttpClient(null); Future f = client.preparePost("http://127.0.0.1:" + port1 + "/?a=").setBody("abc".getBytes()).execute(new AsyncCompletionHandlerBase() { /* @Override */ public STATE onStatusReceived(final HttpResponseStatus status) throws Exception { if (!status.getUrl().toURL().toString().equals("http://127.0.0.1:" + port1 + "/?a")) { throw new IOException(status.getUrl().toURL().toString()); } return super.onStatusReceived(status); } }); Response resp = f.get(3, TimeUnit.SECONDS); assertNotNull(resp); assertEquals(resp.getStatusCode(), HttpServletResponse.SC_OK); client.close(); } @Test(groups = {"standalone", "default_provider"}) public void postWithNulParamsQS() throws IOException, ExecutionException, TimeoutException, InterruptedException { AsyncHttpClient client = getAsyncHttpClient(null); Future f = client.preparePost("http://127.0.0.1:" + port1 + "/?a=b&c&d=e").setBody("abc".getBytes()).execute(new AsyncCompletionHandlerBase() { /* @Override */ public STATE onStatusReceived(final HttpResponseStatus status) throws Exception { if (!status.getUrl().toURL().toString().equals("http://127.0.0.1:" + port1 + "/?a=b&c&d=e")) { throw new IOException("failed to parse the query properly"); } return super.onStatusReceived(status); } }); Response resp = f.get(3, TimeUnit.SECONDS); assertNotNull(resp); assertEquals(resp.getStatusCode(), HttpServletResponse.SC_OK); client.close(); } @Override public AbstractHandler configureHandler() throws Exception { return new PostWithQSHandler(); } } async-http-client-1.6.5/src/test/java/com/ning/http/client/async/ProviderUtil.java000066400000000000000000000034101166553056000301430ustar00rootroot00000000000000/* * Copyright 2010 Ning, Inc. * * Ning licenses this file to you 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. */ package com.ning.http.client.async; import com.ning.http.client.AsyncHttpClient; import com.ning.http.client.AsyncHttpClientConfig; import com.ning.http.client.providers.apache.ApacheAsyncHttpProvider; import com.ning.http.client.providers.jdk.JDKAsyncHttpProvider; public class ProviderUtil { public static AsyncHttpClient nettyProvider(AsyncHttpClientConfig config) { if (config == null) { return new AsyncHttpClient(); } else { return new AsyncHttpClient(config); } } public static AsyncHttpClient apacheProvider(AsyncHttpClientConfig config) { if (config == null) { return new AsyncHttpClient(new ApacheAsyncHttpProvider(new AsyncHttpClientConfig.Builder().build())); } else { return new AsyncHttpClient(new ApacheAsyncHttpProvider(config)); } } public static AsyncHttpClient jdkProvider(AsyncHttpClientConfig config) { if (config == null) { return new AsyncHttpClient(new JDKAsyncHttpProvider(new AsyncHttpClientConfig.Builder().build())); } else { return new AsyncHttpClient(new JDKAsyncHttpProvider(config)); } } } async-http-client-1.6.5/src/test/java/com/ning/http/client/async/ProxyTest.java000066400000000000000000000233531166553056000275040ustar00rootroot00000000000000/* * Copyright 2010 Ning, Inc. * * Ning licenses this file to you 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. */ package com.ning.http.client.async; import static org.testng.Assert.*; import com.ning.http.client.AsyncHttpClient; import com.ning.http.client.AsyncHttpClientConfig; import com.ning.http.client.ProxyServer; import com.ning.http.client.Response; import com.ning.http.client.ProxyServer.Protocol; import com.ning.http.util.ProxyUtils; import java.io.IOException; import java.net.ConnectException; import java.util.Properties; import java.util.concurrent.ExecutionException; import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; 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.handler.AbstractHandler; import org.testng.annotations.Test; /** * Proxy usage tests. * * @author Hubert Iwaniuk */ public abstract class ProxyTest extends AbstractBasicTest { private class ProxyHandler extends AbstractHandler { public void handle(String s, Request r, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { if ("GET".equalsIgnoreCase(request.getMethod())) { response.addHeader("target", r.getUri().toString()); response.setStatus(HttpServletResponse.SC_OK); } else { // this handler is to handle POST request response.sendError(HttpServletResponse.SC_FORBIDDEN); } r.setHandled(true); } } @Override public AbstractHandler configureHandler() throws Exception { return new ProxyHandler(); } @Test(groups = {"standalone", "default_provider"}) public void testRequestLevelProxy() throws IOException, ExecutionException, TimeoutException, InterruptedException { AsyncHttpClient client = getAsyncHttpClient(null); String target = "http://127.0.0.1:1234/"; Future f = client .prepareGet(target) .setProxyServer(new ProxyServer("127.0.0.1", port1)) .execute(); Response resp = f.get(3, TimeUnit.SECONDS); assertNotNull(resp); assertEquals(resp.getStatusCode(), HttpServletResponse.SC_OK); assertEquals(resp.getHeader("target"), target); client.close(); } @Test(groups = {"standalone", "default_provider"}) public void testGlobalProxy() throws IOException, ExecutionException, TimeoutException, InterruptedException { AsyncHttpClientConfig cfg = new AsyncHttpClientConfig.Builder().setProxyServer(new ProxyServer("127.0.0.1", port1)).build(); AsyncHttpClient client = getAsyncHttpClient(cfg); String target = "http://127.0.0.1:1234/"; Future f = client .prepareGet(target) .execute(); Response resp = f.get(3, TimeUnit.SECONDS); assertNotNull(resp); assertEquals(resp.getStatusCode(), HttpServletResponse.SC_OK); assertEquals(resp.getHeader("target"), target); client.close(); } @Test(groups = {"standalone", "default_provider"}) public void testBothProxies() throws IOException, ExecutionException, TimeoutException, InterruptedException { AsyncHttpClientConfig cfg = new AsyncHttpClientConfig.Builder().setProxyServer(new ProxyServer("127.0.0.1", port1 - 1)).build(); AsyncHttpClient client = getAsyncHttpClient(cfg); String target = "http://127.0.0.1:1234/"; Future f = client .prepareGet(target) .setProxyServer(new ProxyServer("127.0.0.1", port1)) .execute(); Response resp = f.get(3, TimeUnit.SECONDS); assertNotNull(resp); assertEquals(resp.getStatusCode(), HttpServletResponse.SC_OK); assertEquals(resp.getHeader("target"), target); client.close(); } @Test(groups = {"standalone", "default_provider"}) public void testNonProxyHosts() throws IOException, ExecutionException, TimeoutException, InterruptedException { AsyncHttpClientConfig cfg = new AsyncHttpClientConfig.Builder().setProxyServer(new ProxyServer("127.0.0.1", port1 - 1)).build(); AsyncHttpClient client = getAsyncHttpClient(cfg); try { String target = "http://127.0.0.1:1234/"; client.prepareGet(target) .setProxyServer(new ProxyServer("127.0.0.1", port1).addNonProxyHost("127.0.0.1")) .execute().get(); assertFalse(true); } catch (Throwable e) { assertNotNull(e.getCause()); assertEquals(e.getCause().getClass(), ConnectException.class); } client.close(); } @Test(groups = { "standalone", "default_provider" }) public void testProxyProperties() throws IOException, ExecutionException, TimeoutException, InterruptedException { Properties originalProps = System.getProperties(); try { Properties props = new Properties(); props.putAll(originalProps); System.setProperties(props); System.setProperty("http.proxyHost", "127.0.0.1"); System.setProperty("http.proxyPort", String.valueOf(port1)); System.setProperty("http.nonProxyHosts", "localhost"); AsyncHttpClientConfig cfg = new AsyncHttpClientConfig.Builder().setUseProxyProperties(true).build(); AsyncHttpClient client = getAsyncHttpClient(cfg); String target = "http://127.0.0.1:1234/"; Future f = client.prepareGet(target).execute(); Response resp = f.get(3, TimeUnit.SECONDS); assertNotNull(resp); assertEquals(resp.getStatusCode(), HttpServletResponse.SC_OK); assertEquals(resp.getHeader("target"), target); target = "http://localhost:1234/"; f = client.prepareGet(target).execute(); try { resp = f.get(3, TimeUnit.SECONDS); fail("should not be able to connect"); } catch (ExecutionException e) { // ok, no proxy used } client.close(); } finally { System.setProperties(originalProps); } } @Test(groups = { "standalone", "default_provider" }) public void testIgnoreProxyPropertiesByDefault() throws IOException, ExecutionException, TimeoutException, InterruptedException { Properties originalProps = System.getProperties(); try { Properties props = new Properties(); props.putAll(originalProps); System.setProperties(props); System.setProperty("http.proxyHost", "127.0.0.1"); System.setProperty("http.proxyPort", String.valueOf(port1)); System.setProperty("http.nonProxyHosts", "localhost"); AsyncHttpClientConfig cfg = new AsyncHttpClientConfig.Builder().build(); AsyncHttpClient client = getAsyncHttpClient(cfg); String target = "http://127.0.0.1:1234/"; Future f = client.prepareGet(target).execute(); try { f.get(3, TimeUnit.SECONDS); fail("should not be able to connect"); } catch (ExecutionException e) { // ok, no proxy used } client.close(); } finally { System.setProperties(originalProps); } } @Test(groups = { "standalone", "default_provider" }) public void testProxyActivationProperty() throws IOException, ExecutionException, TimeoutException, InterruptedException { Properties originalProps = System.getProperties(); try { Properties props = new Properties(); props.putAll(originalProps); System.setProperties(props); System.setProperty("http.proxyHost", "127.0.0.1"); System.setProperty("http.proxyPort", String.valueOf(port1)); System.setProperty("http.nonProxyHosts", "localhost"); System.setProperty("com.ning.http.client.AsyncHttpClientConfig.useProxyProperties", "true"); AsyncHttpClientConfig cfg = new AsyncHttpClientConfig.Builder().build(); AsyncHttpClient client = getAsyncHttpClient(cfg); String target = "http://127.0.0.1:1234/"; Future f = client.prepareGet(target).execute(); Response resp = f.get(3, TimeUnit.SECONDS); assertNotNull(resp); assertEquals(resp.getStatusCode(), HttpServletResponse.SC_OK); assertEquals(resp.getHeader("target"), target); target = "http://localhost:1234/"; f = client.prepareGet(target).execute(); try { resp = f.get(3, TimeUnit.SECONDS); fail("should not be able to connect"); } catch (ExecutionException e) { // ok, no proxy used } client.close(); } finally { System.setProperties(originalProps); } } } async-http-client-1.6.5/src/test/java/com/ning/http/client/async/ProxyyTunnellingTest.java000066400000000000000000000143361166553056000317360ustar00rootroot00000000000000/* * Copyright (c) 2010-2011 Sonatype, Inc. All rights reserved. * * This program is licensed to you under the Apache License Version 2.0, * and you may not use this file except in compliance with the Apache License Version 2.0. * You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0. * * Unless required by applicable law or agreed to in writing, * software distributed under the Apache License Version 2.0 is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. */ package com.ning.http.client.async; import com.ning.http.client.AsyncCompletionHandlerBase; import com.ning.http.client.AsyncHttpClient; import com.ning.http.client.AsyncHttpClientConfig; import com.ning.http.client.ProxyServer; import com.ning.http.client.RequestBuilder; import com.ning.http.client.Response; import com.ning.http.client.SimpleAsyncHttpClient; import org.eclipse.jetty.server.Connector; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.handler.AbstractHandler; import org.eclipse.jetty.server.handler.ProxyHandler; import org.eclipse.jetty.server.nio.SelectChannelConnector; import org.eclipse.jetty.server.ssl.SslSocketConnector; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; import java.io.File; import java.io.IOException; import java.net.URL; import java.util.concurrent.ExecutionException; import java.util.concurrent.Future; import java.util.concurrent.TimeoutException; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertNotNull; /** * Proxy usage tests. */ public abstract class ProxyyTunnellingTest extends AbstractBasicTest { private Server server2; public AbstractHandler configureHandler() throws Exception { ProxyHandler proxy = new ProxyHandler(); return proxy; } @BeforeClass(alwaysRun = true) public void setUpGlobal() throws Exception { server = new Server(); server2 = new Server(); port1 = findFreePort(); port2 = findFreePort(); Connector listener = new SelectChannelConnector(); listener.setHost("127.0.0.1"); listener.setPort(port1); server.addConnector(listener); SslSocketConnector connector = new SslSocketConnector(); connector.setHost("127.0.0.1"); connector.setPort(port2); ClassLoader cl = getClass().getClassLoader(); URL keystoreUrl = cl.getResource("ssltest-keystore.jks"); String keyStoreFile = new File(keystoreUrl.toURI()).getAbsolutePath(); connector.setKeystore(keyStoreFile); connector.setKeyPassword("changeit"); connector.setKeystoreType("JKS"); server2.addConnector(connector); server.setHandler(configureHandler()); server.start(); server2.setHandler(new EchoHandler()); server2.start(); log.info("Local HTTP server started successfully"); } @Test(groups = {"online", "default_provider"}) public void testRequestProxy() throws IOException, InterruptedException, ExecutionException, TimeoutException { AsyncHttpClientConfig.Builder b = new AsyncHttpClientConfig.Builder(); b.setFollowRedirects(true); ProxyServer ps = new ProxyServer(ProxyServer.Protocol.HTTPS, "127.0.0.1", port1); AsyncHttpClientConfig config = b.build(); AsyncHttpClient asyncHttpClient = getAsyncHttpClient(config); RequestBuilder rb = new RequestBuilder("GET").setProxyServer(ps).setUrl(getTargetUrl2()); Future responseFuture = asyncHttpClient.executeRequest(rb.build(), new AsyncCompletionHandlerBase() { public void onThrowable(Throwable t) { t.printStackTrace(); log.debug(t.getMessage(), t); } @Override public Response onCompleted(Response response) throws Exception { return response; } }); Response r = responseFuture.get(); assertEquals(r.getStatusCode(), 200); assertEquals(r.getHeader("server"), "Jetty(7.1.4.v20100610)"); asyncHttpClient.close(); } @Test(groups = {"online", "default_provider"}) public void testConfigProxy() throws IOException, InterruptedException, ExecutionException, TimeoutException { AsyncHttpClientConfig.Builder b = new AsyncHttpClientConfig.Builder(); b.setFollowRedirects(true); ProxyServer ps = new ProxyServer(ProxyServer.Protocol.HTTPS, "127.0.0.1", port1); b.setProxyServer(ps); AsyncHttpClientConfig config = b.build(); AsyncHttpClient asyncHttpClient = getAsyncHttpClient(config); RequestBuilder rb = new RequestBuilder("GET").setUrl(getTargetUrl2()); Future responseFuture = asyncHttpClient.executeRequest(rb.build(), new AsyncCompletionHandlerBase() { public void onThrowable(Throwable t) { t.printStackTrace(); log.debug(t.getMessage(), t); } @Override public Response onCompleted(Response response) throws Exception { return response; } }); Response r = responseFuture.get(); assertEquals(r.getStatusCode(), 200); assertEquals(r.getHeader("server"), "Jetty(7.1.4.v20100610)"); asyncHttpClient.close(); } @Test(groups = {"online", "default_provider"}) public void testSimpleAHCConfigProxy() throws IOException, InterruptedException, ExecutionException, TimeoutException { SimpleAsyncHttpClient client = new SimpleAsyncHttpClient.Builder() .setProxyProtocol(ProxyServer.Protocol.HTTPS) .setProxyHost("127.0.0.1") .setProxyPort(port1) .setFollowRedirects(true) .setUrl(getTargetUrl2()) .setHeader("Content-Type", "text/html").build(); StringBuffer s = new StringBuffer(); Response r = client.get().get(); assertEquals(r.getStatusCode(), 200); assertEquals(r.getHeader("server"), "Jetty(7.1.4.v20100610)"); client.close(); } } async-http-client-1.6.5/src/test/java/com/ning/http/client/async/PutLargeFileTest.java000066400000000000000000000116661166553056000307120ustar00rootroot00000000000000/* * Copyright (c) 2010-2011 Sonatype, Inc. All rights reserved. * * This program is licensed to you under the Apache License Version 2.0, * and you may not use this file except in compliance with the Apache License Version 2.0. * You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0. * * Unless required by applicable law or agreed to in writing, * software distributed under the Apache License Version 2.0 is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. */ package com.ning.http.client.async; import com.ning.http.client.AsyncHttpClient; import com.ning.http.client.AsyncHttpClient.BoundRequestBuilder; import com.ning.http.client.AsyncHttpClientConfig; import com.ning.http.client.Response; import org.eclipse.jetty.server.Request; import org.eclipse.jetty.server.handler.AbstractHandler; import org.testng.Assert; import org.testng.annotations.AfterMethod; import org.testng.annotations.Test; import javax.servlet.ServletException; import javax.servlet.ServletInputStream; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.util.UUID; /** * @author Benjamin Hanzelmann */ public abstract class PutLargeFileTest extends AbstractBasicTest { private File largeFile; @Test(groups = {"standalone", "default_provider"}, enabled = true) public void testPutLargeFile() throws Exception { byte[] bytes = "RatherLargeFileRatherLargeFileRatherLargeFileRatherLargeFile".getBytes("UTF-16"); long repeats = (1024 * 1024 * 100 / bytes.length) + 1; largeFile = createTempFile(bytes, (int) repeats); int timeout = (int) (largeFile.length() / 1000); AsyncHttpClientConfig config = new AsyncHttpClientConfig.Builder().setConnectionTimeoutInMs(timeout).build(); AsyncHttpClient client = getAsyncHttpClient(config); BoundRequestBuilder rb = client.preparePut(getTargetUrl()); rb.setBody(largeFile); Response response = rb.execute().get(); Assert.assertEquals(200, response.getStatusCode()); client.close(); } @Test(groups = {"standalone", "default_provider"}) public void testPutSmallFile() throws Exception { byte[] bytes = "RatherLargeFileRatherLargeFileRatherLargeFileRatherLargeFile".getBytes("UTF-16"); long repeats = (1024 / bytes.length) + 1; int timeout = (5000); largeFile = createTempFile(bytes, (int) repeats); AsyncHttpClientConfig config = new AsyncHttpClientConfig.Builder().build(); AsyncHttpClient client = getAsyncHttpClient(config); BoundRequestBuilder rb = client.preparePut(getTargetUrl()); rb.setBody(largeFile); Response response = rb.execute().get(); Assert.assertEquals(200, response.getStatusCode()); client.close(); } @AfterMethod public void after() { largeFile.delete(); } @Override public AbstractHandler configureHandler() throws Exception { return new AbstractHandler() { public void handle(String arg0, Request arg1, HttpServletRequest req, HttpServletResponse resp) throws IOException, ServletException { ServletInputStream in = req.getInputStream(); byte[] b = new byte[8092]; int count = -1; int total = 0; while ((count = in.read(b)) != -1) { total += count; } System.err.println("consumed " + total + " bytes."); resp.setStatus(200); resp.getOutputStream().flush(); resp.getOutputStream().close(); arg1.setHandled(true); } }; } private static final File TMP = new File(System.getProperty("java.io.tmpdir"), "ahc-tests-" + UUID.randomUUID().toString().substring(0, 8)); public static File createTempFile(byte[] pattern, int repeat) throws IOException { TMP.mkdirs(); TMP.deleteOnExit(); File tmpFile = File.createTempFile("tmpfile-", ".data", TMP); tmpFile.deleteOnExit(); write(pattern, repeat, tmpFile); return tmpFile; } public static void write(byte[] pattern, int repeat, File file) throws IOException { file.deleteOnExit(); file.getParentFile().mkdirs(); FileOutputStream out = null; try { out = new FileOutputStream(file); for (int i = 0; i < repeat; i++) { out.write(pattern); } } finally { if (out != null) { out.close(); } } } } async-http-client-1.6.5/src/test/java/com/ning/http/client/async/QueryParametersTest.java000066400000000000000000000121651166553056000315130ustar00rootroot00000000000000/* * Copyright 2010 Ning, Inc. * * Ning licenses this file to you 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. */ package com.ning.http.client.async; import com.ning.http.client.AsyncHttpClient; import com.ning.http.client.Response; import org.eclipse.jetty.server.Request; import org.eclipse.jetty.server.handler.AbstractHandler; import org.slf4j.LoggerFactory; import org.testng.annotations.Test; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.net.URLDecoder; import java.net.URLEncoder; import java.util.concurrent.ExecutionException; import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertNotNull; /** * Testing query parameters support. * * @author Hubert Iwaniuk */ public abstract class QueryParametersTest extends AbstractBasicTest { private class QueryStringHandler extends AbstractHandler { public void handle(String s, Request r, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { if ("GET".equalsIgnoreCase(request.getMethod())) { String qs = request.getQueryString(); if (qs != null && !qs.equals("")) { for (String qnv : qs.split("&")) { String nv[] = qnv.split("="); response.addHeader(nv[0], nv[1]); } response.setStatus(HttpServletResponse.SC_OK); } else { response.sendError(HttpServletResponse.SC_NOT_ACCEPTABLE); } } else { // this handler is to handle POST request response.sendError(HttpServletResponse.SC_FORBIDDEN); } r.setHandled(true); } } @Override public AbstractHandler configureHandler() throws Exception { return new QueryStringHandler(); } @Test(groups = {"standalone", "default_provider"}) public void testQueryParameters() throws IOException, ExecutionException, TimeoutException, InterruptedException { AsyncHttpClient client = getAsyncHttpClient(null); Future f = client .prepareGet("http://127.0.0.1:" + port1) .addQueryParameter("a", "1") .addQueryParameter("b", "2") .execute(); Response resp = f.get(3, TimeUnit.SECONDS); assertNotNull(resp); assertEquals(resp.getStatusCode(), HttpServletResponse.SC_OK); assertEquals(resp.getHeader("a"), "1"); assertEquals(resp.getHeader("b"), "2"); client.close(); } @Test(groups = {"standalone", "default_provider"}) public void testUrlRequestParametersEncoding() throws IOException, ExecutionException, InterruptedException { String URL = getTargetUrl() + "?q="; String REQUEST_PARAM = "github github \ngithub"; AsyncHttpClient client = getAsyncHttpClient(null); String requestUrl2 = URL + URLEncoder.encode(REQUEST_PARAM, "UTF-8"); LoggerFactory.getLogger(QueryParametersTest.class).info("Executing request [{}] ...", requestUrl2); Response response = client.prepareGet(requestUrl2).execute().get(); String s = URLDecoder.decode(response.getHeader("q"), "UTF-8"); assertEquals(s, REQUEST_PARAM); client.close(); } @Test(groups = {"standalone", "default_provider"}) public void urlWithColonTest_Netty() throws Throwable { AsyncHttpClient c = getAsyncHttpClient(null); String query = "test:colon:"; Response response = c.prepareGet(String.format("http://127.0.0.1:%d/foo/test/colon?q=%s", port1, query)) .setHeader("Content-Type", "text/html") .execute().get(TIMEOUT, TimeUnit.SECONDS); assertEquals(response.getHeader("q"), URLEncoder.encode(query, "UTF-8")); c.close(); } @Test(groups = {"standalone", "default_provider"}) public void urlWithColonTest_JDK() throws Throwable { AsyncHttpClient c = getAsyncHttpClient(null); String query = "test:colon:"; Response response = c.prepareGet(String.format("http://127.0.0.1:%d/foo/test/colon?q=%s", port1, query)) .setHeader("Content-Type", "text/html") .execute().get(TIMEOUT, TimeUnit.SECONDS); assertEquals(response.getHeader("q"), URLEncoder.encode(query, "UTF-8")); c.close(); } } async-http-client-1.6.5/src/test/java/com/ning/http/client/async/RC10KTest.java000066400000000000000000000127431166553056000271440ustar00rootroot00000000000000/* * Copyright 2010 Ning, Inc. * * Ning licenses this file to you 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. */ package com.ning.http.client.async; import com.ning.http.client.AsyncHandler; import com.ning.http.client.AsyncHttpClient; import com.ning.http.client.AsyncHttpClientConfig; import com.ning.http.client.HttpResponseBodyPart; import com.ning.http.client.HttpResponseHeaders; import com.ning.http.client.HttpResponseStatus; 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.testng.annotations.AfterClass; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.util.concurrent.ExecutionException; import java.util.concurrent.Future; import java.util.concurrent.TimeoutException; import java.util.concurrent.atomic.AtomicInteger; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertNotNull; /** * Reverse C10K Problem test. * * @author Hubert Iwaniuk */ public abstract class RC10KTest extends AbstractBasicTest { private static final int C10K = 1000; private static final String ARG_HEADER = "Arg"; private static final int SRV_COUNT = 10; protected List servers = new ArrayList(SRV_COUNT); private int[] ports; @BeforeClass(alwaysRun = true) public void setUpGlobal() throws Exception { ports = new int[SRV_COUNT]; for (int i = 0; i < SRV_COUNT; i++) { ports[i] = createServer(); } log.info("Local HTTP servers started successfully"); } @AfterClass(alwaysRun = true) public void tearDownGlobal() throws Exception { for (Server srv : servers) { srv.stop(); } } private int createServer() throws Exception { Server srv = new Server(); Connector listener = new SelectChannelConnector(); listener.setHost("127.0.0.1"); int port = findFreePort(); listener.setPort(port); srv.addConnector(listener); srv.setHandler(configureHandler()); srv.start(); servers.add(srv); return port; } @Override public AbstractHandler configureHandler() throws Exception { return new AbstractHandler() { public void handle(String s, Request r, HttpServletRequest req, HttpServletResponse resp) throws IOException, ServletException { resp.setContentType("text/pain"); String arg = s.substring(1); resp.setHeader(ARG_HEADER, arg); resp.setStatus(200); resp.getOutputStream().print(arg); resp.getOutputStream().flush(); resp.getOutputStream().close(); } }; } @Test(timeOut = 10 * 60 * 1000, groups = "scalability") public void rc10kProblem() throws IOException, ExecutionException, TimeoutException, InterruptedException { AsyncHttpClient ahc = getAsyncHttpClient( new AsyncHttpClientConfig.Builder().setMaximumConnectionsPerHost(C10K).setAllowPoolingConnection(true).build()); List> resps = new ArrayList>(C10K); int i = 0; while (i < C10K) { resps.add(ahc.prepareGet(String.format("http://127.0.0.1:%d/%d", ports[i % SRV_COUNT], i)).execute(new MyAsyncHandler(i++))); } i = 0; for (Future fResp : resps) { Integer resp = fResp.get(); assertNotNull(resp); assertEquals(resp.intValue(), i++); } ahc.close(); } private class MyAsyncHandler implements AsyncHandler { private String arg; private AtomicInteger result = new AtomicInteger(-1); public MyAsyncHandler(int i) { arg = String.format("%d", i); } public void onThrowable(Throwable t) { log.warn("onThrowable called.", t); } public STATE onBodyPartReceived(HttpResponseBodyPart event) throws Exception { String s = new String(event.getBodyPartBytes()); result.compareAndSet(-1, new Integer(s.trim().equals("") ? "-1" : s)); return STATE.CONTINUE; } public STATE onStatusReceived(HttpResponseStatus event) throws Exception { assertEquals(event.getStatusCode(), 200); return STATE.CONTINUE; } public STATE onHeadersReceived(HttpResponseHeaders event) throws Exception { assertEquals(event.getHeaders().getJoinedValue(ARG_HEADER, ", "), arg); return STATE.CONTINUE; } public Integer onCompleted() throws Exception { return result.get(); } } } async-http-client-1.6.5/src/test/java/com/ning/http/client/async/RedirectConnectionUsageTest.java000066400000000000000000000143571166553056000331350ustar00rootroot00000000000000/* * Copyright 2010 Ning, Inc. * * Ning licenses this file to you 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. */ package com.ning.http.client.async; import com.ning.http.client.AsyncHttpClient; import com.ning.http.client.AsyncHttpClientConfig; import com.ning.http.client.ListenableFuture; import com.ning.http.client.RequestBuilder; import com.ning.http.client.Response; import com.ning.http.client.providers.netty.NettyAsyncHttpProviderConfig; import org.eclipse.jetty.server.Connector; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.nio.SelectChannelConnector; import org.eclipse.jetty.servlet.ServletContextHandler; import org.eclipse.jetty.servlet.ServletHolder; import org.testng.annotations.AfterClass; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.OutputStream; import java.util.Date; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertNotNull; import static org.testng.FileAssert.fail; /** * Test for multithreaded url fetcher calls that use two separate * sets of ssl certificates. This then tests that the certificate * settings do not clash (override each other), resulting in the * peer not authenticated exception * * @author dominict */ public abstract class RedirectConnectionUsageTest extends AbstractBasicTest{ private String BASE_URL; private String servletEndpointRedirectUrl; @BeforeClass public void setUp() throws Exception { server = new Server(); port1 = findFreePort(); Connector listener = new SelectChannelConnector(); listener.setHost("localhost"); listener.setPort(port1); server.addConnector(listener); ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS); context.setContextPath("/"); server.setHandler(context); context.addServlet(new ServletHolder(new MockRedirectHttpServlet()), "/redirect/*"); context.addServlet(new ServletHolder(new MockFullResponseHttpServlet()), "/*"); server.start(); BASE_URL = "http://localhost" + ":" + port1; servletEndpointRedirectUrl = BASE_URL + "/redirect"; } @AfterClass public void tearDown() { try { if (server != null) { server.stop(); } } catch (Exception e) { System.err.print("Error stopping servlet tester"); e.printStackTrace(); } } /** * Tests that after a redirect the final url in the response * reflect the redirect */ @Test public void testGetRedirectFinalUrl() { AsyncHttpClient c = null; try { AsyncHttpClientConfig.Builder bc = new AsyncHttpClientConfig.Builder(); bc.setAllowPoolingConnection(true); bc.setMaximumConnectionsPerHost(1); bc.setMaximumConnectionsTotal(1); bc.setConnectionTimeoutInMs(1000); bc.setRequestTimeoutInMs(1000); bc.setFollowRedirects(true); NettyAsyncHttpProviderConfig config = new NettyAsyncHttpProviderConfig(); if (System.getProperty("blockingio") != null) config.addProperty(NettyAsyncHttpProviderConfig.USE_BLOCKING_IO, "true"); //config.addProperty(NettyAsyncHttpProviderConfig.REUSE_ADDRESS, "true"); bc.setAsyncHttpClientProviderConfig(config); c = getAsyncHttpClient(bc.build()); RequestBuilder builder = new RequestBuilder("GET"); builder.setUrl(servletEndpointRedirectUrl); com.ning.http.client.Request r = builder.build(); try { ListenableFuture response = c.executeRequest(r); Response res = null; res = response.get(); assertNotNull(res.getResponseBody()); assertEquals(BASE_URL + "/overthere", BASE_URL + "/overthere", res.getUri().toString()); } catch (Exception e) { System.err.print("============"); e.printStackTrace(); System.err.print("============"); System.err.flush(); fail("Should not get here, The request threw an exception"); } } finally { // can hang here if (c != null) c.close(); } } class MockRedirectHttpServlet extends HttpServlet { public void service(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException { res.sendRedirect("/overthere"); } } class MockFullResponseHttpServlet extends HttpServlet { private static final String contentType = "text/xml"; private static final String xml = ""; public void service(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException { String xmlToReturn = String.format(xml, new Object[]{new Date().toString()}); res.setStatus(200, "Complete, XML Being Returned"); res.addHeader("Content-Type", contentType); res.addHeader("X-Method", req.getMethod()); res.addHeader("MultiValue", "1"); res.addHeader("MultiValue", "2"); res.addHeader("MultiValue", "3"); OutputStream os = res.getOutputStream(); byte[] retVal = xmlToReturn.getBytes(); res.setContentLength(retVal.length); os.write(retVal); os.close(); } } } async-http-client-1.6.5/src/test/java/com/ning/http/client/async/Relative302Test.java000066400000000000000000000162471166553056000303670ustar00rootroot00000000000000/* * Copyright 2010 Ning, Inc. * * Ning licenses this file to you 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. */ package com.ning.http.client.async; import com.ning.http.client.AsyncHttpClient; import com.ning.http.client.AsyncHttpClientConfig; import com.ning.http.client.Response; 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.testng.annotations.BeforeClass; import org.testng.annotations.Test; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.net.ConnectException; import java.net.URI; import java.util.Enumeration; import java.util.concurrent.ExecutionException; import java.util.concurrent.atomic.AtomicBoolean; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertNotNull; import static org.testng.Assert.assertTrue; public abstract class Relative302Test extends AbstractBasicTest { private final AtomicBoolean isSet = new AtomicBoolean(false); private class Relative302Handler extends AbstractHandler { public void handle(String s, Request r, HttpServletRequest httpRequest, HttpServletResponse httpResponse) throws IOException, ServletException { String param; httpResponse.setContentType("text/html; charset=utf-8"); Enumeration e = httpRequest.getHeaderNames(); while (e.hasMoreElements()) { param = e.nextElement().toString(); if (param.startsWith("X-redirect") && !isSet.getAndSet(true)) { httpResponse.addHeader("Location", httpRequest.getHeader(param)); httpResponse.setStatus(302); httpResponse.getOutputStream().flush(); httpResponse.getOutputStream().close(); return; } } httpResponse.setStatus(200); httpResponse.getOutputStream().flush(); httpResponse.getOutputStream().close(); } } @BeforeClass(alwaysRun = true) public void setUpGlobal() throws Exception { server = new Server(); port1 = findFreePort(); port2 = findFreePort(); Connector listener = new SelectChannelConnector(); listener.setHost("127.0.0.1"); listener.setPort(port1); server.addConnector(listener); server.setHandler(new Relative302Handler()); server.start(); log.info("Local HTTP server started successfully"); } @Test(groups = {"online", "default_provider"}) public void redirected302Test() throws Throwable { isSet.getAndSet(false); AsyncHttpClientConfig cg = new AsyncHttpClientConfig.Builder().setFollowRedirects(true).build(); AsyncHttpClient c = getAsyncHttpClient(cg); // once Response response = c.prepareGet(getTargetUrl()) .setHeader("X-redirect", "http://www.google.com/") .execute().get(); assertNotNull(response); assertEquals(response.getStatusCode(), 200); String anyGoogleSubdomain = "http://www.google.[a-z]{1,}:80"; String baseUrl = getBaseUrl( response.getUri() ); assertTrue(baseUrl.matches( anyGoogleSubdomain ), "response does not show redirection to " + anyGoogleSubdomain); c.close(); } private String getBaseUrl(URI uri) { String url = uri.toString(); int port = uri.getPort(); if (port == -1) { port = getPort(uri); url = url.substring(0, url.length() - 1) + ":" + port; } return url.substring(0, url.lastIndexOf(":") + String.valueOf(port).length() + 1); } private static int getPort(URI uri) { int port = uri.getPort(); if (port == -1) port = uri.getScheme().equals("http") ? 80 : 443; return port; } @Test(groups = {"standalone", "default_provider"}) public void redirected302InvalidTest() throws Throwable { isSet.getAndSet(false); AsyncHttpClientConfig cg = new AsyncHttpClientConfig.Builder().setFollowRedirects(true).build(); AsyncHttpClient c = getAsyncHttpClient(cg); // If the test hit a proxy, no ConnectException will be thrown and instead of 404 will be returned. try { Response response = c.prepareGet(getTargetUrl()) .setHeader("X-redirect", String.format("http://127.0.0.1:%d/", port2)) .execute().get(); assertNotNull(response); assertEquals(response.getStatusCode(), 404); } catch (ExecutionException ex) { assertEquals(ex.getCause().getClass(), ConnectException.class); } c.close(); } @Test(groups = {"standalone", "default_provider"}) public void absolutePathRedirectTest() throws Throwable { isSet.getAndSet(false); AsyncHttpClientConfig cg = new AsyncHttpClientConfig.Builder().setFollowRedirects(true).build(); AsyncHttpClient c = getAsyncHttpClient(cg); String redirectTarget = "/bar/test"; String destinationUrl = new URI(getTargetUrl()).resolve(redirectTarget).toString(); Response response = c.prepareGet(getTargetUrl()) .setHeader("X-redirect", redirectTarget) .execute().get(); assertNotNull(response); assertEquals(response.getStatusCode(), 200); assertEquals(response.getUri().toString(), destinationUrl); log.debug("{} was redirected to {}", redirectTarget, destinationUrl); c.close(); } @Test(groups = {"standalone", "default_provider"}) public void relativePathRedirectTest() throws Throwable { isSet.getAndSet(false); AsyncHttpClientConfig cg = new AsyncHttpClientConfig.Builder().setFollowRedirects(true).build(); AsyncHttpClient c = getAsyncHttpClient(cg); String redirectTarget = "bar/test1"; String destinationUrl = new URI(getTargetUrl()).resolve(redirectTarget).toString(); Response response = c.prepareGet(getTargetUrl()) .setHeader("X-redirect", redirectTarget) .execute().get(); assertNotNull(response); assertEquals(response.getStatusCode(), 200); assertEquals(response.getUri().toString(), destinationUrl); log.debug("{} was redirected to {}", redirectTarget, destinationUrl); c.close(); } } async-http-client-1.6.5/src/test/java/com/ning/http/client/async/RemoteSiteTest.java000066400000000000000000000255321166553056000304440ustar00rootroot00000000000000/* * Copyright 2010 Ning, Inc. * * Ning licenses this file to you 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. */ package com.ning.http.client.async; import com.ning.http.client.AsyncHandler; import com.ning.http.client.AsyncHttpClient; import com.ning.http.client.AsyncHttpClientConfig; import com.ning.http.client.HttpResponseBodyPart; import com.ning.http.client.HttpResponseHeaders; import com.ning.http.client.HttpResponseStatus; import com.ning.http.client.Request; import com.ning.http.client.RequestBuilder; import com.ning.http.client.Response; import com.ning.http.util.AsyncHttpProviderUtils; import org.testng.Assert; import org.testng.annotations.Test; import java.io.InputStream; import java.net.URLEncoder; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertNotNull; import static org.testng.AssertJUnit.assertTrue; /** * Unit tests for remote site. *

* see http://github.com/MSch/ning-async-http-client-bug/tree/master * * @author Martin Schurrer */ public abstract class RemoteSiteTest extends AbstractBasicTest{ public static final String URL = "http://google.com?q="; public static final String REQUEST_PARAM = "github github \n" + "github"; @Test(groups = {"online", "default_provider"}) public void testGoogleCom() throws Throwable { AsyncHttpClient c = getAsyncHttpClient(new AsyncHttpClientConfig.Builder().setRequestTimeoutInMs(10000).build()); // Works Response response = c.prepareGet("http://www.google.com/").execute().get(10,TimeUnit.SECONDS); assertNotNull(response); } @Test(groups = {"online", "default_provider"}) public void testMailGoogleCom() throws Throwable { AsyncHttpClient c = getAsyncHttpClient(new AsyncHttpClientConfig.Builder().setRequestTimeoutInMs(10000).build()); Response response = c.prepareGet("http://mail.google.com/").execute().get(10,TimeUnit.SECONDS); assertNotNull(response); assertEquals(response.getStatusCode(), 200); } @Test(groups = {"online", "default_provider"}) public void testMicrosoftCom() throws Throwable { AsyncHttpClient c = getAsyncHttpClient(new AsyncHttpClientConfig.Builder().setRequestTimeoutInMs(10000).build()); // Works Response response = c.prepareGet("http://microsoft.com/").execute().get(10,TimeUnit.SECONDS); assertNotNull(response); assertEquals(response.getStatusCode(), 301); } @Test(groups = {"online", "default_provider"}) public void testWwwMicrosoftCom() throws Throwable { AsyncHttpClient c = getAsyncHttpClient(new AsyncHttpClientConfig.Builder().setRequestTimeoutInMs(10000).build()); Response response = c.prepareGet("http://www.microsoft.com/").execute().get(10,TimeUnit.SECONDS); assertNotNull(response); assertEquals(response.getStatusCode(), 302); } @Test(groups = {"online", "default_provider"}) public void testUpdateMicrosoftCom() throws Throwable { AsyncHttpClient c = getAsyncHttpClient(new AsyncHttpClientConfig.Builder().setRequestTimeoutInMs(10000).build()); Response response = c.prepareGet("http://update.microsoft.com/").execute().get(10,TimeUnit.SECONDS); assertNotNull(response); assertEquals(response.getStatusCode(), 302); } @Test(groups = {"online", "default_provider"}) public void testGoogleComWithTimeout() throws Throwable { AsyncHttpClient c = getAsyncHttpClient(new AsyncHttpClientConfig.Builder().setRequestTimeoutInMs(10000).build()); // Works Response response = c.prepareGet("http://google.com/").execute().get(10,TimeUnit.SECONDS); assertNotNull(response); assertEquals(response.getStatusCode(), 301); } @Test(groups = {"online", "default_provider"}) public void asyncStatusHEADContentLenghtTest() throws Throwable { AsyncHttpClient p = getAsyncHttpClient( new AsyncHttpClientConfig.Builder().setFollowRedirects(true).build()); final CountDownLatch l = new CountDownLatch(1); Request request = new RequestBuilder("HEAD") .setUrl("http://www.google.com/") .build(); p.executeRequest(request, new AsyncCompletionHandlerAdapter() { @Override public Response onCompleted(Response response) throws Exception { Assert.assertEquals(response.getStatusCode(), 200); l.countDown(); return response; } }).get(); if (!l.await(5, TimeUnit.SECONDS)) { Assert.fail("Timeout out"); } p.close(); } @Test(groups = {"online", "default_provider"}, enabled = false) public void invalidStreamTest2() throws Throwable { AsyncHttpClientConfig config = new AsyncHttpClientConfig.Builder() .setRequestTimeoutInMs(10000) .setFollowRedirects(true) .setAllowPoolingConnection(false) .setMaximumNumberOfRedirects(6) .build(); AsyncHttpClient c = getAsyncHttpClient(config); try { Response response = c.prepareGet("http://bit.ly/aUjTtG").execute().get(); if (response != null) { System.out.println(response); } } catch (Throwable t) { t.printStackTrace(); assertNotNull(t.getCause()); assertEquals(t.getCause().getMessage(), "invalid version format: ICY"); } c.close(); } @Test(groups = {"online", "default_provider"}) public void asyncFullBodyProperlyRead() throws Throwable { final AsyncHttpClient client = getAsyncHttpClient(new AsyncHttpClientConfig.Builder().build()); Response r = client.prepareGet("http://www.cyberpresse.ca/").execute().get(); InputStream stream = r.getResponseBodyAsStream(); int available = stream.available(); int[] lengthWrapper = new int[1]; byte[] bytes = AsyncHttpProviderUtils.readFully(stream, lengthWrapper); int byteToRead = lengthWrapper[0]; Assert.assertEquals(available, byteToRead); client.close(); } @Test(groups = {"online", "default_provider"}) public void testUrlRequestParametersEncoding() throws Throwable { AsyncHttpClient client = getAsyncHttpClient(null); String requestUrl2 = URL + URLEncoder.encode(REQUEST_PARAM, "UTF-8"); log.info(String.format("Executing request [%s] ...", requestUrl2)); Response response = client.prepareGet(requestUrl2).execute().get(); Assert.assertEquals(response.getStatusCode(), 301); } /** * See https://issues.sonatype.org/browse/AHC-61 * @throws Throwable */ @Test(groups = {"online", "default_provider"}) public void testAHC60() throws Throwable { AsyncHttpClient client = getAsyncHttpClient(null); Response response = client.prepareGet("http://www.meetup.com/stackoverflow/Mountain-View-CA/").execute().get(); Assert.assertEquals(response.getStatusCode(), 200); } @Test(groups = {"online", "default_provider"}) public void stripQueryStringTest() throws Throwable { AsyncHttpClientConfig cg = new AsyncHttpClientConfig.Builder().setFollowRedirects(true).build(); AsyncHttpClient c = getAsyncHttpClient(cg); Response response = c.prepareGet("http://www.freakonomics.com/?p=55846") .execute().get(); assertNotNull(response); assertEquals(response.getStatusCode(), 200); c.close(); } @Test(groups = {"online", "default_provider"}) public void stripQueryStringNegativeTest() throws Throwable { AsyncHttpClientConfig cg = new AsyncHttpClientConfig.Builder() .setRemoveQueryParamsOnRedirect(false).setFollowRedirects(true).build(); AsyncHttpClient c = getAsyncHttpClient(cg); Response response = c.prepareGet("http://www.freakonomics.com/?p=55846") .execute().get(); assertNotNull(response); assertEquals(response.getStatusCode(), 301); c.close(); } @Test(groups = {"online", "default_provider"}) public void evilCoookieTest() throws Throwable { AsyncHttpClient c = getAsyncHttpClient(null); RequestBuilder builder2 = new RequestBuilder("GET"); builder2.setFollowRedirects(true); builder2.setUrl("http://www.google.com/"); builder2.addHeader("Content-Type", "text/plain"); builder2.addCookie(new com.ning.http.client.Cookie(".google.com", "evilcookie", "test", "/", 10, false)); com.ning.http.client.Request request2 = builder2.build(); Response response = c.executeRequest(request2).get(); assertNotNull(response); assertEquals(response.getStatusCode(), 200); c.close(); } @Test(groups = {"online", "default_provider"}, enabled = false) public void testAHC62Com() throws Throwable { AsyncHttpClient c = getAsyncHttpClient(new AsyncHttpClientConfig.Builder().setFollowRedirects(true).build()); // Works Response response = c.prepareGet("http://api.crunchbase.com/v/1/financial-organization/kinsey-hills-group.js").execute(new AsyncHandler() { private Response.ResponseBuilder builder = new Response.ResponseBuilder(); public void onThrowable(Throwable t) { t.printStackTrace(); } public STATE onBodyPartReceived(HttpResponseBodyPart bodyPart) throws Exception { System.out.println(bodyPart.getBodyPartBytes().length); builder.accumulate(bodyPart); return STATE.CONTINUE; } public STATE onStatusReceived(HttpResponseStatus responseStatus) throws Exception { builder.accumulate(responseStatus); return STATE.CONTINUE; } public STATE onHeadersReceived(HttpResponseHeaders headers) throws Exception { builder.accumulate(headers); return STATE.CONTINUE; } public Response onCompleted() throws Exception { return builder.build(); } }).get(10, TimeUnit.SECONDS); assertNotNull(response); assertTrue(response.getResponseBody().length() >= 3870); } } async-http-client-1.6.5/src/test/java/com/ning/http/client/async/RequestBuilderTest.java000066400000000000000000000106641166553056000313230ustar00rootroot00000000000000/* * Copyright 2010 Ning, Inc. * * Ning licenses this file to you 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. */ package com.ning.http.client.async; import com.ning.http.client.FluentStringsMap; import com.ning.http.client.Request; import com.ning.http.client.RequestBuilder; import org.testng.annotations.Test; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.util.concurrent.ExecutionException; import static org.testng.Assert.assertEquals; public class RequestBuilderTest { private final static String SAFE_CHARS = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890-_~."; private final static String HEX_CHARS = "0123456789ABCDEF"; @Test(groups = {"standalone", "default_provider"}) public void testEncodesQueryParameters() throws UnsupportedEncodingException { String[] values = new String[]{ "abcdefghijklmnopqrstuvwxyz", "ABCDEFGHIJKQLMNOPQRSTUVWXYZ", "1234567890", "1234567890", "`~!@#$%^&*()", "`~!@#$%^&*()", "_+-=,.<>/?", "_+-=,.<>/?", ";:'\"[]{}\\| ", ";:'\"[]{}\\| " }; /* as per RFC-5849 (Oauth), and RFC-3986 (percent encoding) we MUST * encode everything except for "safe" characters; and nothing but them. * Safe includes ascii letters (upper and lower case), digits (0 - 9) * and FOUR special characters: hyphen ('-'), underscore ('_'), * tilde ('~') and period ('.')). Everything else must be percent-encoded, * byte-by-byte, using UTF-8 encoding (meaning three-byte Unicode/UTF-8 * code points are encoded as three three-letter percent-encode entities). */ for (String value : values) { RequestBuilder builder = new RequestBuilder("GET"). setUrl("http://example.com/"). addQueryParameter("name", value); StringBuilder sb = new StringBuilder(); for (int i = 0, len = value.length(); i < len; ++i) { char c = value.charAt(i); if (SAFE_CHARS.indexOf(c) >= 0) { sb.append(c); } else { int hi = (c >> 4); int lo = c & 0xF; sb.append('%').append(HEX_CHARS.charAt(hi)).append(HEX_CHARS.charAt(lo)); } } String expValue = sb.toString(); Request request = builder.build(); assertEquals(request.getUrl(), "http://example.com/?name=" + expValue); } } @Test(groups = {"standalone", "default_provider"}) public void testChaining() throws IOException, ExecutionException, InterruptedException { Request request = new RequestBuilder("GET") .setUrl("http://foo.com") .addQueryParameter("x", "value") .build(); Request request2 = new RequestBuilder(request).build(); assertEquals(request2.getUrl(), request.getUrl()); } @Test(groups = {"standalone", "default_provider"}) public void testParsesQueryParams() throws IOException, ExecutionException, InterruptedException { Request request = new RequestBuilder("GET") .setUrl("http://foo.com/?param1=value1") .addQueryParameter("param2", "value2") .build(); assertEquals(request.getUrl(), "http://foo.com/?param1=value1¶m2=value2"); FluentStringsMap params = request.getQueryParams(); assertEquals(params.size(), 2); assertEquals(params.get("param1").get(0), "value1"); assertEquals(params.get("param2").get(0), "value2"); } @Test(groups = {"standalone", "default_provider"}) public void testUserProvidedRequestMethod() { Request req = new RequestBuilder("ABC").setUrl("http://foo.com").build(); assertEquals(req.getMethod(), "ABC"); assertEquals(req.getUrl(), "http://foo.com"); } } async-http-client-1.6.5/src/test/java/com/ning/http/client/async/RetryNonBlockingIssue.java000066400000000000000000000257141166553056000317700ustar00rootroot00000000000000/* * Copyright (c) 2010-2011 Sonatype, Inc. All rights reserved. * * This program is licensed to you under the Apache License Version 2.0, * and you may not use this file except in compliance with the Apache License Version 2.0. * You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0. * * Unless required by applicable law or agreed to in writing, * software distributed under the Apache License Version 2.0 is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. */ package com.ning.http.client.async; import com.ning.http.client.AsyncHttpClient; import com.ning.http.client.AsyncHttpClientConfig; import com.ning.http.client.ListenableFuture; import com.ning.http.client.RequestBuilder; import com.ning.http.client.Response; import com.ning.http.client.providers.netty.NettyAsyncHttpProviderConfig; import org.eclipse.jetty.server.Connector; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.nio.SelectChannelConnector; import org.eclipse.jetty.servlet.ServletContextHandler; import org.eclipse.jetty.servlet.ServletHolder; import org.testng.annotations.AfterMethod; import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.net.ServerSocket; import java.net.URI; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.UUID; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ExecutionException; import static org.testng.Assert.assertTrue; public class RetryNonBlockingIssue { private URI servletEndpointUri; private Server server; private int port1; public static int findFreePort() throws IOException { ServerSocket socket = null; try { // 0 is open a socket on any free port socket = new ServerSocket(0); return socket.getLocalPort(); } finally { if (socket != null) { socket.close(); } } } @BeforeMethod public void setUp() throws Exception { server = new Server(); port1 = findFreePort(); Connector listener = new SelectChannelConnector(); listener.setHost("127.0.0.1"); listener.setPort(port1); server.addConnector(listener); ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS); context.setContextPath("/"); server.setHandler(context); context.addServlet(new ServletHolder(new MockExceptionServlet()), "/*"); server.start(); servletEndpointUri = new URI("http://127.0.0.1:" + port1 + "/"); } @AfterMethod public void stop() { try { if (server != null) server.stop(); } catch (Exception e) { } } private ListenableFuture testMethodRequest(AsyncHttpClient fetcher, int requests, String action, String id) throws IOException { RequestBuilder builder = new RequestBuilder("GET"); builder.addQueryParameter(action, "1"); builder.addQueryParameter("maxRequests", "" + requests); builder.addQueryParameter("id", id); builder.setUrl(servletEndpointUri.toString()); com.ning.http.client.Request r = builder.build(); return fetcher.executeRequest(r); } /** * Tests that a head request can be made * * @throws IOException * @throws ExecutionException * @throws InterruptedException */ @Test public void testRetryNonBlocking() throws IOException, InterruptedException, ExecutionException { AsyncHttpClient c = null; List> res = new ArrayList>(); try { AsyncHttpClientConfig.Builder bc = new AsyncHttpClientConfig.Builder(); bc.setAllowPoolingConnection(true); bc.setMaximumConnectionsTotal(100); bc.setConnectionTimeoutInMs(60000); bc.setRequestTimeoutInMs(30000); NettyAsyncHttpProviderConfig config = new NettyAsyncHttpProviderConfig(); bc.setAsyncHttpClientProviderConfig(config); c = new AsyncHttpClient(bc.build()); for (int i = 0; i < 32; i++) { res.add(testMethodRequest(c, 3, "servlet", UUID.randomUUID().toString())); } StringBuilder b = new StringBuilder(); for (ListenableFuture r : res) { Response theres = r.get(); b.append("==============\r\n"); b.append("Response Headers\r\n"); Map> heads = theres.getHeaders(); b.append(heads + "\r\n"); b.append("==============\r\n"); assertTrue(heads.size() > 0); } System.out.println(b.toString()); System.out.flush(); } finally { if (c != null) c.close(); } } @Test public void testRetryNonBlockingAsyncConnect() throws IOException, InterruptedException, ExecutionException { AsyncHttpClient c = null; List> res = new ArrayList>(); try { AsyncHttpClientConfig.Builder bc = new AsyncHttpClientConfig.Builder(); bc.setAllowPoolingConnection(true); bc.setMaximumConnectionsTotal(100); bc.setConnectionTimeoutInMs(60000); bc.setRequestTimeoutInMs(30000); NettyAsyncHttpProviderConfig config = new NettyAsyncHttpProviderConfig(); config.addProperty(NettyAsyncHttpProviderConfig.EXECUTE_ASYNC_CONNECT, "true"); bc.setAsyncHttpClientProviderConfig(config); c = new AsyncHttpClient(bc.build()); for (int i = 0; i < 32; i++) { res.add(testMethodRequest(c, 3, "servlet", UUID.randomUUID().toString())); } StringBuilder b = new StringBuilder(); for (ListenableFuture r : res) { Response theres = r.get(); b.append("==============\r\n"); b.append("Response Headers\r\n"); Map> heads = theres.getHeaders(); b.append(heads + "\r\n"); b.append("==============\r\n"); assertTrue(heads.size() > 0); } System.out.println(b.toString()); System.out.flush(); } finally { if (c != null) c.close(); } } @Test public void testRetryBlocking() throws IOException, InterruptedException, ExecutionException { AsyncHttpClient c = null; List> res = new ArrayList>(); try { AsyncHttpClientConfig.Builder bc = new AsyncHttpClientConfig.Builder(); bc.setAllowPoolingConnection(true); bc.setMaximumConnectionsTotal(100); bc.setConnectionTimeoutInMs(30000); bc.setRequestTimeoutInMs(30000); NettyAsyncHttpProviderConfig config = new NettyAsyncHttpProviderConfig(); config.addProperty(NettyAsyncHttpProviderConfig.USE_BLOCKING_IO, "true"); bc.setAsyncHttpClientProviderConfig(config); c = new AsyncHttpClient(bc.build()); for (int i = 0; i < 32; i++) { res.add(testMethodRequest(c, 3, "servlet", UUID.randomUUID().toString())); } StringBuilder b = new StringBuilder(); for (ListenableFuture r : res) { Response theres = r.get(); b.append("==============\r\n"); b.append("Response Headers\r\n"); Map> heads = theres.getHeaders(); b.append(heads + "\r\n"); b.append("==============\r\n"); assertTrue(heads.size() > 0); } System.out.println(b.toString()); System.out.flush(); } finally { if (c != null) c.close(); } } public class MockExceptionServlet extends HttpServlet { private Map requests = new ConcurrentHashMap(); private synchronized int increment(String id) { int val = 0; if (requests.containsKey(id)) { Integer i = requests.get(id); val = i + 1; requests.put(id, val); } else { requests.put(id, 1); val = 1; } System.out.println("REQUESTS: " + requests); return val; } public void service(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException { String maxRequests = req.getParameter("maxRequests"); int max = 0; try { max = Integer.parseInt(maxRequests); } catch (NumberFormatException e) { max = 3; } String id = req.getParameter("id"); int requestNo = increment(id); String servlet = req.getParameter("servlet"); String io = req.getParameter("io"); String error = req.getParameter("500"); if (requestNo >= max) { res.setHeader("Success-On-Attempt", "" + requestNo); res.setHeader("id", id); if (servlet != null && servlet.trim().length() > 0) res.setHeader("type", "servlet"); if (error != null && error.trim().length() > 0) res.setHeader("type", "500"); if (io != null && io.trim().length() > 0) res.setHeader("type", "io"); res.setStatus(200); res.setContentLength(0); return; } res.setStatus(200); res.setContentLength(100); res.setContentType("application/octet-stream"); res.flushBuffer(); if (servlet != null && servlet.trim().length() > 0) throw new ServletException("Servlet Exception"); if (io != null && io.trim().length() > 0) throw new IOException("IO Exception"); if (error != null && error.trim().length() > 0) res.sendError(500, "servlet process was 500"); } } } async-http-client-1.6.5/src/test/java/com/ning/http/client/async/RetryRequestTest.java000066400000000000000000000061531166553056000310400ustar00rootroot00000000000000/* * Copyright (c) 2010-2011 Sonatype, Inc. All rights reserved. * * This program is licensed to you under the Apache License Version 2.0, * and you may not use this file except in compliance with the Apache License Version 2.0. * You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0. * * Unless required by applicable law or agreed to in writing, * software distributed under the Apache License Version 2.0 is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. */ package com.ning.http.client.async; import com.ning.http.client.AsyncHttpClient; import com.ning.http.client.AsyncHttpClientConfig; import org.eclipse.jetty.server.Request; import org.eclipse.jetty.server.handler.AbstractHandler; import org.testng.annotations.Test; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.OutputStream; import static org.testng.Assert.*; public abstract class RetryRequestTest extends AbstractBasicTest { public static class SlowAndBigHandler extends AbstractHandler { public void handle(String pathInContext, Request request, HttpServletRequest httpRequest, HttpServletResponse httpResponse) throws IOException, ServletException { int load = 100; httpResponse.setStatus(200); httpResponse.setContentLength(load); httpResponse.setContentType("application/octet-stream"); httpResponse.flushBuffer(); OutputStream os = httpResponse.getOutputStream(); for (int i = 0; i < load; i++) { os.write(i % 255); try { Thread.sleep(300); } catch (InterruptedException ex) { // nuku } if (i > load / 10) { httpResponse.sendError(500); } } httpResponse.getOutputStream().flush(); httpResponse.getOutputStream().close(); } } protected String getTargetUrl() { return String.format("http://127.0.0.1:%d/", port1); } @Override public AbstractHandler configureHandler() throws Exception { return new SlowAndBigHandler(); } @Test(groups = {"standalone", "default_provider"}) public void testMaxRetry() throws Throwable { AsyncHttpClient ahc = getAsyncHttpClient(new AsyncHttpClientConfig.Builder().setMaxRequestRetry(0).build()); try { ahc.executeRequest(ahc.prepareGet(getTargetUrl()).build()).get(); fail(); } catch (Exception t) { assertNotNull(t.getCause()); assertEquals(t.getCause().getClass(), IOException.class); if (!t.getCause().getMessage().startsWith("Remotely Closed")) { fail(); } } ahc.close(); } } SimpleAsyncClientErrorBehaviourTest.java000066400000000000000000000071221166553056000345450ustar00rootroot00000000000000async-http-client-1.6.5/src/test/java/com/ning/http/client/async/* * Copyright (c) 2010-2011 Sonatype, Inc. All rights reserved. * * This program is licensed to you under the Apache License Version 2.0, * and you may not use this file except in compliance with the Apache License Version 2.0. * You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0. * * Unless required by applicable law or agreed to in writing, * software distributed under the Apache License Version 2.0 is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. */ package com.ning.http.client.async; import static org.testng.Assert.*; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.util.concurrent.Future; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.eclipse.jetty.server.handler.AbstractHandler; import org.testng.annotations.Test; import com.ning.http.client.AsyncHttpClient; import com.ning.http.client.AsyncHttpClientConfig; import com.ning.http.client.Response; import com.ning.http.client.SimpleAsyncHttpClient; import com.ning.http.client.SimpleAsyncHttpClient.ErrorDocumentBehaviour; import com.ning.http.client.consumers.OutputStreamBodyConsumer; /** * @author Benjamin Hanzelmann * */ public class SimpleAsyncClientErrorBehaviourTest extends AbstractBasicTest { @Test(groups = {"standalone", "default_provider"}) public void testAccumulateErrorBody() throws Throwable { SimpleAsyncHttpClient client = new SimpleAsyncHttpClient.Builder().setUrl(getTargetUrl() + "/nonexistent").setErrorDocumentBehaviour( ErrorDocumentBehaviour.ACCUMULATE ).build(); ByteArrayOutputStream o = new ByteArrayOutputStream(10); Future future = client.get(new OutputStreamBodyConsumer(o)); System.out.println("waiting for response"); Response response = future.get(); assertEquals(response.getStatusCode(), 404); assertEquals(o.toString(), ""); assertTrue(response.getResponseBody().startsWith("")); client.close(); } @Test(groups = {"standalone", "default_provider"}) public void testOmitErrorBody() throws Throwable { SimpleAsyncHttpClient client = new SimpleAsyncHttpClient.Builder().setUrl(getTargetUrl() + "/nonexistent").setErrorDocumentBehaviour( ErrorDocumentBehaviour.OMIT ).build(); ByteArrayOutputStream o = new ByteArrayOutputStream(10); Future future = client.get(new OutputStreamBodyConsumer(o)); System.out.println("waiting for response"); Response response = future.get(); assertEquals(response.getStatusCode(), 404); assertEquals(o.toString(), ""); assertEquals(response.getResponseBody(), ""); client.close(); } @Override public AsyncHttpClient getAsyncHttpClient( AsyncHttpClientConfig config ) { // disabled return null; } @Override public AbstractHandler configureHandler() throws Exception { return new AbstractHandler() { public void handle( String target, org.eclipse.jetty.server.Request baseRequest, HttpServletRequest request, HttpServletResponse response ) throws IOException, ServletException { response.sendError( 404 ); baseRequest.setHandled( true ); } }; } } async-http-client-1.6.5/src/test/java/com/ning/http/client/async/SimpleAsyncHttpClientTest.java000066400000000000000000000302251166553056000326050ustar00rootroot00000000000000/* * Copyright (c) 2010-2011 Sonatype, Inc. All rights reserved. * * This program is licensed to you under the Apache License Version 2.0, * and you may not use this file except in compliance with the Apache License Version 2.0. * You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0. * * Unless required by applicable law or agreed to in writing, * software distributed under the Apache License Version 2.0 is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. */ package com.ning.http.client.async; import com.ning.http.client.ByteArrayPart; import com.ning.http.client.Response; import com.ning.http.client.SimpleAsyncHttpClient; import com.ning.http.client.consumers.AppendableBodyConsumer; import com.ning.http.client.consumers.OutputStreamBodyConsumer; import com.ning.http.client.generators.FileBodyGenerator; import com.ning.http.client.generators.InputStreamBodyGenerator; import com.ning.http.client.simple.HeaderMap; import com.ning.http.client.simple.SimpleAHCTransferListener; import org.testng.annotations.Test; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.IOException; import java.util.concurrent.Future; import static junit.framework.Assert.assertTrue; import static org.testng.Assert.assertEquals; import static org.testng.Assert.fail; import static org.testng.AssertJUnit.assertNotNull; import static org.testng.AssertJUnit.assertNotSame; public abstract class SimpleAsyncHttpClientTest extends AbstractBasicTest { private final static String MY_MESSAGE = "my message"; @Test(groups = { "standalone", "default_provider" }) public void inpuStreamBodyConsumerTest() throws Throwable { SimpleAsyncHttpClient client = new SimpleAsyncHttpClient.Builder().setIdleConnectionInPoolTimeoutInMs(100).setMaximumConnectionsTotal(50) .setRequestTimeoutInMs(5 * 60 * 1000).setUrl(getTargetUrl()).setHeader("Content-Type", "text/html").build(); Future future = client.post(new InputStreamBodyGenerator(new ByteArrayInputStream(MY_MESSAGE.getBytes()))); System.out.println("waiting for response"); Response response = future.get(); assertEquals(response.getStatusCode(), 200); assertEquals(response.getResponseBody(), MY_MESSAGE); client.close(); } @Test(groups = { "standalone", "default_provider" }) public void StringBufferBodyConsumerTest() throws Throwable { SimpleAsyncHttpClient client = new SimpleAsyncHttpClient.Builder().setIdleConnectionInPoolTimeoutInMs(100).setMaximumConnectionsTotal(50) .setRequestTimeoutInMs(5 * 60 * 1000).setUrl(getTargetUrl()).setHeader("Content-Type", "text/html").build(); StringBuilder s = new StringBuilder(); Future future = client.post(new InputStreamBodyGenerator(new ByteArrayInputStream(MY_MESSAGE.getBytes())), new AppendableBodyConsumer(s)); System.out.println("waiting for response"); Response response = future.get(); assertEquals(response.getStatusCode(), 200); assertEquals(s.toString(), MY_MESSAGE); client.close(); } @Test(groups = { "standalone", "default_provider" }) public void ByteArrayOutputStreamBodyConsumerTest() throws Throwable { SimpleAsyncHttpClient client = new SimpleAsyncHttpClient.Builder().setIdleConnectionInPoolTimeoutInMs(100).setMaximumConnectionsTotal(50) .setRequestTimeoutInMs(5 * 60 * 1000).setUrl(getTargetUrl()).setHeader("Content-Type", "text/html").build(); ByteArrayOutputStream o = new ByteArrayOutputStream(10); Future future = client.post(new InputStreamBodyGenerator(new ByteArrayInputStream(MY_MESSAGE.getBytes())), new OutputStreamBodyConsumer(o)); System.out.println("waiting for response"); Response response = future.get(); assertEquals(response.getStatusCode(), 200); assertEquals(o.toString(), MY_MESSAGE); client.close(); } @Test(groups = { "standalone", "default_provider" }) public void RequestByteArrayOutputStreamBodyConsumerTest() throws Throwable { SimpleAsyncHttpClient client = new SimpleAsyncHttpClient.Builder().setUrl(getTargetUrl()).build(); ByteArrayOutputStream o = new ByteArrayOutputStream(10); Future future = client.post(new InputStreamBodyGenerator(new ByteArrayInputStream(MY_MESSAGE.getBytes())), new OutputStreamBodyConsumer(o)); System.out.println("waiting for response"); Response response = future.get(); assertEquals(response.getStatusCode(), 200); assertEquals(o.toString(), MY_MESSAGE); client.close(); } /** * See https://issues.sonatype.org/browse/AHC-5 */ @Test(groups = { "standalone", "default_provider" }, enabled = true) public void testPutZeroBytesFileTest() throws Throwable { System.err.println("setting up client"); SimpleAsyncHttpClient client = new SimpleAsyncHttpClient.Builder().setIdleConnectionInPoolTimeoutInMs(100).setMaximumConnectionsTotal(50) .setRequestTimeoutInMs(5 * 1000).setUrl(getTargetUrl() + "/testPutZeroBytesFileTest.txt").setHeader("Content-Type", "text/plain").build(); File tmpfile = File.createTempFile("testPutZeroBytesFile", ".tmp"); tmpfile.deleteOnExit(); Future future = client.put(new FileBodyGenerator(tmpfile)); System.out.println("waiting for response"); Response response = future.get(); tmpfile.delete(); assertEquals(response.getStatusCode(), 200); client.close(); } @Test(groups = { "standalone", "default_provider" }) public void testDerive() throws Exception { SimpleAsyncHttpClient client = new SimpleAsyncHttpClient.Builder().build(); SimpleAsyncHttpClient derived = client.derive().build(); assertNotSame(derived, client); } @Test(groups = { "standalone", "default_provider" }) public void testDeriveOverrideURL() throws Exception { SimpleAsyncHttpClient client = new SimpleAsyncHttpClient.Builder().setUrl("http://invalid.url").build(); ByteArrayOutputStream o = new ByteArrayOutputStream(10); InputStreamBodyGenerator generator = new InputStreamBodyGenerator(new ByteArrayInputStream(MY_MESSAGE.getBytes())); OutputStreamBodyConsumer consumer = new OutputStreamBodyConsumer(o); SimpleAsyncHttpClient derived = client.derive().setUrl(getTargetUrl()).build(); Future future = derived.post(generator, consumer); Response response = future.get(); assertEquals(response.getStatusCode(), 200); assertEquals(o.toString(), MY_MESSAGE); client.close(); derived.close(); } @Test(groups = { "standalone", "default_provider" }) public void testSimpleTransferListener() throws Exception { SimpleAHCTransferListener listener = new SimpleAHCTransferListener() { public void onStatus(String url, int statusCode, String statusText) { assertEquals(statusCode, 200); assertEquals(url, getTargetUrl()); } public void onHeaders(String url, HeaderMap headers) { assertEquals(url, getTargetUrl()); assertNotNull(headers); assertTrue(!headers.isEmpty()); assertEquals(headers.getFirstValue("X-Custom"), "custom"); } public void onCompleted(String url, int statusCode, String statusText) { assertEquals(statusCode, 200); assertEquals(url, getTargetUrl()); } public void onBytesSent(String url, long amount, long current, long total) { assertEquals(url, getTargetUrl()); assertEquals(total, MY_MESSAGE.getBytes().length); } public void onBytesReceived(String url, long amount, long current, long total) { assertEquals(url, getTargetUrl()); assertEquals(total, -1); } }; SimpleAsyncHttpClient client = new SimpleAsyncHttpClient.Builder().setUrl(getTargetUrl()).setHeader("Custom", "custom").setListener(listener).build(); ByteArrayOutputStream o = new ByteArrayOutputStream(10); InputStreamBodyGenerator generator = new InputStreamBodyGenerator(new ByteArrayInputStream(MY_MESSAGE.getBytes())); OutputStreamBodyConsumer consumer = new OutputStreamBodyConsumer(o); Future future = client.post(generator, consumer); Response response = future.get(); client.close(); assertEquals(response.getStatusCode(), 200); assertEquals(o.toString(), MY_MESSAGE); } @Test(groups = { "standalone", "default_provider" }) public void testNullUrl() throws Exception { try { new SimpleAsyncHttpClient.Builder().build().derive().build(); assertTrue(true); } catch (NullPointerException ex) { fail(); } } @Test(groups = { "standalone", "default_provider" }) public void testCloseDerivedValidMaster() throws Exception { SimpleAsyncHttpClient client = new SimpleAsyncHttpClient.Builder().setUrl(getTargetUrl()).build(); SimpleAsyncHttpClient derived = client.derive().build(); derived.get().get(); derived.close(); Response response = client.get().get(); assertEquals(response.getStatusCode(), 200); } @Test(groups = { "standalone", "default_provider" }) public void testCloseMasterInvalidDerived() throws Exception { SimpleAsyncHttpClient client = new SimpleAsyncHttpClient.Builder().setUrl(getTargetUrl()).build(); SimpleAsyncHttpClient derived = client.derive().build(); client.close(); try { derived.get().get(); fail("Expected closed AHC"); } catch (IOException e) { // expected } } @Test(groups = { "standalone", "default_provider" }) public void testMultiPartPut() throws Exception { SimpleAsyncHttpClient client = new SimpleAsyncHttpClient.Builder().setUrl(getTargetUrl() + "/multipart").build(); Response response = client.put(new ByteArrayPart("baPart", "fileName", "testMultiPart".getBytes("utf-8"), "application/test", "utf-8")).get(); String body = response.getResponseBody(); String contentType = response.getHeader("X-Content-Type"); assertTrue(contentType.contains("multipart/form-data")); String boundary = contentType.substring(contentType.lastIndexOf("=") + 1); assertTrue(body.startsWith("--" + boundary)); assertTrue(body.trim().endsWith("--" + boundary + "--")); assertTrue(body.contains("Content-Disposition:")); assertTrue(body.contains("Content-Type: application/test")); assertTrue(body.contains("name=\"baPart")); assertTrue(body.contains("filename=\"fileName")); } @Test(groups = { "standalone", "default_provider" }) public void testMultiPartPost() throws Exception { SimpleAsyncHttpClient client = new SimpleAsyncHttpClient.Builder().setUrl(getTargetUrl() + "/multipart").build(); Response response = client.post(new ByteArrayPart("baPart", "fileName", "testMultiPart".getBytes("utf-8"), "application/test", "utf-8")).get(); String body = response.getResponseBody(); String contentType = response.getHeader("X-Content-Type"); assertTrue(contentType.contains("multipart/form-data")); String boundary = contentType.substring(contentType.lastIndexOf("=") + 1); assertTrue(body.startsWith("--" + boundary)); assertTrue(body.trim().endsWith("--" + boundary + "--")); assertTrue(body.contains("Content-Disposition:")); assertTrue(body.contains("Content-Type: application/test")); assertTrue(body.contains("name=\"baPart")); assertTrue(body.contains("filename=\"fileName")); } } async-http-client-1.6.5/src/test/java/com/ning/http/client/async/TransferListenerTest.java000066400000000000000000000252201166553056000316500ustar00rootroot00000000000000/* * Copyright (c) 2010-2011 Sonatype, Inc. All rights reserved. * * This program is licensed to you under the Apache License Version 2.0, * and you may not use this file except in compliance with the Apache License Version 2.0. * You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0. * * Unless required by applicable law or agreed to in writing, * software distributed under the Apache License Version 2.0 is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. */ package com.ning.http.client.async; import com.ning.http.client.AsyncHttpClient; import com.ning.http.client.FluentCaseInsensitiveStringsMap; import com.ning.http.client.Response; import com.ning.http.client.generators.FileBodyGenerator; import com.ning.http.client.listener.TransferCompletionHandler; import com.ning.http.client.listener.TransferListener; import org.eclipse.jetty.server.handler.AbstractHandler; import org.testng.annotations.Test; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.nio.ByteBuffer; import java.util.Enumeration; import java.util.UUID; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicReference; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertNotNull; import static org.testng.Assert.assertNull; import static org.testng.Assert.fail; public abstract class TransferListenerTest extends AbstractBasicTest { private static final File TMP = new File(System.getProperty("java.io.tmpdir"), "ahc-tests-" + UUID.randomUUID().toString().substring(0, 8)); private class BasicHandler extends AbstractHandler { public void handle(String s, org.eclipse.jetty.server.Request r, HttpServletRequest httpRequest, HttpServletResponse httpResponse) throws IOException, ServletException { Enumeration e = httpRequest.getHeaderNames(); String param; while (e.hasMoreElements()) { param = e.nextElement().toString(); httpResponse.addHeader("X-" + param, httpRequest.getHeader(param)); } int size = 10 * 1024; if (httpRequest.getContentLength() > 0) { size = httpRequest.getContentLength(); } byte[] bytes = new byte[size]; if (bytes.length > 0) { httpRequest.getInputStream().read(bytes); httpResponse.getOutputStream().write(bytes); } httpResponse.setStatus(200); httpResponse.getOutputStream().flush(); httpResponse.getOutputStream().close(); } } @Override public AbstractHandler configureHandler() throws Exception { return new BasicHandler(); } @Test(groups = {"standalone", "default_provider"}) public void basicGetTest() throws Throwable { AsyncHttpClient c = getAsyncHttpClient(null); final AtomicReference throwable = new AtomicReference(); final AtomicReference hSent = new AtomicReference(); final AtomicReference hRead = new AtomicReference(); final AtomicReference bb = new AtomicReference(); final AtomicBoolean completed = new AtomicBoolean(false); TransferCompletionHandler tl = new TransferCompletionHandler(); tl.addTransferListener(new TransferListener() { public void onRequestHeadersSent(FluentCaseInsensitiveStringsMap headers) { hSent.set(headers); } public void onResponseHeadersReceived(FluentCaseInsensitiveStringsMap headers) { hRead.set(headers); } public void onBytesReceived(ByteBuffer buffer) { bb.set(buffer); } public void onBytesSent(ByteBuffer buffer) { } public void onRequestResponseCompleted() { completed.set(true); } public void onThrowable(Throwable t) { throwable.set(t); } }); try { Response response = c.prepareGet(getTargetUrl()) .execute(tl).get(); assertNotNull(response); assertEquals(response.getStatusCode(), 200); assertNotNull(hRead.get()); assertNotNull(hSent.get()); assertNotNull(bb.get()); assertNull(throwable.get()); } catch (IOException ex) { fail("Should have timed out"); } c.close(); } @Test(groups = {"standalone", "default_provider"}) public void basicPutTest() throws Throwable { AsyncHttpClient c = getAsyncHttpClient(null); final AtomicReference throwable = new AtomicReference(); final AtomicReference hSent = new AtomicReference(); final AtomicReference hRead = new AtomicReference(); final AtomicInteger bbReceivedLenght = new AtomicInteger(0); final AtomicInteger bbSentLenght = new AtomicInteger(0); final AtomicBoolean completed = new AtomicBoolean(false); byte[] bytes = "RatherLargeFileRatherLargeFileRatherLargeFileRatherLargeFile".getBytes("UTF-16"); long repeats = (1024 * 100 * 10 / bytes.length) + 1; File largeFile = createTempFile(bytes, (int) repeats); TransferCompletionHandler tl = new TransferCompletionHandler(); tl.addTransferListener(new TransferListener() { public void onRequestHeadersSent(FluentCaseInsensitiveStringsMap headers) { hSent.set(headers); } public void onResponseHeadersReceived(FluentCaseInsensitiveStringsMap headers) { hRead.set(headers); } public void onBytesReceived(ByteBuffer buffer) { bbReceivedLenght.addAndGet(buffer.capacity()); } public void onBytesSent(ByteBuffer buffer) { bbSentLenght.addAndGet(buffer.capacity()); } public void onRequestResponseCompleted() { completed.set(true); } public void onThrowable(Throwable t) { throwable.set(t); } }); try { Response response = c.preparePut(getTargetUrl()).setBody(largeFile) .execute(tl).get(); assertNotNull(response); assertEquals(response.getStatusCode(), 200); assertNotNull(hRead.get()); assertNotNull(hSent.get()); assertEquals(bbReceivedLenght.get(), largeFile.length()); assertEquals(bbSentLenght.get(), largeFile.length()); } catch (IOException ex) { fail("Should have timed out"); } c.close(); } @Test(groups = {"standalone", "default_provider"}) public void basicPutBodyTest() throws Throwable { AsyncHttpClient c = getAsyncHttpClient(null); final AtomicReference throwable = new AtomicReference(); final AtomicReference hSent = new AtomicReference(); final AtomicReference hRead = new AtomicReference(); final AtomicInteger bbReceivedLenght = new AtomicInteger(0); final AtomicInteger bbSentLenght = new AtomicInteger(0); final AtomicBoolean completed = new AtomicBoolean(false); byte[] bytes = "RatherLargeFileRatherLargeFileRatherLargeFileRatherLargeFile".getBytes("UTF-16"); long repeats = (1024 * 100 * 10 / bytes.length) + 1; File largeFile = createTempFile(bytes, (int) repeats); TransferCompletionHandler tl = new TransferCompletionHandler(); tl.addTransferListener(new TransferListener() { public void onRequestHeadersSent(FluentCaseInsensitiveStringsMap headers) { hSent.set(headers); } public void onResponseHeadersReceived(FluentCaseInsensitiveStringsMap headers) { hRead.set(headers); } public void onBytesReceived(ByteBuffer buffer) { bbReceivedLenght.addAndGet(buffer.capacity()); } public void onBytesSent(ByteBuffer buffer) { bbSentLenght.addAndGet(buffer.capacity()); } public void onRequestResponseCompleted() { completed.set(true); } public void onThrowable(Throwable t) { throwable.set(t); } }); try { Response response = c.preparePut(getTargetUrl()).setBody(new FileBodyGenerator(largeFile)) .execute(tl).get(); assertNotNull(response); assertEquals(response.getStatusCode(), 200); assertNotNull(hRead.get()); assertNotNull(hSent.get()); assertEquals(bbReceivedLenght.get(), largeFile.length()); assertEquals(bbSentLenght.get(), largeFile.length()); } catch (IOException ex) { fail("Should have timed out"); } c.close(); } public String getTargetUrl() { return String.format("http://127.0.0.1:%d/foo/test", port1); } public static File createTempFile(byte[] pattern, int repeat) throws IOException { TMP.mkdirs(); TMP.deleteOnExit(); File tmpFile = File.createTempFile("tmpfile-", ".data", TMP); write(pattern, repeat, tmpFile); return tmpFile; } public static void write(byte[] pattern, int repeat, File file) throws IOException { file.deleteOnExit(); file.getParentFile().mkdirs(); FileOutputStream out = null; try { out = new FileOutputStream(file); for (int i = 0; i < repeat; i++) { out.write(pattern); } } finally { if (out != null) { out.close(); } } } } async-http-client-1.6.5/src/test/java/com/ning/http/client/async/WebDavBasicTest.java000066400000000000000000000156211166553056000304740ustar00rootroot00000000000000/* * Copyright (c) 2010-2011 Sonatype, Inc. All rights reserved. * * This program is licensed to you under the Apache License Version 2.0, * and you may not use this file except in compliance with the Apache License Version 2.0. * You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0. * * Unless required by applicable law or agreed to in writing, * software distributed under the Apache License Version 2.0 is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. */ package com.ning.http.client.async; import com.ning.http.client.AsyncHttpClient; import com.ning.http.client.Request; import com.ning.http.client.RequestBuilder; import com.ning.http.client.Response; import com.ning.http.client.webdav.WebDavCompletionHandlerBase; import com.ning.http.client.webdav.WebDavResponse; import org.apache.catalina.Context; import org.apache.catalina.Engine; import org.apache.catalina.Host; import org.apache.catalina.Wrapper; import org.apache.catalina.connector.Connector; import org.apache.catalina.startup.Embedded; import org.apache.coyote.http11.Http11NioProtocol; import org.testng.annotations.AfterClass; import org.testng.annotations.AfterMethod; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; import java.io.File; import java.io.IOException; import java.util.concurrent.ExecutionException; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertNotNull; import static org.testng.Assert.assertTrue; public abstract class WebDavBasicTest extends AbstractBasicTest { public Embedded embedded; @BeforeClass(alwaysRun = true) public void setUpGlobal() throws Exception { port1 = findFreePort(); embedded = new Embedded(); String path = new File(".").getAbsolutePath(); embedded.setCatalinaHome(path); Engine engine = embedded.createEngine(); engine.setDefaultHost("127.0.0.1"); Host host = embedded.createHost("127.0.0.1", path); engine.addChild(host); Context c = embedded.createContext("/", path); c.setReloadable(false); Wrapper w = c.createWrapper(); w.addMapping("/*"); w.setServletClass(org.apache.catalina.servlets.WebdavServlet.class.getName()); w.addInitParameter("readonly", "false"); w.addInitParameter("listings", "true"); w.setLoadOnStartup(0); c.addChild(w); host.addChild(c); Connector connector = embedded.createConnector("127.0.0.1", port1, Http11NioProtocol.class.getName()); connector.setContainer(host); embedded.addEngine(engine); embedded.addConnector(connector); embedded.start(); } protected String getTargetUrl() { return String.format("http://127.0.0.1:%s/folder1", port1); } @AfterMethod(alwaysRun = true) public void clean() throws InterruptedException, Exception { AsyncHttpClient c = getAsyncHttpClient(null); Request deleteRequest = new RequestBuilder("DELETE").setUrl(getTargetUrl()).build(); c.executeRequest(deleteRequest).get(); } @AfterClass(alwaysRun = true) public void tearDownGlobal() throws InterruptedException, Exception { embedded.stop(); } @Test(groups = {"standalone", "default_provider"}) public void mkcolWebDavTest1() throws InterruptedException, IOException, ExecutionException { AsyncHttpClient c = getAsyncHttpClient(null); Request mkcolRequest = new RequestBuilder("MKCOL").setUrl(getTargetUrl()).build(); Response response = c.executeRequest(mkcolRequest).get(); assertEquals(response.getStatusCode(), 201); c.close(); } @Test(groups = {"standalone", "default_provider"}) public void mkcolWebDavTest2() throws InterruptedException, IOException, ExecutionException { AsyncHttpClient c = getAsyncHttpClient(null); Request mkcolRequest = new RequestBuilder("MKCOL").setUrl(getTargetUrl() + "/folder2").build(); Response response = c.executeRequest(mkcolRequest).get(); assertEquals(response.getStatusCode(), 409); c.close(); } @Test(groups = {"standalone", "default_provider"}) public void basicPropFindWebDavTest() throws InterruptedException, IOException, ExecutionException { AsyncHttpClient c = getAsyncHttpClient(null); Request propFindRequest = new RequestBuilder("PROPFIND").setUrl(getTargetUrl()).build(); Response response = c.executeRequest(propFindRequest).get(); assertEquals(response.getStatusCode(), 404); c.close(); } @Test(groups = {"standalone", "default_provider"}) public void propFindWebDavTest() throws InterruptedException, IOException, ExecutionException { AsyncHttpClient c = getAsyncHttpClient(null); Request mkcolRequest = new RequestBuilder("MKCOL").setUrl(getTargetUrl()).build(); Response response = c.executeRequest(mkcolRequest).get(); assertEquals(response.getStatusCode(), 201); Request putRequest = new RequestBuilder("PUT").setUrl(String.format("http://127.0.0.1:%s/folder1/Test.txt", port1)).setBody("this is a test").build(); response = c.executeRequest(putRequest).get(); assertEquals(response.getStatusCode(), 201); Request propFindRequest = new RequestBuilder("PROPFIND").setUrl(String.format("http://127.0.0.1:%s/folder1/Test.txt", port1)).build(); response = c.executeRequest(propFindRequest).get(); assertEquals(response.getStatusCode(), 207); assertTrue(response.getResponseBody().contains("HTTP/1.1 200 OK")); c.close(); } @Test(groups = {"standalone", "default_provider"}) public void propFindCompletionHandlerWebDavTest() throws InterruptedException, IOException, ExecutionException { AsyncHttpClient c = getAsyncHttpClient(null); Request mkcolRequest = new RequestBuilder("MKCOL").setUrl(getTargetUrl()).build(); Response response = c.executeRequest(mkcolRequest).get(); assertEquals(response.getStatusCode(), 201); Request propFindRequest = new RequestBuilder("PROPFIND").setUrl(getTargetUrl()).build(); WebDavResponse webDavResponse = c.executeRequest(propFindRequest, new WebDavCompletionHandlerBase() { /** * {@inheritDoc} */ /* @Override */ public void onThrowable(Throwable t) { t.printStackTrace(); } @Override public WebDavResponse onCompleted(WebDavResponse response) throws Exception { return response; } }).get(); assertNotNull(webDavResponse); assertEquals(webDavResponse.getStatusCode(), 200); c.close(); } } async-http-client-1.6.5/src/test/java/com/ning/http/client/async/ZeroCopyFileTest.java000066400000000000000000000206701166553056000307340ustar00rootroot00000000000000/* * Copyright (c) 2010-2011 Sonatype, Inc. All rights reserved. * * This program is licensed to you under the Apache License Version 2.0, * and you may not use this file except in compliance with the Apache License Version 2.0. * You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0. * * Unless required by applicable law or agreed to in writing, * software distributed under the Apache License Version 2.0 is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. */ package com.ning.http.client.async; import com.ning.http.client.AsyncCompletionHandler; import com.ning.http.client.AsyncHandler; import com.ning.http.client.AsyncHttpClient; import com.ning.http.client.HttpResponseBodyPart; import com.ning.http.client.HttpResponseHeaders; import com.ning.http.client.HttpResponseStatus; import com.ning.http.client.Response; import org.eclipse.jetty.server.Request; import org.eclipse.jetty.server.handler.AbstractHandler; import org.testng.annotations.Test; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.net.URISyntaxException; import java.net.URL; import java.util.concurrent.ExecutionException; import java.util.concurrent.Future; import java.util.concurrent.TimeoutException; import java.util.concurrent.atomic.AtomicBoolean; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertNotNull; import static org.testng.Assert.assertNull; import static org.testng.Assert.assertTrue; /** * Zero copy test which use FileChannel.transfer under the hood . The same SSL test is also covered in {@link com.ning.http.client.async.BasicHttpsTest} */ public abstract class ZeroCopyFileTest extends AbstractBasicTest { private class ZeroCopyHandler extends AbstractHandler { public void handle(String s, Request r, HttpServletRequest httpRequest, HttpServletResponse httpResponse) throws IOException, ServletException { int size = 10 * 1024; if (httpRequest.getContentLength() > 0) { size = httpRequest.getContentLength(); } byte[] bytes = new byte[size]; if (bytes.length > 0) { httpRequest.getInputStream().read(bytes); httpResponse.getOutputStream().write(bytes); } httpResponse.setStatus(200); httpResponse.getOutputStream().flush(); } } @Test(groups = {"standalone", "default_provider"}) public void zeroCopyPostTest() throws IOException, ExecutionException, TimeoutException, InterruptedException, URISyntaxException { AsyncHttpClient client = getAsyncHttpClient(null); ClassLoader cl = getClass().getClassLoader(); // override system properties URL url = cl.getResource("SimpleTextFile.txt"); File file = new File(url.toURI()); final AtomicBoolean headerSent = new AtomicBoolean(false); final AtomicBoolean operationCompleted = new AtomicBoolean(false); Future f = client.preparePost("http://127.0.0.1:" + port1 + "/").setBody(file).execute(new AsyncCompletionHandler() { public STATE onHeaderWriteCompleted() { headerSent.set(true); return STATE.CONTINUE; } public STATE onContentWriteCompleted() { operationCompleted.set(true); return STATE.CONTINUE; } @Override public Object onCompleted(Response response) throws Exception { return response; } }); Response resp = f.get(); assertNotNull(resp); assertEquals(resp.getStatusCode(), HttpServletResponse.SC_OK); assertEquals(resp.getResponseBody(), "This is a simple test file"); assertTrue(operationCompleted.get()); assertTrue(headerSent.get()); client.close(); } @Test(groups = {"standalone", "default_provider"}) public void zeroCopyPutTest() throws IOException, ExecutionException, TimeoutException, InterruptedException, URISyntaxException { AsyncHttpClient client = getAsyncHttpClient(null); ClassLoader cl = getClass().getClassLoader(); // override system properties URL url = cl.getResource("SimpleTextFile.txt"); File file = new File(url.toURI()); Future f = client.preparePut("http://127.0.0.1:" + port1 + "/").setBody(file).execute(); Response resp = f.get(); assertNotNull(resp); assertEquals(resp.getStatusCode(), HttpServletResponse.SC_OK); assertEquals(resp.getResponseBody(), "This is a simple test file"); client.close(); } @Override public AbstractHandler configureHandler() throws Exception { return new ZeroCopyHandler(); } @Test(groups = {"standalone", "default_provider"}) public void zeroCopyFileTest() throws IOException, ExecutionException, TimeoutException, InterruptedException, URISyntaxException { AsyncHttpClient client = getAsyncHttpClient(null); ClassLoader cl = getClass().getClassLoader(); // override system properties URL url = cl.getResource("SimpleTextFile.txt"); File file = new File(url.toURI()); File tmp = new File(System.getProperty("java.io.tmpdir") + File.separator + "zeroCopy.txt"); tmp.deleteOnExit(); final FileOutputStream stream = new FileOutputStream(tmp); Future f = client.preparePost("http://127.0.0.1:" + port1 + "/").setBody(file).execute(new AsyncHandler() { public void onThrowable(Throwable t) { } public STATE onBodyPartReceived(HttpResponseBodyPart bodyPart) throws Exception { bodyPart.writeTo(stream); return STATE.CONTINUE; } public STATE onStatusReceived(HttpResponseStatus responseStatus) throws Exception { return STATE.CONTINUE; } public STATE onHeadersReceived(HttpResponseHeaders headers) throws Exception { return STATE.CONTINUE; } public Response onCompleted() throws Exception { return null; } }); Response resp = f.get(); stream.close(); assertNull(resp); assertEquals(file.length(), tmp.length()); client.close(); } @Test(groups = {"standalone", "default_provider"}) public void zeroCopyFileWithBodyManipulationTest() throws IOException, ExecutionException, TimeoutException, InterruptedException, URISyntaxException { AsyncHttpClient client = getAsyncHttpClient(null); ClassLoader cl = getClass().getClassLoader(); // override system properties URL url = cl.getResource("SimpleTextFile.txt"); File file = new File(url.toURI()); File tmp = new File(System.getProperty("java.io.tmpdir") + File.separator + "zeroCopy.txt"); tmp.deleteOnExit(); final FileOutputStream stream = new FileOutputStream(tmp); Future f = client.preparePost("http://127.0.0.1:" + port1 + "/").setBody(file).execute(new AsyncHandler() { public void onThrowable(Throwable t) { } public STATE onBodyPartReceived(HttpResponseBodyPart bodyPart) throws Exception { bodyPart.writeTo(stream); if (bodyPart.getBodyPartBytes().length == 0) { return STATE.ABORT; } return STATE.CONTINUE; } public STATE onStatusReceived(HttpResponseStatus responseStatus) throws Exception { return STATE.CONTINUE; } public STATE onHeadersReceived(HttpResponseHeaders headers) throws Exception { return STATE.CONTINUE; } public Response onCompleted() throws Exception { return null; } }); Response resp = f.get(); stream.close(); assertNull(resp); assertEquals(file.length(), tmp.length()); client.close(); } } async-http-client-1.6.5/src/test/java/com/ning/http/client/async/netty/000077500000000000000000000000001166553056000260155ustar00rootroot00000000000000NettyAsyncHttpProviderTest.java000066400000000000000000000036371166553056000341260ustar00rootroot00000000000000async-http-client-1.6.5/src/test/java/com/ning/http/client/async/netty/* * Copyright (c) 2010-2011 Sonatype, Inc. All rights reserved. * * This program is licensed to you under the Apache License Version 2.0, * and you may not use this file except in compliance with the Apache License Version 2.0. * You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0. * * Unless required by applicable law or agreed to in writing, * software distributed under the Apache License Version 2.0 is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. */ package com.ning.http.client.async.netty; import com.ning.http.client.AsyncHttpClient; import com.ning.http.client.AsyncHttpClientConfig; import com.ning.http.client.Response; import com.ning.http.client.async.AbstractBasicTest; import com.ning.http.client.async.ProviderUtil; import com.ning.http.client.providers.netty.NettyAsyncHttpProviderConfig; import org.testng.annotations.Test; import java.util.concurrent.Executors; import static org.testng.Assert.assertEquals; public class NettyAsyncHttpProviderTest extends AbstractBasicTest { @Test public void bossThreadPoolExecutor() throws Throwable { NettyAsyncHttpProviderConfig conf = new NettyAsyncHttpProviderConfig(); conf.addProperty(NettyAsyncHttpProviderConfig.BOSS_EXECUTOR_SERVICE, Executors.newSingleThreadExecutor()); AsyncHttpClientConfig cf = new AsyncHttpClientConfig.Builder().setAsyncHttpClientProviderConfig(conf).build(); AsyncHttpClient c = getAsyncHttpClient(cf); Response r = c.prepareGet(getTargetUrl()).execute().get(); assertEquals(r.getStatusCode(), 200); } @Override public AsyncHttpClient getAsyncHttpClient(AsyncHttpClientConfig config) { return ProviderUtil.nettyProvider(config); } } NettyAsyncProviderBasicTest.java000066400000000000000000000022231166553056000342160ustar00rootroot00000000000000async-http-client-1.6.5/src/test/java/com/ning/http/client/async/netty/* * Copyright (c) 2010-2011 Sonatype, Inc. All rights reserved. * * This program is licensed to you under the Apache License Version 2.0, * and you may not use this file except in compliance with the Apache License Version 2.0. * You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0. * * Unless required by applicable law or agreed to in writing, * software distributed under the Apache License Version 2.0 is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. */ package com.ning.http.client.async.netty; import com.ning.http.client.AsyncHttpClient; import com.ning.http.client.AsyncHttpClientConfig; import com.ning.http.client.async.AsyncProvidersBasicTest; import com.ning.http.client.async.ProviderUtil; public class NettyAsyncProviderBasicTest extends AsyncProvidersBasicTest { @Override public AsyncHttpClient getAsyncHttpClient(AsyncHttpClientConfig config) { return ProviderUtil.nettyProvider(config); } } NettyAsyncStreamHandlerTest.java000066400000000000000000000022201166553056000342100ustar00rootroot00000000000000async-http-client-1.6.5/src/test/java/com/ning/http/client/async/netty/* * Copyright (c) 2010-2011 Sonatype, Inc. All rights reserved. * * This program is licensed to you under the Apache License Version 2.0, * and you may not use this file except in compliance with the Apache License Version 2.0. * You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0. * * Unless required by applicable law or agreed to in writing, * software distributed under the Apache License Version 2.0 is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. */ package com.ning.http.client.async.netty; import com.ning.http.client.AsyncHttpClient; import com.ning.http.client.AsyncHttpClientConfig; import com.ning.http.client.async.AsyncStreamHandlerTest; import com.ning.http.client.async.ProviderUtil; public class NettyAsyncStreamHandlerTest extends AsyncStreamHandlerTest { @Override public AsyncHttpClient getAsyncHttpClient(AsyncHttpClientConfig config) { return ProviderUtil.nettyProvider(config); } } NettyAsyncStreamLifecycleTest.java000066400000000000000000000022251166553056000345370ustar00rootroot00000000000000async-http-client-1.6.5/src/test/java/com/ning/http/client/async/netty/* * Copyright (c) 2010-2011 Sonatype, Inc. All rights reserved. * * This program is licensed to you under the Apache License Version 2.0, * and you may not use this file except in compliance with the Apache License Version 2.0. * You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0. * * Unless required by applicable law or agreed to in writing, * software distributed under the Apache License Version 2.0 is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. */ package com.ning.http.client.async.netty; import com.ning.http.client.AsyncHttpClient; import com.ning.http.client.AsyncHttpClientConfig; import com.ning.http.client.async.AsyncStreamLifecycleTest; import com.ning.http.client.async.ProviderUtil; public class NettyAsyncStreamLifecycleTest extends AsyncStreamLifecycleTest { @Override public AsyncHttpClient getAsyncHttpClient(AsyncHttpClientConfig config) { return ProviderUtil.nettyProvider(config); } } async-http-client-1.6.5/src/test/java/com/ning/http/client/async/netty/NettyAuthTimeoutTest.java000066400000000000000000000021741166553056000330200ustar00rootroot00000000000000/* * Copyright (c) 2010-2011 Sonatype, Inc. All rights reserved. * * This program is licensed to you under the Apache License Version 2.0, * and you may not use this file except in compliance with the Apache License Version 2.0. * You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0. * * Unless required by applicable law or agreed to in writing, * software distributed under the Apache License Version 2.0 is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. */ package com.ning.http.client.async.netty; import com.ning.http.client.AsyncHttpClient; import com.ning.http.client.AsyncHttpClientConfig; import com.ning.http.client.async.AuthTimeoutTest; import com.ning.http.client.async.ProviderUtil; public class NettyAuthTimeoutTest extends AuthTimeoutTest { @Override public AsyncHttpClient getAsyncHttpClient(AsyncHttpClientConfig config) { return ProviderUtil.nettyProvider(config); } } async-http-client-1.6.5/src/test/java/com/ning/http/client/async/netty/NettyBasicAuthTest.java000066400000000000000000000021721166553056000324110ustar00rootroot00000000000000/* * Copyright (c) 2010-2011 Sonatype, Inc. All rights reserved. * * This program is licensed to you under the Apache License Version 2.0, * and you may not use this file except in compliance with the Apache License Version 2.0. * You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0. * * Unless required by applicable law or agreed to in writing, * software distributed under the Apache License Version 2.0 is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. */ package com.ning.http.client.async.netty; import com.ning.http.client.AsyncHttpClient; import com.ning.http.client.AsyncHttpClientConfig; import com.ning.http.client.async.BasicAuthTest; import com.ning.http.client.async.ProviderUtil; public class NettyBasicAuthTest extends BasicAuthTest { @Override public AsyncHttpClient getAsyncHttpClient(AsyncHttpClientConfig config) { return ProviderUtil.nettyProvider(config); } } async-http-client-1.6.5/src/test/java/com/ning/http/client/async/netty/NettyBasicHttpsTest.java000066400000000000000000000021701166553056000326100ustar00rootroot00000000000000/* * Copyright (c) 2010-2011 Sonatype, Inc. All rights reserved. * * This program is licensed to you under the Apache License Version 2.0, * and you may not use this file except in compliance with the Apache License Version 2.0. * You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0. * * Unless required by applicable law or agreed to in writing, * software distributed under the Apache License Version 2.0 is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. */ package com.ning.http.client.async.netty; import com.ning.http.client.AsyncHttpClient; import com.ning.http.client.AsyncHttpClientConfig; import com.ning.http.client.async.BasicHttpsTest; import com.ning.http.client.async.ProviderUtil; public class NettyBasicHttpsTest extends BasicHttpsTest { @Override public AsyncHttpClient getAsyncHttpClient(AsyncHttpClientConfig config) { return ProviderUtil.nettyProvider(config); } } async-http-client-1.6.5/src/test/java/com/ning/http/client/async/netty/NettyBodyChunkTest.java000066400000000000000000000021651166553056000324360ustar00rootroot00000000000000/* * Copyright (c) 2010-2011 Sonatype, Inc. All rights reserved. * * This program is licensed to you under the Apache License Version 2.0, * and you may not use this file except in compliance with the Apache License Version 2.0. * You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0. * * Unless required by applicable law or agreed to in writing, * software distributed under the Apache License Version 2.0 is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. */ package com.ning.http.client.async.netty; import com.ning.http.client.AsyncHttpClient; import com.ning.http.client.AsyncHttpClientConfig; import com.ning.http.client.async.BodyChunkTest; import com.ning.http.client.async.ProviderUtil; public class NettyBodyChunkTest extends BodyChunkTest { @Override public AsyncHttpClient getAsyncHttpClient(AsyncHttpClientConfig config) { return ProviderUtil.nettyProvider(config); } } NettyBodyDeferringAsyncHandlerTest.java000066400000000000000000000022561166553056000355110ustar00rootroot00000000000000async-http-client-1.6.5/src/test/java/com/ning/http/client/async/netty/* * Copyright (c) 2010-2011 Sonatype, Inc. All rights reserved. * * This program is licensed to you under the Apache License Version 2.0, * and you may not use this file except in compliance with the Apache License Version 2.0. * You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0. * * Unless required by applicable law or agreed to in writing, * software distributed under the Apache License Version 2.0 is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. */ package com.ning.http.client.async.netty; import com.ning.http.client.AsyncHttpClient; import com.ning.http.client.AsyncHttpClientConfig; import com.ning.http.client.async.BodyDeferringAsyncHandlerTest; import com.ning.http.client.async.ProviderUtil; public class NettyBodyDeferringAsyncHandlerTest extends BodyDeferringAsyncHandlerTest { @Override public AsyncHttpClient getAsyncHttpClient(AsyncHttpClientConfig config) { return ProviderUtil.nettyProvider(config); } } NettyByteBufferCapacityTest.java000066400000000000000000000023051166553056000342000ustar00rootroot00000000000000async-http-client-1.6.5/src/test/java/com/ning/http/client/async/netty/* * Copyright (c) 2010-2011 Sonatype, Inc. All rights reserved. * * This program is licensed to you under the Apache License Version 2.0, * and you may not use this file except in compliance with the Apache License Version 2.0. * You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0. * * Unless required by applicable law or agreed to in writing, * software distributed under the Apache License Version 2.0 is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. */ package com.ning.http.client.async.netty; import com.ning.http.client.AsyncHttpClient; import com.ning.http.client.AsyncHttpClientConfig; import com.ning.http.client.async.AbstractBasicTest; import com.ning.http.client.async.ByteBufferCapacityTest; import com.ning.http.client.async.ProviderUtil; public class NettyByteBufferCapacityTest extends ByteBufferCapacityTest { @Override public AsyncHttpClient getAsyncHttpClient(AsyncHttpClientConfig config) { return ProviderUtil.nettyProvider(config); } } async-http-client-1.6.5/src/test/java/com/ning/http/client/async/netty/NettyChunkingTest.java000066400000000000000000000006711166553056000323160ustar00rootroot00000000000000package com.ning.http.client.async.netty; import com.ning.http.client.AsyncHttpClient; import com.ning.http.client.AsyncHttpClientConfig; import com.ning.http.client.async.ChunkingTest; import com.ning.http.client.async.ProviderUtil; public class NettyChunkingTest extends ChunkingTest { @Override public AsyncHttpClient getAsyncHttpClient(AsyncHttpClientConfig config) { return ProviderUtil.nettyProvider(config); } } async-http-client-1.6.5/src/test/java/com/ning/http/client/async/netty/NettyComplexClientTest.java000066400000000000000000000022011166553056000333050ustar00rootroot00000000000000/* * Copyright (c) 2010-2011 Sonatype, Inc. All rights reserved. * * This program is licensed to you under the Apache License Version 2.0, * and you may not use this file except in compliance with the Apache License Version 2.0. * You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0. * * Unless required by applicable law or agreed to in writing, * software distributed under the Apache License Version 2.0 is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. */ package com.ning.http.client.async.netty; import com.ning.http.client.AsyncHttpClient; import com.ning.http.client.AsyncHttpClientConfig; import com.ning.http.client.async.ComplexClientTest; import com.ning.http.client.async.ProviderUtil; public class NettyComplexClientTest extends ComplexClientTest { @Override public AsyncHttpClient getAsyncHttpClient(AsyncHttpClientConfig config) { return ProviderUtil.nettyProvider(config); } } async-http-client-1.6.5/src/test/java/com/ning/http/client/async/netty/NettyConnectionPoolTest.java000066400000000000000000000022051166553056000334740ustar00rootroot00000000000000/* * Copyright (c) 2010-2011 Sonatype, Inc. All rights reserved. * * This program is licensed to you under the Apache License Version 2.0, * and you may not use this file except in compliance with the Apache License Version 2.0. * You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0. * * Unless required by applicable law or agreed to in writing, * software distributed under the Apache License Version 2.0 is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. */ package com.ning.http.client.async.netty; import com.ning.http.client.AsyncHttpClient; import com.ning.http.client.AsyncHttpClientConfig; import com.ning.http.client.async.ConnectionPoolTest; import com.ning.http.client.async.ProviderUtil; public class NettyConnectionPoolTest extends ConnectionPoolTest { @Override public AsyncHttpClient getAsyncHttpClient(AsyncHttpClientConfig config) { return ProviderUtil.nettyProvider(config); } } async-http-client-1.6.5/src/test/java/com/ning/http/client/async/netty/NettyDigestAuthTest.java000066400000000000000000000021671166553056000326130ustar00rootroot00000000000000/* * Copyright (c) 2010-2011 Sonatype, Inc. All rights reserved. * * This program is licensed to you under the Apache License Version 2.0, * and you may not use this file except in compliance with the Apache License Version 2.0. * You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0. * * Unless required by applicable law or agreed to in writing, * software distributed under the Apache License Version 2.0 is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. */ package com.ning.http.client.async.netty; import com.ning.http.client.AsyncHttpClient; import com.ning.http.client.AsyncHttpClientConfig; import com.ning.http.client.async.DigestAuthTest; import com.ning.http.client.async.ProviderUtil; public class NettyDigestAuthTest extends DigestAuthTest { @Override public AsyncHttpClient getAsyncHttpClient(AsyncHttpClientConfig config) { return ProviderUtil.nettyProvider(config); } } async-http-client-1.6.5/src/test/java/com/ning/http/client/async/netty/NettyEmptyBodyTest.java000066400000000000000000000021651166553056000324640ustar00rootroot00000000000000/* * Copyright (c) 2010-2011 Sonatype, Inc. All rights reserved. * * This program is licensed to you under the Apache License Version 2.0, * and you may not use this file except in compliance with the Apache License Version 2.0. * You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0. * * Unless required by applicable law or agreed to in writing, * software distributed under the Apache License Version 2.0 is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. */ package com.ning.http.client.async.netty; import com.ning.http.client.AsyncHttpClient; import com.ning.http.client.AsyncHttpClientConfig; import com.ning.http.client.async.EmptyBodyTest; import com.ning.http.client.async.ProviderUtil; public class NettyEmptyBodyTest extends EmptyBodyTest { @Override public AsyncHttpClient getAsyncHttpClient(AsyncHttpClientConfig config) { return ProviderUtil.nettyProvider(config); } } async-http-client-1.6.5/src/test/java/com/ning/http/client/async/netty/NettyErrorResponseTest.java000066400000000000000000000022011166553056000333470ustar00rootroot00000000000000/* * Copyright (c) 2010-2011 Sonatype, Inc. All rights reserved. * * This program is licensed to you under the Apache License Version 2.0, * and you may not use this file except in compliance with the Apache License Version 2.0. * You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0. * * Unless required by applicable law or agreed to in writing, * software distributed under the Apache License Version 2.0 is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. */ package com.ning.http.client.async.netty; import com.ning.http.client.AsyncHttpClient; import com.ning.http.client.AsyncHttpClientConfig; import com.ning.http.client.async.ErrorResponseTest; import com.ning.http.client.async.ProviderUtil; public class NettyErrorResponseTest extends ErrorResponseTest { @Override public AsyncHttpClient getAsyncHttpClient(AsyncHttpClientConfig config) { return ProviderUtil.nettyProvider(config); } } NettyExpect100ContinueTest.java000066400000000000000000000022151166553056000336430ustar00rootroot00000000000000async-http-client-1.6.5/src/test/java/com/ning/http/client/async/netty/* * Copyright (c) 2010-2011 Sonatype, Inc. All rights reserved. * * This program is licensed to you under the Apache License Version 2.0, * and you may not use this file except in compliance with the Apache License Version 2.0. * You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0. * * Unless required by applicable law or agreed to in writing, * software distributed under the Apache License Version 2.0 is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. */ package com.ning.http.client.async.netty; import com.ning.http.client.AsyncHttpClient; import com.ning.http.client.AsyncHttpClientConfig; import com.ning.http.client.async.Expect100ContinueTest; import com.ning.http.client.async.ProviderUtil; public class NettyExpect100ContinueTest extends Expect100ContinueTest { @Override public AsyncHttpClient getAsyncHttpClient(AsyncHttpClientConfig config) { return ProviderUtil.nettyProvider(config); } } NettyFilePartLargeFileTest.java000066400000000000000000000022141166553056000337450ustar00rootroot00000000000000async-http-client-1.6.5/src/test/java/com/ning/http/client/async/netty/* * Copyright (c) 2010-2011 Sonatype, Inc. All rights reserved. * * This program is licensed to you under the Apache License Version 2.0, * and you may not use this file except in compliance with the Apache License Version 2.0. * You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0. * * Unless required by applicable law or agreed to in writing, * software distributed under the Apache License Version 2.0 is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. */ package com.ning.http.client.async.netty; import com.ning.http.client.AsyncHttpClient; import com.ning.http.client.AsyncHttpClientConfig; import com.ning.http.client.async.FilePartLargeFileTest; import com.ning.http.client.async.ProviderUtil; public class NettyFilePartLargeFileTest extends FilePartLargeFileTest { @Override public AsyncHttpClient getAsyncHttpClient(AsyncHttpClientConfig config) { return ProviderUtil.nettyProvider(config); } } async-http-client-1.6.5/src/test/java/com/ning/http/client/async/netty/NettyFilterTest.java000066400000000000000000000021531166553056000317720ustar00rootroot00000000000000/* * Copyright (c) 2010-2011 Sonatype, Inc. All rights reserved. * * This program is licensed to you under the Apache License Version 2.0, * and you may not use this file except in compliance with the Apache License Version 2.0. * You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0. * * Unless required by applicable law or agreed to in writing, * software distributed under the Apache License Version 2.0 is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. */ package com.ning.http.client.async.netty; import com.ning.http.client.AsyncHttpClient; import com.ning.http.client.AsyncHttpClientConfig; import com.ning.http.client.async.FilterTest; import com.ning.http.client.async.ProviderUtil; public class NettyFilterTest extends FilterTest { @Override public AsyncHttpClient getAsyncHttpClient(AsyncHttpClientConfig config) { return ProviderUtil.nettyProvider(config); } } async-http-client-1.6.5/src/test/java/com/ning/http/client/async/netty/NettyFollowingThreadTest.java000066400000000000000000000022101166553056000336270ustar00rootroot00000000000000/* * Copyright (c) 2010-2011 Sonatype, Inc. All rights reserved. * * This program is licensed to you under the Apache License Version 2.0, * and you may not use this file except in compliance with the Apache License Version 2.0. * You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0. * * Unless required by applicable law or agreed to in writing, * software distributed under the Apache License Version 2.0 is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. */ package com.ning.http.client.async.netty; import com.ning.http.client.AsyncHttpClient; import com.ning.http.client.AsyncHttpClientConfig; import com.ning.http.client.async.FollowingThreadTest; import com.ning.http.client.async.ProviderUtil; public class NettyFollowingThreadTest extends FollowingThreadTest { @Override public AsyncHttpClient getAsyncHttpClient(AsyncHttpClientConfig config) { return ProviderUtil.nettyProvider(config); } } async-http-client-1.6.5/src/test/java/com/ning/http/client/async/netty/NettyHead302Test.java000066400000000000000000000021571166553056000316370ustar00rootroot00000000000000/* * Copyright (c) 2010-2011 Sonatype, Inc. All rights reserved. * * This program is licensed to you under the Apache License Version 2.0, * and you may not use this file except in compliance with the Apache License Version 2.0. * You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0. * * Unless required by applicable law or agreed to in writing, * software distributed under the Apache License Version 2.0 is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. */ package com.ning.http.client.async.netty; import com.ning.http.client.AsyncHttpClient; import com.ning.http.client.AsyncHttpClientConfig; import com.ning.http.client.async.Head302Test; import com.ning.http.client.async.ProviderUtil; public class NettyHead302Test extends Head302Test { @Override public AsyncHttpClient getAsyncHttpClient(AsyncHttpClientConfig config) { return ProviderUtil.nettyProvider(config); } } NettyHostnameVerifierTest.java000066400000000000000000000022121166553056000337340ustar00rootroot00000000000000async-http-client-1.6.5/src/test/java/com/ning/http/client/async/netty/* * Copyright (c) 2010-2011 Sonatype, Inc. All rights reserved. * * This program is licensed to you under the Apache License Version 2.0, * and you may not use this file except in compliance with the Apache License Version 2.0. * You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0. * * Unless required by applicable law or agreed to in writing, * software distributed under the Apache License Version 2.0 is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. */ package com.ning.http.client.async.netty; import com.ning.http.client.AsyncHttpClient; import com.ning.http.client.AsyncHttpClientConfig; import com.ning.http.client.async.HostnameVerifierTest; import com.ning.http.client.async.ProviderUtil; public class NettyHostnameVerifierTest extends HostnameVerifierTest { @Override public AsyncHttpClient getAsyncHttpClient(AsyncHttpClientConfig config) { return ProviderUtil.nettyProvider(config); } } NettyHttpToHttpsRedirectTest.java000066400000000000000000000022221166553056000344120ustar00rootroot00000000000000async-http-client-1.6.5/src/test/java/com/ning/http/client/async/netty/* * Copyright (c) 2010-2011 Sonatype, Inc. All rights reserved. * * This program is licensed to you under the Apache License Version 2.0, * and you may not use this file except in compliance with the Apache License Version 2.0. * You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0. * * Unless required by applicable law or agreed to in writing, * software distributed under the Apache License Version 2.0 is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. */ package com.ning.http.client.async.netty; import com.ning.http.client.AsyncHttpClient; import com.ning.http.client.AsyncHttpClientConfig; import com.ning.http.client.async.HttpToHttpsRedirectTest; import com.ning.http.client.async.ProviderUtil; public class NettyHttpToHttpsRedirectTest extends HttpToHttpsRedirectTest { @Override public AsyncHttpClient getAsyncHttpClient(AsyncHttpClientConfig config) { return ProviderUtil.nettyProvider(config); } } NettyIdleStateHandlerTest.java000066400000000000000000000022111166553056000336350ustar00rootroot00000000000000async-http-client-1.6.5/src/test/java/com/ning/http/client/async/netty/* * Copyright (c) 2010-2011 Sonatype, Inc. All rights reserved. * * This program is licensed to you under the Apache License Version 2.0, * and you may not use this file except in compliance with the Apache License Version 2.0. * You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0. * * Unless required by applicable law or agreed to in writing, * software distributed under the Apache License Version 2.0 is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. */ package com.ning.http.client.async.netty; import com.ning.http.client.AsyncHttpClient; import com.ning.http.client.AsyncHttpClientConfig; import com.ning.http.client.async.IdleStateHandlerTest; import com.ning.http.client.async.ProviderUtil; public class NettyIdleStateHandlerTest extends IdleStateHandlerTest { @Override public AsyncHttpClient getAsyncHttpClient(AsyncHttpClientConfig config) { return ProviderUtil.nettyProvider(config); } } async-http-client-1.6.5/src/test/java/com/ning/http/client/async/netty/NettyInputStreamTest.java000066400000000000000000000021721166553056000330210ustar00rootroot00000000000000/* * Copyright (c) 2010-2011 Sonatype, Inc. All rights reserved. * * This program is licensed to you under the Apache License Version 2.0, * and you may not use this file except in compliance with the Apache License Version 2.0. * You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0. * * Unless required by applicable law or agreed to in writing, * software distributed under the Apache License Version 2.0 is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. */ package com.ning.http.client.async.netty; import com.ning.http.client.AsyncHttpClient; import com.ning.http.client.AsyncHttpClientConfig; import com.ning.http.client.async.InputStreamTest; import com.ning.http.client.async.ProviderUtil; public class NettyInputStreamTest extends InputStreamTest { @Override public AsyncHttpClient getAsyncHttpClient(AsyncHttpClientConfig config) { return ProviderUtil.nettyProvider(config); } } NettyListenableFutureTest.java000066400000000000000000000022131166553056000337400ustar00rootroot00000000000000async-http-client-1.6.5/src/test/java/com/ning/http/client/async/netty/* * Copyright (c) 2010-2011 Sonatype, Inc. All rights reserved. * * This program is licensed to you under the Apache License Version 2.0, * and you may not use this file except in compliance with the Apache License Version 2.0. * You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0. * * Unless required by applicable law or agreed to in writing, * software distributed under the Apache License Version 2.0 is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. */ package com.ning.http.client.async.netty; import com.ning.http.client.AsyncHttpClient; import com.ning.http.client.AsyncHttpClientConfig; import com.ning.http.client.async.ListenableFutureTest; import com.ning.http.client.async.ProviderUtil; public class NettyListenableFutureTest extends ListenableFutureTest { @Override public AsyncHttpClient getAsyncHttpClient(AsyncHttpClientConfig config) { return ProviderUtil.nettyProvider(config); } } NettyMaxConnectionsInThreads.java000066400000000000000000000021741166553056000343630ustar00rootroot00000000000000async-http-client-1.6.5/src/test/java/com/ning/http/client/async/netty/******************************************************************************* * Copyright (c) 2010-2011 Sonatype, Inc. * 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.apache.org/licenses/LICENSE-2.0.html * You may elect to redistribute this code under either of these licenses. *******************************************************************************/ package com.ning.http.client.async.netty; import com.ning.http.client.AsyncHttpClient; import com.ning.http.client.AsyncHttpClientConfig; import com.ning.http.client.async.MaxConnectionsInThreads; import com.ning.http.client.async.ProviderUtil; public class NettyMaxConnectionsInThreads extends MaxConnectionsInThreads { @Override public AsyncHttpClient getAsyncHttpClient(AsyncHttpClientConfig config) { return ProviderUtil.nettyProvider(config); } } NettyMaxTotalConnectionTest.java000066400000000000000000000022171166553056000342400ustar00rootroot00000000000000async-http-client-1.6.5/src/test/java/com/ning/http/client/async/netty/* * Copyright (c) 2010-2011 Sonatype, Inc. All rights reserved. * * This program is licensed to you under the Apache License Version 2.0, * and you may not use this file except in compliance with the Apache License Version 2.0. * You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0. * * Unless required by applicable law or agreed to in writing, * software distributed under the Apache License Version 2.0 is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. */ package com.ning.http.client.async.netty; import com.ning.http.client.AsyncHttpClient; import com.ning.http.client.AsyncHttpClientConfig; import com.ning.http.client.async.MaxTotalConnectionTest; import com.ning.http.client.async.ProviderUtil; public class NettyMaxTotalConnectionTest extends MaxTotalConnectionTest { @Override public AsyncHttpClient getAsyncHttpClient(AsyncHttpClientConfig config) { return ProviderUtil.nettyProvider(config); } } async-http-client-1.6.5/src/test/java/com/ning/http/client/async/netty/NettyMultipartUploadTest.java000066400000000000000000000022451166553056000336750ustar00rootroot00000000000000/* * Copyright (c) 2010-2011 Sonatype, Inc. All rights reserved. * * This program is licensed to you under the Apache License Version 2.0, * and you may not use this file except in compliance with the Apache License Version 2.0. * You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0. * * Unless required by applicable law or agreed to in writing, * software distributed under the Apache License Version 2.0 is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. */ package com.ning.http.client.async.netty; import com.ning.http.client.AsyncHttpClient; import com.ning.http.client.AsyncHttpClientConfig; import com.ning.http.client.async.MultipartUploadTest; import com.ning.http.client.async.ProviderUtil; /** * @author dominict */ public class NettyMultipartUploadTest extends MultipartUploadTest { @Override public AsyncHttpClient getAsyncHttpClient(AsyncHttpClientConfig config) { return ProviderUtil.nettyProvider(config); } } async-http-client-1.6.5/src/test/java/com/ning/http/client/async/netty/NettyMultipleHeaderTest.java000066400000000000000000000022031166553056000334450ustar00rootroot00000000000000/* * Copyright (c) 2010-2011 Sonatype, Inc. All rights reserved. * * This program is licensed to you under the Apache License Version 2.0, * and you may not use this file except in compliance with the Apache License Version 2.0. * You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0. * * Unless required by applicable law or agreed to in writing, * software distributed under the Apache License Version 2.0 is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. */ package com.ning.http.client.async.netty; import com.ning.http.client.AsyncHttpClient; import com.ning.http.client.AsyncHttpClientConfig; import com.ning.http.client.async.MultipleHeaderTest; import com.ning.http.client.async.ProviderUtil; public class NettyMultipleHeaderTest extends MultipleHeaderTest { @Override public AsyncHttpClient getAsyncHttpClient(AsyncHttpClientConfig config) { return ProviderUtil.nettyProvider(config); } } async-http-client-1.6.5/src/test/java/com/ning/http/client/async/netty/NettyNoNullResponseTest.java000066400000000000000000000022031166553056000334670ustar00rootroot00000000000000/* * Copyright (c) 2010-2011 Sonatype, Inc. All rights reserved. * * This program is licensed to you under the Apache License Version 2.0, * and you may not use this file except in compliance with the Apache License Version 2.0. * You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0. * * Unless required by applicable law or agreed to in writing, * software distributed under the Apache License Version 2.0 is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. */ package com.ning.http.client.async.netty; import com.ning.http.client.AsyncHttpClient; import com.ning.http.client.AsyncHttpClientConfig; import com.ning.http.client.async.NoNullResponseTest; import com.ning.http.client.async.ProviderUtil; public class NettyNoNullResponseTest extends NoNullResponseTest { @Override public AsyncHttpClient getAsyncHttpClient(AsyncHttpClientConfig config) { return ProviderUtil.nettyProvider(config); } } NettyNonAsciiContentLengthTest.java000066400000000000000000000022151166553056000346650ustar00rootroot00000000000000async-http-client-1.6.5/src/test/java/com/ning/http/client/async/netty/* * Copyright (c) 2010-2011 Sonatype, Inc. All rights reserved. * * This program is licensed to you under the Apache License Version 2.0, * and you may not use this file except in compliance with the Apache License Version 2.0. * You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0. * * Unless required by applicable law or agreed to in writing, * software distributed under the Apache License Version 2.0 is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. */ package com.ning.http.client.async.netty; import com.ning.http.client.AsyncHttpClient; import com.ning.http.client.AsyncHttpClientConfig; import com.ning.http.client.async.NonAsciiContentLengthTest; import com.ning.http.client.async.ProviderUtil; public class NettyNonAsciiContentLengthTest extends NonAsciiContentLengthTest { @Override public AsyncHttpClient getAsyncHttpClient(AsyncHttpClientConfig config) { return ProviderUtil.nettyProvider(config); } } async-http-client-1.6.5/src/test/java/com/ning/http/client/async/netty/NettyParamEncodingTest.java000066400000000000000000000022001166553056000332450ustar00rootroot00000000000000/* * Copyright (c) 2010-2011 Sonatype, Inc. All rights reserved. * * This program is licensed to you under the Apache License Version 2.0, * and you may not use this file except in compliance with the Apache License Version 2.0. * You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0. * * Unless required by applicable law or agreed to in writing, * software distributed under the Apache License Version 2.0 is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. */ package com.ning.http.client.async.netty; import com.ning.http.client.AsyncHttpClient; import com.ning.http.client.AsyncHttpClientConfig; import com.ning.http.client.async.ParamEncodingTest; import com.ning.http.client.async.ProviderUtil; public class NettyParamEncodingTest extends ParamEncodingTest { @Override public AsyncHttpClient getAsyncHttpClient(AsyncHttpClientConfig config) { return ProviderUtil.nettyProvider(config); } } NettyPerRequestRelative302Test.java000066400000000000000000000022301166553056000345020ustar00rootroot00000000000000async-http-client-1.6.5/src/test/java/com/ning/http/client/async/netty/* * Copyright (c) 2010-2011 Sonatype, Inc. All rights reserved. * * This program is licensed to you under the Apache License Version 2.0, * and you may not use this file except in compliance with the Apache License Version 2.0. * You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0. * * Unless required by applicable law or agreed to in writing, * software distributed under the Apache License Version 2.0 is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. */ package com.ning.http.client.async.netty; import com.ning.http.client.AsyncHttpClient; import com.ning.http.client.AsyncHttpClientConfig; import com.ning.http.client.async.PerRequestRelative302Test; import com.ning.http.client.async.ProviderUtil; public class NettyPerRequestRelative302Test extends PerRequestRelative302Test { @Override public AsyncHttpClient getAsyncHttpClient(AsyncHttpClientConfig config) { return ProviderUtil.nettyProvider(config); } } NettyPerRequestTimeoutTest.java000066400000000000000000000022141166553056000341320ustar00rootroot00000000000000async-http-client-1.6.5/src/test/java/com/ning/http/client/async/netty/* * Copyright (c) 2010-2011 Sonatype, Inc. All rights reserved. * * This program is licensed to you under the Apache License Version 2.0, * and you may not use this file except in compliance with the Apache License Version 2.0. * You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0. * * Unless required by applicable law or agreed to in writing, * software distributed under the Apache License Version 2.0 is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. */ package com.ning.http.client.async.netty; import com.ning.http.client.AsyncHttpClient; import com.ning.http.client.AsyncHttpClientConfig; import com.ning.http.client.async.PerRequestTimeoutTest; import com.ning.http.client.async.ProviderUtil; public class NettyPerRequestTimeoutTest extends PerRequestTimeoutTest { @Override public AsyncHttpClient getAsyncHttpClient(AsyncHttpClientConfig config) { return ProviderUtil.nettyProvider(config); } } async-http-client-1.6.5/src/test/java/com/ning/http/client/async/netty/NettyPostWithQSTest.java000066400000000000000000000021671166553056000325770ustar00rootroot00000000000000/* * Copyright (c) 2010-2011 Sonatype, Inc. All rights reserved. * * This program is licensed to you under the Apache License Version 2.0, * and you may not use this file except in compliance with the Apache License Version 2.0. * You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0. * * Unless required by applicable law or agreed to in writing, * software distributed under the Apache License Version 2.0 is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. */ package com.ning.http.client.async.netty; import com.ning.http.client.AsyncHttpClient; import com.ning.http.client.AsyncHttpClientConfig; import com.ning.http.client.async.PostWithQSTest; import com.ning.http.client.async.ProviderUtil; public class NettyPostWithQSTest extends PostWithQSTest { @Override public AsyncHttpClient getAsyncHttpClient(AsyncHttpClientConfig config) { return ProviderUtil.nettyProvider(config); } } async-http-client-1.6.5/src/test/java/com/ning/http/client/async/netty/NettyProxyTest.java000066400000000000000000000021541166553056000316670ustar00rootroot00000000000000/* * Copyright (c) 2010-2011 Sonatype, Inc. All rights reserved. * * This program is licensed to you under the Apache License Version 2.0, * and you may not use this file except in compliance with the Apache License Version 2.0. * You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0. * * Unless required by applicable law or agreed to in writing, * software distributed under the Apache License Version 2.0 is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. */ package com.ning.http.client.async.netty; import com.ning.http.client.AsyncHttpClient; import com.ning.http.client.AsyncHttpClientConfig; import com.ning.http.client.async.ProviderUtil; import com.ning.http.client.async.ProxyTest; public class NettyProxyTest extends ProxyTest { @Override public AsyncHttpClient getAsyncHttpClient(AsyncHttpClientConfig config) { return ProviderUtil.nettyProvider(config); } } async-http-client-1.6.5/src/test/java/com/ning/http/client/async/netty/NettyProxyTunnellingTest.java000066400000000000000000000022101166553056000337200ustar00rootroot00000000000000/* * Copyright (c) 2010-2011 Sonatype, Inc. All rights reserved. * * This program is licensed to you under the Apache License Version 2.0, * and you may not use this file except in compliance with the Apache License Version 2.0. * You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0. * * Unless required by applicable law or agreed to in writing, * software distributed under the Apache License Version 2.0 is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. */ package com.ning.http.client.async.netty; import com.ning.http.client.AsyncHttpClient; import com.ning.http.client.AsyncHttpClientConfig; import com.ning.http.client.async.ProviderUtil; import com.ning.http.client.async.ProxyyTunnellingTest; public class NettyProxyTunnellingTest extends ProxyyTunnellingTest { @Override public AsyncHttpClient getAsyncHttpClient(AsyncHttpClientConfig config) { return ProviderUtil.nettyProvider(config); } } async-http-client-1.6.5/src/test/java/com/ning/http/client/async/netty/NettyPutLargeFileTest.java000066400000000000000000000021751166553056000330740ustar00rootroot00000000000000/* * Copyright (c) 2010-2011 Sonatype, Inc. All rights reserved. * * This program is licensed to you under the Apache License Version 2.0, * and you may not use this file except in compliance with the Apache License Version 2.0. * You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0. * * Unless required by applicable law or agreed to in writing, * software distributed under the Apache License Version 2.0 is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. */ package com.ning.http.client.async.netty; import com.ning.http.client.AsyncHttpClient; import com.ning.http.client.AsyncHttpClientConfig; import com.ning.http.client.async.ProviderUtil; import com.ning.http.client.async.PutLargeFileTest; public class NettyPutLargeFileTest extends PutLargeFileTest { @Override public AsyncHttpClient getAsyncHttpClient(AsyncHttpClientConfig config) { return ProviderUtil.nettyProvider(config); } } async-http-client-1.6.5/src/test/java/com/ning/http/client/async/netty/NettyQueryParametersTest.java000066400000000000000000000022061166553056000336750ustar00rootroot00000000000000/* * Copyright (c) 2010-2011 Sonatype, Inc. All rights reserved. * * This program is licensed to you under the Apache License Version 2.0, * and you may not use this file except in compliance with the Apache License Version 2.0. * You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0. * * Unless required by applicable law or agreed to in writing, * software distributed under the Apache License Version 2.0 is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. */ package com.ning.http.client.async.netty; import com.ning.http.client.AsyncHttpClient; import com.ning.http.client.AsyncHttpClientConfig; import com.ning.http.client.async.ProviderUtil; import com.ning.http.client.async.QueryParametersTest; public class NettyQueryParametersTest extends QueryParametersTest { @Override public AsyncHttpClient getAsyncHttpClient(AsyncHttpClientConfig config) { return ProviderUtil.nettyProvider(config); } } async-http-client-1.6.5/src/test/java/com/ning/http/client/async/netty/NettyRC10KTest.java000066400000000000000000000021501166553056000313220ustar00rootroot00000000000000/* * Copyright (c) 2010-2011 Sonatype, Inc. All rights reserved. * * This program is licensed to you under the Apache License Version 2.0, * and you may not use this file except in compliance with the Apache License Version 2.0. * You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0. * * Unless required by applicable law or agreed to in writing, * software distributed under the Apache License Version 2.0 is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. */ package com.ning.http.client.async.netty; import com.ning.http.client.AsyncHttpClient; import com.ning.http.client.AsyncHttpClientConfig; import com.ning.http.client.async.ProviderUtil; import com.ning.http.client.async.RC10KTest; public class NettyRC10KTest extends RC10KTest { @Override public AsyncHttpClient getAsyncHttpClient(AsyncHttpClientConfig config) { return ProviderUtil.nettyProvider(config); } } NettyRedirectConnectionUsageTest.java000066400000000000000000000022361166553056000352360ustar00rootroot00000000000000async-http-client-1.6.5/src/test/java/com/ning/http/client/async/netty/* * Copyright (c) 2010-2011 Sonatype, Inc. All rights reserved. * * This program is licensed to you under the Apache License Version 2.0, * and you may not use this file except in compliance with the Apache License Version 2.0. * You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0. * * Unless required by applicable law or agreed to in writing, * software distributed under the Apache License Version 2.0 is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. */ package com.ning.http.client.async.netty; import com.ning.http.client.AsyncHttpClient; import com.ning.http.client.AsyncHttpClientConfig; import com.ning.http.client.async.ProviderUtil; import com.ning.http.client.async.RedirectConnectionUsageTest; public class NettyRedirectConnectionUsageTest extends RedirectConnectionUsageTest { @Override public AsyncHttpClient getAsyncHttpClient(AsyncHttpClientConfig config) { return ProviderUtil.nettyProvider(config); } } async-http-client-1.6.5/src/test/java/com/ning/http/client/async/netty/NettyRelative302Test.java000066400000000000000000000021731166553056000325470ustar00rootroot00000000000000/* * Copyright (c) 2010-2011 Sonatype, Inc. All rights reserved. * * This program is licensed to you under the Apache License Version 2.0, * and you may not use this file except in compliance with the Apache License Version 2.0. * You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0. * * Unless required by applicable law or agreed to in writing, * software distributed under the Apache License Version 2.0 is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. */ package com.ning.http.client.async.netty; import com.ning.http.client.AsyncHttpClient; import com.ning.http.client.AsyncHttpClientConfig; import com.ning.http.client.async.ProviderUtil; import com.ning.http.client.async.Relative302Test; public class NettyRelative302Test extends Relative302Test { @Override public AsyncHttpClient getAsyncHttpClient(AsyncHttpClientConfig config) { return ProviderUtil.nettyProvider(config); } } async-http-client-1.6.5/src/test/java/com/ning/http/client/async/netty/NettyRemoteSiteTest.java000066400000000000000000000020531166553056000326240ustar00rootroot00000000000000/* * Copyright 2010 Ning, Inc. * * Ning licenses this file to you 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. */ package com.ning.http.client.async.netty; import com.ning.http.client.AsyncHttpClient; import com.ning.http.client.AsyncHttpClientConfig; import com.ning.http.client.async.ProviderUtil; import com.ning.http.client.async.RemoteSiteTest; public class NettyRemoteSiteTest extends RemoteSiteTest { @Override public AsyncHttpClient getAsyncHttpClient(AsyncHttpClientConfig config) { return ProviderUtil.nettyProvider(config); } } async-http-client-1.6.5/src/test/java/com/ning/http/client/async/netty/NettyRetryRequestTest.java000066400000000000000000000020571166553056000332260ustar00rootroot00000000000000/* * Copyright 2010 Ning, Inc. * * Ning licenses this file to you 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. */ package com.ning.http.client.async.netty; import com.ning.http.client.AsyncHttpClient; import com.ning.http.client.AsyncHttpClientConfig; import com.ning.http.client.async.ProviderUtil; import com.ning.http.client.async.RetryRequestTest; public class NettyRetryRequestTest extends RetryRequestTest{ @Override public AsyncHttpClient getAsyncHttpClient(AsyncHttpClientConfig config) { return ProviderUtil.nettyProvider(config); } } NettySimpleAsyncHttpClientTest.java000066400000000000000000000023101166553056000347070ustar00rootroot00000000000000async-http-client-1.6.5/src/test/java/com/ning/http/client/async/netty/* * Copyright (c) 2010-2011 Sonatype, Inc. All rights reserved. * * This program is licensed to you under the Apache License Version 2.0, * and you may not use this file except in compliance with the Apache License Version 2.0. * You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0. * * Unless required by applicable law or agreed to in writing, * software distributed under the Apache License Version 2.0 is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. */ package com.ning.http.client.async.netty; import com.ning.http.client.AsyncHttpClient; import com.ning.http.client.AsyncHttpClientConfig; import com.ning.http.client.async.SimpleAsyncHttpClientTest; public class NettySimpleAsyncHttpClientTest extends SimpleAsyncHttpClientTest { /** * Not Used with {@link com.ning.http.client.SimpleAsyncHttpClient} * @param config * @return */ @Override public AsyncHttpClient getAsyncHttpClient(AsyncHttpClientConfig config) { return null; } } NettyTransferListenerTest.java000066400000000000000000000022111166553056000337530ustar00rootroot00000000000000async-http-client-1.6.5/src/test/java/com/ning/http/client/async/netty/* * Copyright (c) 2010-2011 Sonatype, Inc. All rights reserved. * * This program is licensed to you under the Apache License Version 2.0, * and you may not use this file except in compliance with the Apache License Version 2.0. * You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0. * * Unless required by applicable law or agreed to in writing, * software distributed under the Apache License Version 2.0 is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. */ package com.ning.http.client.async.netty; import com.ning.http.client.AsyncHttpClient; import com.ning.http.client.AsyncHttpClientConfig; import com.ning.http.client.async.ProviderUtil; import com.ning.http.client.async.TransferListenerTest; public class NettyTransferListenerTest extends TransferListenerTest { @Override public AsyncHttpClient getAsyncHttpClient(AsyncHttpClientConfig config) { return ProviderUtil.nettyProvider(config); } } async-http-client-1.6.5/src/test/java/com/ning/http/client/async/netty/NettyWebDavBasicTest.java000066400000000000000000000021721166553056000326600ustar00rootroot00000000000000/* * Copyright (c) 2010-2011 Sonatype, Inc. All rights reserved. * * This program is licensed to you under the Apache License Version 2.0, * and you may not use this file except in compliance with the Apache License Version 2.0. * You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0. * * Unless required by applicable law or agreed to in writing, * software distributed under the Apache License Version 2.0 is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. */ package com.ning.http.client.async.netty; import com.ning.http.client.AsyncHttpClient; import com.ning.http.client.AsyncHttpClientConfig; import com.ning.http.client.async.ProviderUtil; import com.ning.http.client.async.WebDavBasicTest; public class NettyWebDavBasicTest extends WebDavBasicTest { @Override public AsyncHttpClient getAsyncHttpClient(AsyncHttpClientConfig config) { return ProviderUtil.nettyProvider(config); } } async-http-client-1.6.5/src/test/java/com/ning/http/client/async/netty/NettyZeroCopyFileTest.java000066400000000000000000000022651166553056000331230ustar00rootroot00000000000000/* * Copyright (c) 2010-2011 Sonatype, Inc. All rights reserved. * * This program is licensed to you under the Apache License Version 2.0, * and you may not use this file except in compliance with the Apache License Version 2.0. * You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0. * * Unless required by applicable law or agreed to in writing, * software distributed under the Apache License Version 2.0 is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. */ package com.ning.http.client.async.netty; import com.ning.http.client.AsyncHttpClient; import com.ning.http.client.AsyncHttpClientConfig; import com.ning.http.client.async.ProviderUtil; import com.ning.http.client.async.TransferListenerTest; import com.ning.http.client.async.ZeroCopyFileTest; public class NettyZeroCopyFileTest extends ZeroCopyFileTest { @Override public AsyncHttpClient getAsyncHttpClient(AsyncHttpClientConfig config) { return ProviderUtil.nettyProvider(config); } } async-http-client-1.6.5/src/test/java/com/ning/http/client/oauth/000077500000000000000000000000001166553056000246555ustar00rootroot00000000000000async-http-client-1.6.5/src/test/java/com/ning/http/client/oauth/TestSignatureCalculator.java000066400000000000000000000036311166553056000323360ustar00rootroot00000000000000/* * Copyright 2010 Ning, Inc. * * Ning licenses this file to you 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. */ package com.ning.http.client.oauth; import org.testng.Assert; import org.testng.annotations.Test; import com.ning.http.client.FluentStringsMap; public class TestSignatureCalculator { private static final String CONSUMER_KEY = "dpf43f3p2l4k3l03"; private static final String CONSUMER_SECRET = "kd94hf93k423kf44"; public static final String TOKEN_KEY = "nnch734d00sl2jdk"; public static final String TOKEN_SECRET = "pfkkdhi9sl3r4s00"; public static final String NONCE = "kllo9940pd9333jh"; final static long TIMESTAMP = 1191242096; // based on the reference test case from // http://oauth.pbwiki.com/TestCases @Test(groups="fast") public void test() { ConsumerKey consumer = new ConsumerKey(CONSUMER_KEY, CONSUMER_SECRET); RequestToken user = new RequestToken(TOKEN_KEY, TOKEN_SECRET); OAuthSignatureCalculator calc = new OAuthSignatureCalculator(consumer, user); FluentStringsMap queryParams = new FluentStringsMap(); queryParams.add("file", "vacation.jpg"); queryParams.add("size", "original"); String url = "http://photos.example.net/photos"; String sig = calc.calculateSignature("GET", url, TIMESTAMP, NONCE, null, queryParams); Assert.assertEquals("tR3+Ty81lMeYAr/Fid0kMTYa/WM=", sig); } } async-http-client-1.6.5/src/test/java/com/ning/http/client/providers/000077500000000000000000000000001166553056000255525ustar00rootroot00000000000000async-http-client-1.6.5/src/test/java/com/ning/http/client/providers/netty/000077500000000000000000000000001166553056000267155ustar00rootroot00000000000000NettyAsyncResponseTest.java000066400000000000000000000072061166553056000341660ustar00rootroot00000000000000async-http-client-1.6.5/src/test/java/com/ning/http/client/providers/netty/* * Copyright (c) 2010-2011 Sonatype, Inc. All rights reserved. * * This program is licensed to you under the Apache License Version 2.0, * and you may not use this file except in compliance with the Apache License Version 2.0. * You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0. * * Unless required by applicable law or agreed to in writing, * software distributed under the Apache License Version 2.0 is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. */ package com.ning.http.client.providers.netty; import com.ning.http.client.Cookie; import com.ning.http.client.FluentCaseInsensitiveStringsMap; import com.ning.http.client.HttpResponseHeaders; import org.testng.annotations.Test; import java.text.SimpleDateFormat; import java.util.Date; import java.util.List; import java.util.Locale; import java.util.TimeZone; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertTrue; /** * @author Benjamin Hanzelmann */ public class NettyAsyncResponseTest { @Test(groups = "standalone") public void testCookieParseExpires() { // e.g. "Sun, 06-Feb-2011 03:45:24 GMT"; SimpleDateFormat sdf = new SimpleDateFormat("EEE, dd-MMM-yyyy HH:mm:ss z", Locale.US); sdf.setTimeZone(TimeZone.getTimeZone("GMT")); Date date = new Date(System.currentTimeMillis() + 60000); // sdf.parse( dateString ); final String cookieDef = String.format("efmembercheck=true; expires=%s; path=/; domain=.eclipse.org", sdf.format(date)); NettyResponse response = new NettyResponse(new ResponseStatus(null, null, null), new HttpResponseHeaders(null, null, false) { @Override public FluentCaseInsensitiveStringsMap getHeaders() { return new FluentCaseInsensitiveStringsMap().add("Set-Cookie", cookieDef); } }, null); List cookies = response.getCookies(); assertEquals(cookies.size(), 1); Cookie cookie = cookies.get(0); assertTrue(cookie.getMaxAge() > 55 && cookie.getMaxAge() < 61, ""); } @Test(groups = "standalone") public void testCookieParseMaxAge() { final String cookieDef = "efmembercheck=true; max-age=60; path=/; domain=.eclipse.org"; NettyResponse response = new NettyResponse(new ResponseStatus(null, null, null), new HttpResponseHeaders(null, null, false) { @Override public FluentCaseInsensitiveStringsMap getHeaders() { return new FluentCaseInsensitiveStringsMap().add("Set-Cookie", cookieDef); } }, null); List cookies = response.getCookies(); assertEquals(cookies.size(), 1); Cookie cookie = cookies.get(0); assertEquals(cookie.getMaxAge(), 60); } @Test(groups = "standalone") public void testCookieParseWeirdExpiresValue() { final String cookieDef = "efmembercheck=true; expires=60; path=/; domain=.eclipse.org"; NettyResponse response = new NettyResponse(new ResponseStatus(null, null, null), new HttpResponseHeaders(null, null, false) { @Override public FluentCaseInsensitiveStringsMap getHeaders() { return new FluentCaseInsensitiveStringsMap().add("Set-Cookie", cookieDef); } }, null); List cookies = response.getCookies(); assertEquals(cookies.size(), 1); Cookie cookie = cookies.get(0); assertEquals(cookie.getMaxAge(), 60); } } async-http-client-1.6.5/src/test/java/com/ning/http/client/resumable/000077500000000000000000000000001166553056000255145ustar00rootroot00000000000000async-http-client-1.6.5/src/test/java/com/ning/http/client/resumable/MapResumableProcessor.java000066400000000000000000000012641166553056000326370ustar00rootroot00000000000000package com.ning.http.client.resumable; import com.ning.http.client.resumable.ResumableAsyncHandler.ResumableProcessor; import java.util.HashMap; import java.util.Map; /** * @author Benjamin Hanzelmann */ public class MapResumableProcessor implements ResumableProcessor { Map map = new HashMap(); public void put(String key, long transferredBytes) { map.put(key, transferredBytes); } public void remove(String key) { map.remove(key); } /** * NOOP */ public void save(Map map) { } /** * NOOP */ public Map load() { return map; } }PropertiesBasedResumableProcesserTest.java000066400000000000000000000027451166553056000357710ustar00rootroot00000000000000async-http-client-1.6.5/src/test/java/com/ning/http/client/resumablepackage com.ning.http.client.resumable; /* * Copyright (c) 2010 Sonatype, Inc. All rights reserved. * * This program is licensed to you under the Apache License Version 2.0, * and you may not use this file except in compliance with the Apache License Version 2.0. * You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0. * * Unless required by applicable law or agreed to in writing, * software distributed under the Apache License Version 2.0 is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. */ import org.testng.annotations.Test; import java.util.Map; import static org.testng.Assert.assertEquals; /** * @author Benjamin Hanzelmann */ public class PropertiesBasedResumableProcesserTest { @Test public void testSaveLoad() throws Exception { PropertiesBasedResumableProcessor p = new PropertiesBasedResumableProcessor(); p.put("http://localhost/test.url", 15L); p.put("http://localhost/test2.url", 50L); p.save(null); p = new PropertiesBasedResumableProcessor(); Map m = p.load(); assertEquals(m.size(), 2); assertEquals(m.get("http://localhost/test.url"), Long.valueOf(15L)); assertEquals(m.get("http://localhost/test2.url"), Long.valueOf(50L)); } } async-http-client-1.6.5/src/test/java/com/ning/http/client/resumable/ResumableAsyncHandlerTest.java000066400000000000000000000035141166553056000334350ustar00rootroot00000000000000package com.ning.http.client.resumable; /* * Copyright (c) 2010 Sonatype, Inc. All rights reserved. * * This program is licensed to you under the Apache License Version 2.0, * and you may not use this file except in compliance with the Apache License Version 2.0. * You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0. * * Unless required by applicable law or agreed to in writing, * software distributed under the Apache License Version 2.0 is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. */ import com.ning.http.client.Request; import com.ning.http.client.RequestBuilder; import com.ning.http.client.Response; import org.testng.annotations.Test; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertNull; /** * @author Benjamin Hanzelmann */ public class ResumableAsyncHandlerTest { @Test public void testAdjustRange() { MapResumableProcessor proc = new MapResumableProcessor(); ResumableAsyncHandler h = new ResumableAsyncHandler(proc); Request request = new RequestBuilder("GET").setUrl("http://test/url").build(); Request newRequest = h.adjustRequestRange(request); assertEquals(newRequest.getUrl(), request.getUrl()); String rangeHeader = newRequest.getHeaders().getFirstValue("Range"); assertNull(rangeHeader); proc.put("http://test/url", 5000); newRequest = h.adjustRequestRange(request); assertEquals(newRequest.getUrl(), request.getUrl()); rangeHeader = newRequest.getHeaders().getFirstValue("Range"); assertEquals(rangeHeader, "bytes=5000-"); } } async-http-client-1.6.5/src/test/java/com/ning/http/util/000077500000000000000000000000001166553056000232345ustar00rootroot00000000000000async-http-client-1.6.5/src/test/java/com/ning/http/util/ProxyUtilsTest.java000066400000000000000000000042071166553056000271040ustar00rootroot00000000000000/* * Copyright (c) 2010-2011 Sonatype, Inc. All rights reserved. * * This program is licensed to you under the Apache License Version 2.0, * and you may not use this file except in compliance with the Apache License Version 2.0. * You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0. * * Unless required by applicable law or agreed to in writing, * software distributed under the Apache License Version 2.0 is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. */ package com.ning.http.util; import com.ning.http.client.ProxyServer; import com.ning.http.client.Request; import com.ning.http.client.RequestBuilder; import org.testng.Assert; import org.testng.annotations.Test; public class ProxyUtilsTest { @Test(groups = "fast") public void testBasics() { ProxyServer proxyServer; Request req; // should avoid, there is no proxy (is null) req = new RequestBuilder("GET").setUrl("http://somewhere.com/foo").build(); Assert.assertTrue(ProxyUtils.avoidProxy(null, req)); // should avoid, it's in non-proxy hosts req = new RequestBuilder("GET").setUrl("http://somewhere.com/foo").build(); proxyServer = new ProxyServer("foo", 1234); proxyServer.addNonProxyHost("somewhere.com"); Assert.assertTrue(ProxyUtils.avoidProxy(proxyServer, req)); // should avoid, it's in non-proxy hosts (with "*") req = new RequestBuilder("GET").setUrl("http://sub.somewhere.com/foo").build(); proxyServer = new ProxyServer("foo", 1234); proxyServer.addNonProxyHost("*.somewhere.com"); Assert.assertTrue(ProxyUtils.avoidProxy(proxyServer, req)); // should use it req = new RequestBuilder("GET").setUrl("http://sub.somewhere.com/foo").build(); proxyServer = new ProxyServer("foo", 1234); proxyServer.addNonProxyHost("*.somewhere.org"); Assert.assertFalse(ProxyUtils.avoidProxy(proxyServer, req)); } } async-http-client-1.6.5/src/test/java/com/ning/http/util/TestUTF8UrlCodec.java000066400000000000000000000017721166553056000271150ustar00rootroot00000000000000/* * Copyright 2010 Ning, Inc. * * Ning licenses this file to you 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. */ package com.ning.http.util; import org.testng.Assert; import org.testng.annotations.Test; public class TestUTF8UrlCodec { @Test(groups="fast") public void testBasics() { Assert.assertEquals(UTF8UrlEncoder.encode("foobar"), "foobar"); Assert.assertEquals(UTF8UrlEncoder.encode("a&b"), "a%26b"); Assert.assertEquals(UTF8UrlEncoder.encode("a+b"), "a%2Bb"); } }