├── .gitignore ├── README.md ├── pom.xml └── src ├── main └── java │ └── org │ └── sonatype │ └── spice │ └── jersey │ └── client │ └── ahc │ ├── AhcClientHandler.java │ ├── AhcHttpClient.java │ ├── AhcRequestWriter.java │ └── config │ ├── AhcConfig.java │ └── DefaultAhcConfig.java └── test ├── java └── org │ └── sonatype │ └── spice │ └── jersey │ └── client │ └── ahc │ └── tests │ └── tests │ ├── AbstractGrizzlyServerTester.java │ ├── AuthTest.java │ ├── CookieTest.java │ ├── GZIPContentEncodingTest.java │ ├── HttpHeadersTest.java │ ├── HttpMethodTest.java │ ├── HttpMethodWithClientFilterTest.java │ └── NoEntityTest.java └── resources └── logback-test.xml /.gitignore: -------------------------------------------------------------------------------- 1 | ###################### 2 | # Logs 3 | ###################### 4 | *.log 5 | /logs 6 | 7 | ###################### 8 | # Build output directies 9 | ###################### 10 | /target 11 | */target 12 | /build 13 | */build 14 | test-output 15 | *.class 16 | *~ 17 | .*.swp 18 | .*.swo 19 | .loadpath 20 | .buildpath 21 | 22 | ###################### 23 | # Eclipse specific files/directories 24 | ###################### 25 | .classpath 26 | .project 27 | .settings 28 | .metadata 29 | 30 | ###################### 31 | # IntelliJ specific files/directories 32 | ###################### 33 | out 34 | .idea 35 | *.iml 36 | *.ipr 37 | *.iws 38 | *.iml 39 | atlassian-ide-plugin.xml 40 | nbproject 41 | /META-INF/MANIFEST.MF 42 | 43 | ###################### 44 | # OS generated files 45 | ###################### 46 | .DS_Store* 47 | ehthumbs.db 48 | Icon? 49 | Thumbs.db 50 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ### An AsyncHttpClient transport for the [Jersey Client API](http://jersey.java.net/nonav/documentation/latest/client-api.html). 2 | 3 | The Jersey Async HTTP Client library is simple to use. Add it to your Maven project, simply add this dependency: 4 | 5 | ```xml 6 | 7 | org.jfarcand 8 | jersey-ahc-client 9 | 1.0.5 10 | 11 | ``` 12 | 13 | Keep up to date on the library development by joining the Asynchronous HTTP Client discussion group 14 | 15 | [Google Group](http://groups.google.com/group/asynchttpclient) 16 | 17 | or follow us on [Twitter](http://twitter.com/jfarcand) 18 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 14 | 15 | 16 | 17 | org.sonatype.oss 18 | oss-parent 19 | 5 20 | 21 | 4.0.0 22 | org.jfarcand 23 | jersey-ahc-client 24 | jersey-ahc-client 25 | 1.0.6-SNAPSHOT 26 | jar 27 | 28 | Async Http Client implementation for the Jersey Client API. 29 | 30 | http://github.com/AsyncHttpClient/jersey-ahc-client 31 | 32 | scm:git:git@github.com:AsyncHttpClient/jersey-ahc-client.git 33 | scm:git:git@github.com:AsyncHttpClient/jersey-ahc-client.git 34 | scm:git:git@github.com:AsyncHttpClient/jersey-ahc-client.git 35 | 36 | 37 | 2.0.9 38 | 39 | 40 | 41 | jfarcand 42 | Jeanfrancois Arcand 43 | jfarcand@apache.org 44 | 45 | 46 | simonetripodi 47 | Simone Tripodi 48 | simonetripodi@apache.org 49 | 50 | 51 | 52 | 53 | Eclipse Public License, Version 1.0 54 | http://www.eclipse.org/legal/epl-v10.html 55 | repo 56 | 57 | 58 | Apache License, Version 2.0 59 | http://www.apache.org/licenses/LICENSE-2.0.txt 60 | repo 61 | 62 | 63 | 64 | 1.14 65 | 1.8.5 66 | 3.9.0.Final 67 | 68 | 69 | 70 | com.sun.jersey 71 | jersey-client 72 | ${jersey.version} 73 | 74 | 75 | com.sun.jersey 76 | jersey-json 77 | ${jersey.version} 78 | 79 | 80 | javax.ws.rs 81 | jsr311-api 82 | 1.1.1 83 | provided 84 | 85 | 86 | com.ning 87 | async-http-client 88 | ${async-http-client-version} 89 | 90 | 91 | com.sun.xml.bind 92 | jaxb-impl 93 | 2.2.3-1 94 | test 95 | 96 | 97 | ch.qos.logback 98 | logback-classic 99 | 0.9.26 100 | test 101 | 102 | 103 | com.sun.grizzly 104 | grizzly-servlet-webserver 105 | 1.9.18-i 106 | test 107 | 108 | 109 | junit 110 | junit 111 | 4.10 112 | test 113 | 114 | 115 | com.sun.jersey 116 | jersey-server 117 | ${jersey.version} 118 | test 119 | 120 | 121 | com.sun.jersey 122 | jersey-bundle 123 | ${jersey.version} 124 | test 125 | 126 | 127 | io.netty 128 | netty 129 | ${netty-version} 130 | 131 | 132 | 133 | install 134 | 135 | 136 | org.codehaus.mojo 137 | animal-sniffer-maven-plugin 138 | 139 | 140 | org.codehaus.mojo.signature 141 | java15 142 | 1.0 143 | 144 | 145 | 146 | 147 | check-java-1.5-compat 148 | process-classes 149 | 150 | check 151 | 152 | 153 | 154 | 155 | 156 | org.apache.felix 157 | maven-bundle-plugin 158 | true 159 | 2.4.0 160 | 161 | META-INF 162 | 163 | Sonatype 164 | 165 | com.sun.jersey.*;resolution:=optional, 166 | * 167 | 168 | 169 | org.sonatype.spice.jersey.client.ahc.*;version="1.0.0" 170 | 171 | 172 | 173 | 174 | 175 | osgi-bundle 176 | package 177 | 178 | bundle 179 | 180 | 181 | 182 | 183 | 184 | org.apache.maven.plugins 185 | maven-enforcer-plugin 186 | 187 | 188 | enforce-versions 189 | 190 | enforce 191 | 192 | 193 | 194 | 195 | 2.0.9 196 | 197 | 198 | 1.5 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | org.apache.maven.plugins 207 | maven-compiler-plugin 208 | 2.0.2 209 | 210 | 1.6 211 | 1.6 212 | 1.6 213 | 1024m 214 | 215 | 216 | 217 | org.apache.maven.plugins 218 | maven-jar-plugin 219 | 220 | 221 | 222 | test-jar 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | -------------------------------------------------------------------------------- /src/main/java/org/sonatype/spice/jersey/client/ahc/AhcClientHandler.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2010-2011 Sonatype, Inc. 3 | * All rights reserved. This program and the accompanying materials 4 | * are made available under the terms of the Eclipse Public License v1.0 5 | * and Apache License v2.0 which accompanies this distribution. 6 | * The Eclipse Public License is available at 7 | * http://www.eclipse.org/legal/epl-v10.html 8 | * The Apache License v2.0 is available at 9 | * http://www.apache.org/licenses/LICENSE-2.0.html 10 | * You may elect to redistribute this code under either of these licenses. 11 | *******************************************************************************/ 12 | package org.sonatype.spice.jersey.client.ahc; 13 | 14 | import java.util.ArrayList; 15 | import java.util.Iterator; 16 | import java.util.List; 17 | import java.util.Map; 18 | 19 | import javax.ws.rs.core.Context; 20 | 21 | import org.sonatype.spice.jersey.client.ahc.config.AhcConfig; 22 | import org.sonatype.spice.jersey.client.ahc.config.DefaultAhcConfig; 23 | 24 | import com.ning.http.client.AsyncHttpClient; 25 | import com.ning.http.client.FluentCaseInsensitiveStringsMap; 26 | import com.ning.http.client.RequestBuilder; 27 | import com.ning.http.client.Response; 28 | import com.ning.http.client.cookie.Cookie; 29 | import com.sun.jersey.api.client.ClientHandler; 30 | import com.sun.jersey.api.client.ClientHandlerException; 31 | import com.sun.jersey.api.client.ClientRequest; 32 | import com.sun.jersey.api.client.ClientResponse; 33 | import com.sun.jersey.core.header.InBoundHeaders; 34 | import com.sun.jersey.spi.MessageBodyWorkers; 35 | 36 | /** 37 | * A root handler with Sonatype AsyncHttpClient acting as a backend. 38 | *

39 | * Client operations are thread safe, the HTTP connection may 40 | * be shared between different threads. 41 | *

42 | * If a response entity is obtained that is an instance of {@link java.io.Closeable} 43 | * then the instance MUST be closed after processing the entity to release 44 | * connection-based resources. 45 | *

46 | * If a {@link ClientResponse} is obtained and an entity is not read from the 47 | * response then {@link ClientResponse#close() } MUST be called after processing 48 | * the response to release connection-based resources. 49 | *

50 | * The following methods are currently supported: HEAD, GET, POST, PUT, DELETE, TRACE 51 | * OPTIONS as well as custom methods. 52 | *

53 | * 54 | * @author Jeanfrancois Arcand 55 | */ 56 | public final class AhcClientHandler implements ClientHandler { 57 | 58 | private final AsyncHttpClient client; 59 | 60 | private final AhcConfig config; 61 | 62 | private final AhcRequestWriter requestWriter = new AhcRequestWriter(); 63 | 64 | private final List cookies = new ArrayList(); 65 | 66 | @Context 67 | private MessageBodyWorkers workers; 68 | 69 | /** 70 | * Create a new root handler with an {@link AsyncHttpClient}. 71 | * 72 | * @param client the {@link AsyncHttpClient}. 73 | */ 74 | public AhcClientHandler(final AsyncHttpClient client) { 75 | this(client, new DefaultAhcConfig()); 76 | } 77 | 78 | /** 79 | * Create a new root handler with an {@link AsyncHttpClient}. 80 | * 81 | * @param client the {@link AsyncHttpClient}. 82 | * @param config the client configuration. 83 | */ 84 | public AhcClientHandler(final AsyncHttpClient client, final AhcConfig config) { 85 | this.client = client; 86 | this.config = config; 87 | } 88 | 89 | /** 90 | * Get the client config. 91 | * 92 | * @return the client config. 93 | */ 94 | public AhcConfig getConfig() { 95 | return config; 96 | } 97 | 98 | /** 99 | * Get the {@link AsyncHttpClient}. 100 | * 101 | * @return the {@link AsyncHttpClient}. 102 | */ 103 | public AsyncHttpClient getHttpClient() { 104 | return client; 105 | } 106 | 107 | /** 108 | * Translate the {@link ClientRequest} into a AsyncHttpClient request, and execute it. 109 | * 110 | * @param cr the HTTP request. 111 | * @return the {@link ClientResponse} 112 | * @throws ClientHandlerException 113 | */ 114 | @Override 115 | public ClientResponse handle(final ClientRequest cr) 116 | throws ClientHandlerException { 117 | 118 | try { 119 | final RequestBuilder requestBuilder = getRequestBuilder(cr); 120 | handleCookie(requestBuilder); 121 | requestWriter.configureRequest(requestBuilder, cr, allowBody(cr.getMethod())); 122 | 123 | final Response response = client.executeRequest(requestBuilder.build()).get(); 124 | 125 | applyResponseCookies(response.getCookies()); 126 | 127 | final ClientResponse r = new ClientResponse(response.getStatusCode(), 128 | getInBoundHeaders(response), 129 | response.getResponseBodyAsStream(), 130 | workers); 131 | if (!r.hasEntity()) { 132 | r.bufferEntity(); 133 | r.close(); 134 | } 135 | return r; 136 | } catch (final Exception e) { 137 | throw new ClientHandlerException(e); 138 | } 139 | } 140 | 141 | /** 142 | * append request cookies and override existing cookies 143 | * 144 | * @param responseCookies list of cookies from response 145 | */ 146 | private void applyResponseCookies(final List responseCookies) { 147 | if (responseCookies != null) { 148 | for (final Cookie rc : responseCookies) { 149 | // remove existing cookie 150 | final Iterator it = cookies.iterator(); 151 | while (it.hasNext()) { 152 | final Cookie c = it.next(); 153 | if (isSame(rc, c)) { 154 | it.remove(); 155 | break; 156 | } 157 | } 158 | // add new cookie 159 | cookies.add(rc); 160 | } 161 | } 162 | } 163 | 164 | private boolean isSame(final Cookie c, final Cookie o) { 165 | return isEquals(c.getDomain(), o.getDomain()) && 166 | isEquals(c.getPath(), o.getPath()) && 167 | isEquals(c.getName(), o.getName()); 168 | } 169 | 170 | private boolean isEquals(final Object o, final Object o2) { 171 | return (o == null && o2 == null) || o != null && o.equals(o2); 172 | } 173 | 174 | /** 175 | * Check if a body needs to be constructed based on a method's name. 176 | * 177 | * @param method An HTTP method 178 | * @return true if s body can be allowed. 179 | */ 180 | private boolean allowBody(final String method) { 181 | if (method.equalsIgnoreCase("GET") || method.equalsIgnoreCase("OPTIONS") 182 | && method.equalsIgnoreCase("TRACE") 183 | && method.equalsIgnoreCase("HEAD")) { 184 | return false; 185 | } else { 186 | return true; 187 | } 188 | } 189 | 190 | /** 191 | * Return the {@link RequestBuilder} based on a method 192 | * 193 | * @param cr the HTTP request. 194 | * @return {@link RequestBuilder} 195 | */ 196 | private RequestBuilder getRequestBuilder(final ClientRequest cr) { 197 | final String strMethod = cr.getMethod(); 198 | final String uri = cr.getURI().toString(); 199 | 200 | if (strMethod.equals("GET")) { 201 | return new RequestBuilder("GET").setUrl(uri); 202 | } else if (strMethod.equals("POST")) { 203 | return new RequestBuilder("POST").setUrl(uri); 204 | } else if (strMethod.equals("PUT")) { 205 | return new RequestBuilder("PUT").setUrl(uri); 206 | } else if (strMethod.equals("DELETE")) { 207 | return new RequestBuilder("DELETE").setUrl(uri); 208 | } else if (strMethod.equals("HEAD")) { 209 | return new RequestBuilder("HEAD").setUrl(uri); 210 | } else if (strMethod.equals("OPTIONS")) { 211 | return new RequestBuilder("OPTIONS").setUrl(uri); 212 | } else { 213 | return new RequestBuilder(strMethod).setUrl(uri); 214 | } 215 | } 216 | 217 | private InBoundHeaders getInBoundHeaders(final Response response) { 218 | final InBoundHeaders headers = new InBoundHeaders(); 219 | final FluentCaseInsensitiveStringsMap respHeaders = response.getHeaders(); 220 | for (final Map.Entry> header : respHeaders) { 221 | headers.put(header.getKey(), header.getValue()); 222 | } 223 | return headers; 224 | } 225 | 226 | /** 227 | * Return the instance of {@link com.sun.jersey.api.client.RequestWriter}. This instance will be injected 228 | * within Jersey so it cannot be null. 229 | * 230 | * @return the instance of {@link com.sun.jersey.api.client.RequestWriter}. 231 | */ 232 | public AhcRequestWriter getAhcRequestWriter() { 233 | return requestWriter; 234 | } 235 | 236 | private void handleCookie(final RequestBuilder requestBuilder) { 237 | for (final Cookie c : cookies) { 238 | requestBuilder.addCookie(c); 239 | } 240 | } 241 | 242 | } 243 | -------------------------------------------------------------------------------- /src/main/java/org/sonatype/spice/jersey/client/ahc/AhcHttpClient.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2010-2011 Sonatype, Inc. 3 | * All rights reserved. This program and the accompanying materials 4 | * are made available under the terms of the Eclipse Public License v1.0 5 | * and Apache License v2.0 which accompanies this distribution. 6 | * The Eclipse Public License is available at 7 | * http://www.eclipse.org/legal/epl-v10.html 8 | * The Apache License v2.0 is available at 9 | * http://www.apache.org/licenses/LICENSE-2.0.html 10 | * You may elect to redistribute this code under either of these licenses. 11 | *******************************************************************************/ 12 | package org.sonatype.spice.jersey.client.ahc; 13 | 14 | import org.sonatype.spice.jersey.client.ahc.config.AhcConfig; 15 | import org.sonatype.spice.jersey.client.ahc.config.DefaultAhcConfig; 16 | 17 | import com.ning.http.client.AsyncHttpClient; 18 | import com.sun.jersey.api.client.Client; 19 | import com.sun.jersey.api.client.config.ClientConfig; 20 | import com.sun.jersey.core.spi.component.ioc.IoCComponentProviderFactory; 21 | 22 | /** 23 | * A {@link Client} that utilizes the AsyncHttpClient to send and receive 24 | * HTTP request and responses. 25 | *

26 | * If an {@link AhcClientHandler} is not explicitly passed as a 27 | * constructor or method parameter then by default an instance is created with 28 | * an {@link AsyncHttpClient} constructed 29 | *

30 | *

31 | * If a response entity is obtained that is an instance of 32 | * {@link java.io.Closeable} 33 | * then the instance MUST be closed after processing the entity to release 34 | * connection-based resources. 35 | *

36 | * If a {@link com.sun.jersey.api.client.ClientResponse} is obtained and an 37 | * entity is not read from the response then 38 | * {@link com.sun.jersey.api.client.ClientResponse#close() } MUST be called 39 | * after processing the response to release connection-based resources. 40 | * 41 | * @author Jeanfrancois Arcand 42 | */ 43 | public class AhcHttpClient extends Client { 44 | 45 | private final AhcClientHandler clientHandler; 46 | 47 | /** 48 | * Create a new client instance. 49 | * 50 | */ 51 | public AhcHttpClient() { 52 | this(createDefaultClientHander(new DefaultAhcConfig())); 53 | } 54 | 55 | /** 56 | * Create a new client instance. 57 | * 58 | * @param root the root client handler for dispatching a request and 59 | * returning a response. 60 | */ 61 | public AhcHttpClient(final AhcClientHandler root) { 62 | this(root, null); 63 | } 64 | 65 | /** 66 | * Create a new instance with a client configuration and a 67 | * component provider. 68 | * 69 | * @param root the root client handler for dispatching a request and 70 | * returning a response. 71 | * @param config the client configuration. 72 | * @param provider the IoC component provider factory. 73 | * @deprecated the config parameter is no longer utilized and instead 74 | * the config obtained from the {@link AhcClientHandler#getConfig() } 75 | * is utilized instead. 76 | */ 77 | @Deprecated 78 | public AhcHttpClient(final AhcClientHandler root, final ClientConfig config, 79 | final IoCComponentProviderFactory provider) { 80 | this(root, provider); 81 | } 82 | 83 | /** 84 | * Create a new instance with a client configuration and a 85 | * component provider. 86 | * 87 | * @param root the root client handler for dispatching a request and 88 | * returning a response. 89 | * @param provider the IoC component provider factory. 90 | */ 91 | public AhcHttpClient(final AhcClientHandler root, 92 | final IoCComponentProviderFactory provider) { 93 | super(root, root.getConfig(), provider); 94 | 95 | this.clientHandler = root; 96 | inject(this.clientHandler.getAhcRequestWriter()); 97 | } 98 | 99 | /** 100 | * Get the AsyncHttpClient client handler. 101 | * 102 | * @return the AsyncHttpClient client handler. 103 | */ 104 | public AhcClientHandler getClientHandler() { 105 | return clientHandler; 106 | } 107 | 108 | /** 109 | * Create a default client. 110 | * 111 | * @return a default client. 112 | */ 113 | public static AhcHttpClient create() { 114 | return create(new DefaultAhcConfig()); 115 | } 116 | 117 | /** 118 | * Create a default client with client configuration. 119 | * 120 | * @param cc the client configuration. 121 | * @return a default client. 122 | */ 123 | public static AhcHttpClient create(final ClientConfig cc) { 124 | return create(cc, null); 125 | } 126 | 127 | /** 128 | * Create a default client with client configuration and component provider. 129 | * 130 | * @param cc the client configuration. 131 | * @param provider the IoC component provider factory. 132 | * @return a default client. 133 | */ 134 | public static AhcHttpClient create(final ClientConfig cc, final IoCComponentProviderFactory provider) { 135 | return new AhcHttpClient(createDefaultClientHander(cc), provider); 136 | } 137 | 138 | @Override 139 | public void destroy(){ 140 | try{ 141 | clientHandler.getHttpClient().close(); 142 | } finally { 143 | super.destroy(); 144 | } 145 | } 146 | 147 | @Override 148 | protected void finalize(){ 149 | try { 150 | // Do not close the AHCClient. 151 | super.destroy(); 152 | } finally { 153 | try { 154 | super.finalize(); 155 | } catch (final Throwable e) { 156 | // TODO swallow? 157 | } 158 | } 159 | } 160 | 161 | /** 162 | * Create a default AsyncHttpClient client handler. 163 | * 164 | * @return a default AsyncHttpClient client handler. 165 | */ 166 | private static AhcClientHandler createDefaultClientHander(final ClientConfig cc) { 167 | 168 | if (AhcConfig.class.isAssignableFrom(cc.getClass()) || DefaultAhcConfig.class.isAssignableFrom(cc.getClass())) { 169 | final AhcConfig c = AhcConfig.class.cast(cc); 170 | return new AhcClientHandler(new AsyncHttpClient(c.getAsyncHttpClientConfigBuilder().build()), c); 171 | } else { 172 | throw new IllegalStateException("Client Config Type not supported"); 173 | } 174 | } 175 | 176 | @Override 177 | public void setFollowRedirects(final Boolean redirect) { 178 | clientHandler.getConfig().getAsyncHttpClientConfigBuilder().setFollowRedirects(redirect); 179 | } 180 | 181 | @Override 182 | public void setReadTimeout(final Integer interval) { 183 | clientHandler.getConfig().getAsyncHttpClientConfigBuilder().setRequestTimeoutInMs(interval); 184 | } 185 | 186 | @Override 187 | public void setConnectTimeout(final Integer interval) { 188 | clientHandler.getConfig().getAsyncHttpClientConfigBuilder().setConnectionTimeoutInMs(interval); 189 | } 190 | } -------------------------------------------------------------------------------- /src/main/java/org/sonatype/spice/jersey/client/ahc/AhcRequestWriter.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2010-2011 Sonatype, Inc. 3 | * All rights reserved. This program and the accompanying materials 4 | * are made available under the terms of the Eclipse Public License v1.0 5 | * and Apache License v2.0 which accompanies this distribution. 6 | * The Eclipse Public License is available at 7 | * http://www.eclipse.org/legal/epl-v10.html 8 | * The Apache License v2.0 is available at 9 | * http://www.apache.org/licenses/LICENSE-2.0.html 10 | * You may elect to redistribute this code under either of these licenses. 11 | *******************************************************************************/ 12 | package org.sonatype.spice.jersey.client.ahc; 13 | 14 | import static com.sun.jersey.api.client.ClientRequest.getHeaderValue; 15 | 16 | import java.io.ByteArrayOutputStream; 17 | import java.io.IOException; 18 | import java.io.OutputStream; 19 | import java.util.List; 20 | import java.util.Map; 21 | 22 | import javax.ws.rs.core.MultivaluedMap; 23 | 24 | import org.sonatype.spice.jersey.client.ahc.config.AhcConfig; 25 | 26 | import com.ning.http.client.PerRequestConfig; 27 | import com.ning.http.client.Request; 28 | import com.ning.http.client.RequestBuilder; 29 | import com.sun.jersey.api.client.ClientHandlerException; 30 | import com.sun.jersey.api.client.ClientRequest; 31 | import com.sun.jersey.api.client.CommittingOutputStream; 32 | import com.sun.jersey.api.client.RequestWriter; 33 | 34 | /** 35 | * An implementation of {@link RequestWriter} that also configure the AHC {@link RequestBuilder} 36 | * 37 | * @author Jeanfrancois Arcand 38 | */ 39 | public class AhcRequestWriter extends RequestWriter { 40 | 41 | public void configureRequest(final RequestBuilder requestBuilder, final ClientRequest cr, final boolean needsBody) { 42 | final Map props = cr.getProperties(); 43 | 44 | // Set the read timeout 45 | final Integer readTimeout = (Integer) props.get(AhcConfig.PROPERTY_READ_TIMEOUT); 46 | if (readTimeout != null) { 47 | final PerRequestConfig c = new PerRequestConfig(); 48 | c.setRequestTimeoutInMs(readTimeout); 49 | requestBuilder.setPerRequestConfig(c); 50 | } 51 | if (cr.getEntity() != null && needsBody) { 52 | final RequestEntityWriter re = getRequestEntityWriter(cr); 53 | 54 | final ByteArrayOutputStream baos = new ByteArrayOutputStream(); 55 | try { 56 | re.writeRequestEntity(new CommittingOutputStream(baos) { 57 | @Override 58 | protected void commit() throws IOException { 59 | configureHeaders(cr.getHeaders(), requestBuilder); 60 | } 61 | }); 62 | } catch (final IOException ex) { 63 | throw new ClientHandlerException(ex); 64 | } 65 | 66 | final byte[] content = baos.toByteArray(); 67 | requestBuilder.setBody(new Request.EntityWriter() { 68 | @Override 69 | public void writeEntity(final OutputStream out) throws IOException { 70 | out.write(content); 71 | } 72 | }); 73 | } else { 74 | configureHeaders(cr.getHeaders(), requestBuilder); 75 | } 76 | } 77 | 78 | private void configureHeaders(final MultivaluedMap metadata, final RequestBuilder requestBuilder) { 79 | for (final Map.Entry> e : metadata.entrySet()) { 80 | final List vs = e.getValue(); 81 | for (final Object o : vs) { 82 | if (String.class.isAssignableFrom( o.getClass() )) { 83 | requestBuilder.addHeader(e.getKey(), o.toString()); 84 | } else { 85 | requestBuilder.addHeader(e.getKey(), getHeaderValue(o)); 86 | } 87 | } 88 | } 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /src/main/java/org/sonatype/spice/jersey/client/ahc/config/AhcConfig.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2010-2011 Sonatype, Inc. 3 | * All rights reserved. This program and the accompanying materials 4 | * are made available under the terms of the Eclipse Public License v1.0 5 | * and Apache License v2.0 which accompanies this distribution. 6 | * The Eclipse Public License is available at 7 | * http://www.eclipse.org/legal/epl-v10.html 8 | * The Apache License v2.0 is available at 9 | * http://www.apache.org/licenses/LICENSE-2.0.html 10 | * You may elect to redistribute this code under either of these licenses. 11 | *******************************************************************************/ 12 | package org.sonatype.spice.jersey.client.ahc.config; 13 | 14 | import com.ning.http.client.AsyncHttpClientConfig; 15 | import com.sun.jersey.api.client.config.ClientConfig; 16 | 17 | public interface AhcConfig extends ClientConfig { 18 | 19 | /** 20 | * Get the {@link com.ning.http.client.AsyncHttpClientConfig.Builder} config object. Credentials may be set on the it. 21 | *

22 | * @return the {@link com.ning.http.client.AsyncHttpClientConfig.Builder} 23 | */ 24 | public AsyncHttpClientConfig.Builder getAsyncHttpClientConfigBuilder(); 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/org/sonatype/spice/jersey/client/ahc/config/DefaultAhcConfig.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2010-2011 Sonatype, Inc. 3 | * All rights reserved. This program and the accompanying materials 4 | * are made available under the terms of the Eclipse Public License v1.0 5 | * and Apache License v2.0 which accompanies this distribution. 6 | * The Eclipse Public License is available at 7 | * http://www.eclipse.org/legal/epl-v10.html 8 | * The Apache License v2.0 is available at 9 | * http://www.apache.org/licenses/LICENSE-2.0.html 10 | * You may elect to redistribute this code under either of these licenses. 11 | *******************************************************************************/ 12 | package org.sonatype.spice.jersey.client.ahc.config; 13 | 14 | import com.ning.http.client.AsyncHttpClientConfig; 15 | import com.sun.jersey.api.client.config.DefaultClientConfig; 16 | 17 | public class DefaultAhcConfig extends DefaultClientConfig implements AhcConfig{ 18 | 19 | private AsyncHttpClientConfig.Builder config; 20 | 21 | @Override 22 | public AsyncHttpClientConfig.Builder getAsyncHttpClientConfigBuilder() { 23 | 24 | if (config == null) { 25 | config = new AsyncHttpClientConfig.Builder(); 26 | } 27 | 28 | return config; 29 | } 30 | } -------------------------------------------------------------------------------- /src/test/java/org/sonatype/spice/jersey/client/ahc/tests/tests/AbstractGrizzlyServerTester.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2010-2011 Sonatype, Inc. 3 | * All rights reserved. This program and the accompanying materials 4 | * are made available under the terms of the Eclipse Public License v1.0 5 | * and Apache License v2.0 which accompanies this distribution. 6 | * The Eclipse Public License is available at 7 | * http://www.eclipse.org/legal/epl-v10.html 8 | * The Apache License v2.0 is available at 9 | * http://www.apache.org/licenses/LICENSE-2.0.html 10 | * You may elect to redistribute this code under either of these licenses. 11 | *******************************************************************************/ 12 | 13 | package org.sonatype.spice.jersey.client.ahc.tests.tests; 14 | 15 | import com.sun.grizzly.http.SelectorThread; 16 | import com.sun.grizzly.tcp.Adapter; 17 | import com.sun.jersey.api.container.ContainerFactory; 18 | import com.sun.jersey.api.container.grizzly.GrizzlyServerFactory; 19 | import com.sun.jersey.api.core.ResourceConfig; 20 | import junit.framework.TestCase; 21 | 22 | import javax.ws.rs.core.UriBuilder; 23 | import java.io.IOException; 24 | import java.net.URI; 25 | 26 | /** 27 | * 28 | * @author Paul.Sandoz@Sun.Com 29 | */ 30 | public abstract class AbstractGrizzlyServerTester extends TestCase { 31 | public static final String CONTEXT = ""; 32 | 33 | private SelectorThread selectorThread; 34 | 35 | private int port = getEnvVariable("JERSEY_HTTP_PORT", 9997); 36 | 37 | private static int getEnvVariable(final String varName, int defaultValue) { 38 | if (null == varName) { 39 | return defaultValue; 40 | } 41 | String varValue = System.getenv(varName); 42 | if (null != varValue) { 43 | try { 44 | return Integer.parseInt(varValue); 45 | }catch (NumberFormatException e) { 46 | // will return default value bellow 47 | } 48 | } 49 | return defaultValue; 50 | } 51 | 52 | public AbstractGrizzlyServerTester(String name) { 53 | super(name); 54 | } 55 | 56 | public UriBuilder getUri() { 57 | return UriBuilder.fromUri("http://localhost").port(port).path(CONTEXT); 58 | } 59 | 60 | public void startServer(Class... resources) { 61 | start(ContainerFactory.createContainer(Adapter.class, resources)); 62 | } 63 | 64 | public void startServer(ResourceConfig config) { 65 | start(ContainerFactory.createContainer(Adapter.class, config)); 66 | } 67 | 68 | private void start(Adapter adapter) { 69 | if (selectorThread != null && selectorThread.isRunning()){ 70 | stopServer(); 71 | } 72 | 73 | System.out.println("Starting GrizzlyServer port number = " + port); 74 | 75 | URI u = UriBuilder.fromUri("http://localhost").port(port).build(); 76 | try { 77 | selectorThread = GrizzlyServerFactory.create(u, adapter); 78 | } catch (IOException e) { 79 | throw new RuntimeException(e); 80 | } 81 | System.out.println("Started GrizzlyServer"); 82 | 83 | int timeToSleep = getEnvVariable("JERSEY_HTTP_SLEEP", 0); 84 | if (timeToSleep > 0) { 85 | System.out.println("Sleeping for " + timeToSleep + " ms"); 86 | try { 87 | // Wait for the server to start 88 | Thread.sleep(timeToSleep); 89 | } catch (InterruptedException ex) { 90 | System.out.println("Sleeping interrupted: " + ex.getLocalizedMessage()); 91 | } 92 | } 93 | } 94 | 95 | public void stopServer() { 96 | if (selectorThread.isRunning()) { 97 | selectorThread.stopEndpoint(); 98 | } 99 | } 100 | 101 | @Override 102 | public void tearDown() { 103 | stopServer(); 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /src/test/java/org/sonatype/spice/jersey/client/ahc/tests/tests/AuthTest.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2010-2011 Sonatype, Inc. 3 | * All rights reserved. This program and the accompanying materials 4 | * are made available under the terms of the Eclipse Public License v1.0 5 | * and Apache License v2.0 which accompanies this distribution. 6 | * The Eclipse Public License is available at 7 | * http://www.eclipse.org/legal/epl-v10.html 8 | * The Apache License v2.0 is available at 9 | * http://www.apache.org/licenses/LICENSE-2.0.html 10 | * You may elect to redistribute this code under either of these licenses. 11 | *******************************************************************************/ 12 | 13 | package org.sonatype.spice.jersey.client.ahc.tests.tests; 14 | 15 | import com.ning.http.client.Realm; 16 | import com.sun.jersey.api.client.ClientResponse; 17 | import com.sun.jersey.api.client.WebResource; 18 | import com.sun.jersey.api.client.filter.HTTPBasicAuthFilter; 19 | import com.sun.jersey.api.container.filter.LoggingFilter; 20 | import com.sun.jersey.api.core.DefaultResourceConfig; 21 | import com.sun.jersey.api.core.ResourceConfig; 22 | import com.sun.jersey.spi.resource.Singleton; 23 | import org.sonatype.spice.jersey.client.ahc.AhcHttpClient; 24 | import org.sonatype.spice.jersey.client.ahc.config.DefaultAhcConfig; 25 | 26 | import javax.ws.rs.DELETE; 27 | import javax.ws.rs.GET; 28 | import javax.ws.rs.POST; 29 | import javax.ws.rs.Path; 30 | import javax.ws.rs.WebApplicationException; 31 | import javax.ws.rs.core.Context; 32 | import javax.ws.rs.core.HttpHeaders; 33 | import javax.ws.rs.core.Response; 34 | 35 | /** 36 | * 37 | * @author Paul.Sandoz@Sun.Com 38 | */ 39 | public class AuthTest extends AbstractGrizzlyServerTester { 40 | 41 | public AuthTest(String testName) { 42 | super(testName); 43 | } 44 | 45 | @Path("/") 46 | public static class PreemptiveAuthResource { 47 | @GET 48 | public String get(@Context HttpHeaders h) { 49 | String value = h.getRequestHeaders().getFirst("Authorization"); 50 | assertNotNull(value); 51 | return "GET"; 52 | } 53 | 54 | @POST 55 | public String post(@Context HttpHeaders h, String e) { 56 | String value = h.getRequestHeaders().getFirst("Authorization"); 57 | assertNotNull(value); 58 | return e; 59 | } 60 | } 61 | 62 | public void testPreemptiveAuth() { 63 | ResourceConfig rc = new DefaultResourceConfig(PreemptiveAuthResource.class); 64 | rc.getProperties().put(ResourceConfig.PROPERTY_CONTAINER_REQUEST_FILTERS, 65 | LoggingFilter.class.getName()); 66 | startServer(rc); 67 | 68 | DefaultAhcConfig config = new DefaultAhcConfig(); 69 | config.getAsyncHttpClientConfigBuilder().setRealm(new Realm.RealmBuilder().setScheme(Realm.AuthScheme.BASIC).setUsePreemptiveAuth(true).setPrincipal("name").setPassword("password").build()); 70 | AhcHttpClient c = AhcHttpClient.create(config); 71 | 72 | WebResource r = c.resource(getUri().build()); 73 | assertEquals("GET", r.get(String.class)); 74 | } 75 | 76 | public void testPreemptiveAuthPost() { 77 | ResourceConfig rc = new DefaultResourceConfig(PreemptiveAuthResource.class); 78 | rc.getProperties().put(ResourceConfig.PROPERTY_CONTAINER_REQUEST_FILTERS, 79 | LoggingFilter.class.getName()); 80 | startServer(rc); 81 | 82 | DefaultAhcConfig config = new DefaultAhcConfig(); 83 | config.getAsyncHttpClientConfigBuilder().setRealm(new Realm.RealmBuilder().setScheme(Realm.AuthScheme.BASIC).setUsePreemptiveAuth(true).setPrincipal("name").setPassword("password").build()); 84 | AhcHttpClient c = AhcHttpClient.create(config); 85 | 86 | WebResource r = c.resource(getUri().build()); 87 | assertEquals("POST", r.post(String.class, "POST")); 88 | } 89 | 90 | @Path("/test") 91 | @Singleton 92 | public static class AuthResource { 93 | int requestCount = 0; 94 | @GET 95 | public String get(@Context HttpHeaders h) { 96 | requestCount++; 97 | String value = h.getRequestHeaders().getFirst("Authorization"); 98 | if (value == null) { 99 | assertEquals(1, requestCount); 100 | throw new WebApplicationException(Response.status(401).header("WWW-Authenticate", "Basic realm=\"WallyWorld\"").build()); 101 | } else { 102 | assertTrue(requestCount > 1); 103 | } 104 | 105 | return "GET"; 106 | } 107 | 108 | @GET 109 | @Path("filter") 110 | public String getFilter(@Context HttpHeaders h) { 111 | String value = h.getRequestHeaders().getFirst("Authorization"); 112 | if (value == null) { 113 | throw new WebApplicationException(Response.status(401).header("WWW-Authenticate", "Basic realm=\"WallyWorld\"").build()); 114 | } 115 | 116 | return "GET"; 117 | } 118 | 119 | @POST 120 | public String post(@Context HttpHeaders h, String e) { 121 | requestCount++; 122 | String value = h.getRequestHeaders().getFirst("Authorization"); 123 | if (value == null) { 124 | assertEquals(1, requestCount); 125 | throw new WebApplicationException(Response.status(401).header("WWW-Authenticate", "Basic realm=\"WallyWorld\"").build()); 126 | } else { 127 | assertTrue(requestCount > 1); 128 | } 129 | 130 | return e; 131 | } 132 | 133 | @POST 134 | @Path("filter") 135 | public String postFilter(@Context HttpHeaders h, String e) { 136 | String value = h.getRequestHeaders().getFirst("Authorization"); 137 | if (value == null) { 138 | throw new WebApplicationException(Response.status(401).header("WWW-Authenticate", "Basic realm=\"WallyWorld\"").build()); 139 | } 140 | 141 | return e; 142 | } 143 | 144 | @DELETE 145 | public void delete(@Context HttpHeaders h) { 146 | requestCount++; 147 | String value = h.getRequestHeaders().getFirst("Authorization"); 148 | if (value == null) { 149 | assertEquals(1, requestCount); 150 | throw new WebApplicationException(Response.status(401).header("WWW-Authenticate", "Basic realm=\"WallyWorld\"").build()); 151 | } else { 152 | assertTrue(requestCount > 1); 153 | } 154 | } 155 | 156 | @DELETE 157 | @Path("filter") 158 | public void deleteFilter(@Context HttpHeaders h) { 159 | String value = h.getRequestHeaders().getFirst("Authorization"); 160 | if (value == null) { 161 | throw new WebApplicationException(Response.status(401).header("WWW-Authenticate", "Basic realm=\"WallyWorld\"").build()); 162 | } 163 | } 164 | 165 | @DELETE 166 | @Path("filter/withEntity") 167 | public String deleteFilterWithEntity(@Context HttpHeaders h, String e) { 168 | String value = h.getRequestHeaders().getFirst("Authorization"); 169 | if (value == null) { 170 | throw new WebApplicationException(Response.status(401).header("WWW-Authenticate", "Basic realm=\"WallyWorld\"").build()); 171 | } 172 | 173 | return e; 174 | } 175 | 176 | 177 | 178 | } 179 | 180 | public void testAuthGet() { 181 | ResourceConfig rc = new DefaultResourceConfig(AuthResource.class); 182 | rc.getProperties().put(ResourceConfig.PROPERTY_CONTAINER_REQUEST_FILTERS, 183 | LoggingFilter.class.getName()); 184 | startServer(rc); 185 | 186 | DefaultAhcConfig config = new DefaultAhcConfig(); 187 | config.getAsyncHttpClientConfigBuilder().setRealm(new Realm.RealmBuilder().setUsePreemptiveAuth(false).setPrincipal("name").setPassword("password").build()); 188 | AhcHttpClient c = AhcHttpClient.create(config); 189 | 190 | WebResource r = c.resource(getUri().path("test").build()); 191 | assertEquals("GET", r.get(String.class)); 192 | } 193 | 194 | public void testAuthGetWithClientFilter() { 195 | ResourceConfig rc = new DefaultResourceConfig(AuthResource.class); 196 | rc.getProperties().put(ResourceConfig.PROPERTY_CONTAINER_REQUEST_FILTERS, 197 | LoggingFilter.class.getName()); 198 | rc.getProperties().put(ResourceConfig.PROPERTY_CONTAINER_RESPONSE_FILTERS, 199 | LoggingFilter.class.getName()); 200 | startServer(rc); 201 | AhcHttpClient c = AhcHttpClient.create(); 202 | c.addFilter(new HTTPBasicAuthFilter("name", "password")); 203 | 204 | WebResource r = c.resource(getUri().path("test/filter").build()); 205 | assertEquals("GET", r.get(String.class)); 206 | } 207 | 208 | public void testAuthPost() { 209 | ResourceConfig rc = new DefaultResourceConfig(AuthResource.class); 210 | // rc.getProperties().put(ResourceConfig.PROPERTY_CONTAINER_REQUEST_FILTERS, 211 | // LoggingFilter.class.getName()); 212 | startServer(rc); 213 | 214 | DefaultAhcConfig config = new DefaultAhcConfig(); 215 | config.getAsyncHttpClientConfigBuilder().setRealm(new Realm.RealmBuilder().setUsePreemptiveAuth(false).setPrincipal("name").setPassword("password").build()); 216 | AhcHttpClient c = AhcHttpClient.create(config); 217 | 218 | WebResource r = c.resource(getUri().path("test").build()); 219 | assertEquals("POST", r.post(String.class, "POST")); 220 | } 221 | 222 | public void testAuthPostWithClientFilter() { 223 | ResourceConfig rc = new DefaultResourceConfig(AuthResource.class); 224 | rc.getProperties().put(ResourceConfig.PROPERTY_CONTAINER_REQUEST_FILTERS, 225 | LoggingFilter.class.getName()); 226 | rc.getProperties().put(ResourceConfig.PROPERTY_CONTAINER_RESPONSE_FILTERS, 227 | LoggingFilter.class.getName()); 228 | startServer(rc); 229 | AhcHttpClient c = AhcHttpClient.create(); 230 | c.addFilter(new HTTPBasicAuthFilter("name", "password")); 231 | 232 | WebResource r = c.resource(getUri().path("test/filter").build()); 233 | assertEquals("POST", r.post(String.class, "POST")); 234 | } 235 | 236 | public void testAuthDelete() { 237 | ResourceConfig rc = new DefaultResourceConfig(AuthResource.class); 238 | rc.getProperties().put(ResourceConfig.PROPERTY_CONTAINER_REQUEST_FILTERS, 239 | LoggingFilter.class.getName()); 240 | rc.getProperties().put(ResourceConfig.PROPERTY_CONTAINER_RESPONSE_FILTERS, 241 | LoggingFilter.class.getName()); 242 | startServer(rc); 243 | DefaultAhcConfig config = new DefaultAhcConfig(); 244 | config.getAsyncHttpClientConfigBuilder().setRealm(new Realm.RealmBuilder().setUsePreemptiveAuth(false).setPrincipal("name").setPassword("password").build()); 245 | AhcHttpClient c = AhcHttpClient.create(config); 246 | 247 | WebResource r = c.resource(getUri().path("test").build()); 248 | ClientResponse response = r.delete(ClientResponse.class); 249 | assertEquals(response.getStatus(), 204); 250 | } 251 | 252 | public void testAuthDeleteWithClientFilter() { 253 | ResourceConfig rc = new DefaultResourceConfig(AuthResource.class); 254 | rc.getProperties().put(ResourceConfig.PROPERTY_CONTAINER_REQUEST_FILTERS, 255 | LoggingFilter.class.getName()); 256 | rc.getProperties().put(ResourceConfig.PROPERTY_CONTAINER_RESPONSE_FILTERS, 257 | LoggingFilter.class.getName()); 258 | startServer(rc); 259 | AhcHttpClient c = AhcHttpClient.create(); 260 | c.addFilter(new HTTPBasicAuthFilter("name", "password")); 261 | 262 | WebResource r = c.resource(getUri().path("test/filter").build()); 263 | ClientResponse response = r.delete(ClientResponse.class); 264 | assertEquals(204, response.getStatus()); 265 | } 266 | 267 | public void testAuthDeleteWithEntityUsingClientFilter() { 268 | ResourceConfig rc = new DefaultResourceConfig(AuthResource.class); 269 | rc.getProperties().put(ResourceConfig.PROPERTY_CONTAINER_REQUEST_FILTERS, 270 | LoggingFilter.class.getName()); 271 | rc.getProperties().put(ResourceConfig.PROPERTY_CONTAINER_RESPONSE_FILTERS, 272 | LoggingFilter.class.getName()); 273 | startServer(rc); 274 | AhcHttpClient c = AhcHttpClient.create(); 275 | c.addFilter(new HTTPBasicAuthFilter("name", "password")); 276 | 277 | WebResource r = c.resource(getUri().path("test/filter/withEntity").build()); 278 | ClientResponse response = r.delete(ClientResponse.class, "DELETE"); 279 | assertEquals(200, response.getStatus()); 280 | assertEquals("DELETE", response.getEntity(String.class)); 281 | } 282 | 283 | public void testAuthInteractiveGet() { 284 | ResourceConfig rc = new DefaultResourceConfig(AuthResource.class); 285 | rc.getProperties().put(ResourceConfig.PROPERTY_CONTAINER_REQUEST_FILTERS, 286 | LoggingFilter.class.getName()); 287 | startServer(rc); 288 | 289 | DefaultAhcConfig config = new DefaultAhcConfig(); 290 | config.getAsyncHttpClientConfigBuilder().setRealm(new Realm.RealmBuilder().setUsePreemptiveAuth(false).setPrincipal("name").setPassword("password").build()); 291 | AhcHttpClient c = AhcHttpClient.create(config); 292 | 293 | WebResource r = c.resource(getUri().path("test").build()); 294 | assertEquals("GET", r.get(String.class)); 295 | } 296 | 297 | public void testAuthInteractivePost() { 298 | ResourceConfig rc = new DefaultResourceConfig(AuthResource.class); 299 | rc.getProperties().put(ResourceConfig.PROPERTY_CONTAINER_REQUEST_FILTERS, 300 | LoggingFilter.class.getName()); 301 | startServer(rc); 302 | 303 | DefaultAhcConfig config = new DefaultAhcConfig(); 304 | config.getAsyncHttpClientConfigBuilder().setRealm(new Realm.RealmBuilder().setUsePreemptiveAuth(false).setPrincipal("name").setPassword("password").build()); 305 | 306 | AhcHttpClient c = AhcHttpClient.create(config); 307 | 308 | WebResource r = c.resource(getUri().path("test").build()); 309 | assertEquals("POST", r.post(String.class, "POST")); 310 | } 311 | } 312 | -------------------------------------------------------------------------------- /src/test/java/org/sonatype/spice/jersey/client/ahc/tests/tests/CookieTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 3 | * 4 | * Copyright (c) 2010-2011 Oracle and/or its affiliates. All rights reserved. 5 | * 6 | * The contents of this file are subject to the terms of either the GNU 7 | * General Public License Version 2 only ("GPL") or the Common Development 8 | * and Distribution License("CDDL") (collectively, the "License"). You 9 | * may not use this file except in compliance with the License. You can 10 | * obtain a copy of the License at 11 | * http://glassfish.java.net/public/CDDL+GPL_1_1.html 12 | * or packager/legal/LICENSE.txt. See the License for the specific 13 | * language governing permissions and limitations under the License. 14 | * 15 | * When distributing the software, include this License Header Notice in each 16 | * file and include the License file at packager/legal/LICENSE.txt. 17 | * 18 | * GPL Classpath Exception: 19 | * Oracle designates this particular file as subject to the "Classpath" 20 | * exception as provided by Oracle in the GPL Version 2 section of the License 21 | * file that accompanied this code. 22 | * 23 | * Modifications: 24 | * If applicable, add the following below the License Header, with the fields 25 | * enclosed by brackets [] replaced by your own identifying information: 26 | * "Portions Copyright [year] [name of copyright owner]" 27 | * 28 | * Contributor(s): 29 | * If you wish your version of this file to be governed by only the CDDL or 30 | * only the GPL Version 2, indicate your decision by adding "[Contributor] 31 | * elects to include this software in this distribution under the [CDDL or GPL 32 | * Version 2] license." If you don't indicate a single choice of license, a 33 | * recipient has the option to distribute your version of this file under 34 | * either the CDDL, the GPL Version 2 or to extend the choice of license to 35 | * its licensees as provided above. However, if you add GPL Version 2 code 36 | * and therefore, elected the GPL Version 2 license, then the option applies 37 | * only if the new code is made subject to such option by the copyright 38 | * holder. 39 | */ 40 | 41 | package org.sonatype.spice.jersey.client.ahc.tests.tests; 42 | 43 | import com.sun.jersey.api.client.WebResource; 44 | import com.sun.jersey.api.container.filter.LoggingFilter; 45 | import com.sun.jersey.api.core.DefaultResourceConfig; 46 | import com.sun.jersey.api.core.ResourceConfig; 47 | import org.sonatype.spice.jersey.client.ahc.AhcHttpClient; 48 | import org.sonatype.spice.jersey.client.ahc.config.DefaultAhcConfig; 49 | 50 | import javax.ws.rs.GET; 51 | import javax.ws.rs.POST; 52 | import javax.ws.rs.Path; 53 | import javax.ws.rs.core.*; 54 | 55 | /** 56 | * @author Paul.Sandoz@Sun.Com 57 | */ 58 | public class CookieTest extends AbstractGrizzlyServerTester { 59 | @Path("/") 60 | public static class CookieResource { 61 | @GET 62 | public Response get(@Context HttpHeaders h) { 63 | Cookie c = h.getCookies().get("name"); 64 | String e = (c == null) ? "NO-COOKIE" : c.getValue(); 65 | return Response.ok(e). 66 | cookie(new NewCookie("name", "value")).build(); 67 | } 68 | 69 | @POST 70 | public Response get() { 71 | // return response without cookie 72 | return Response.ok("wo-cookie").build(); 73 | } 74 | } 75 | 76 | public CookieTest(String testName) { 77 | super(testName); 78 | } 79 | 80 | public void testCookie() { 81 | ResourceConfig rc = new DefaultResourceConfig(CookieResource.class); 82 | rc.getProperties().put(ResourceConfig.PROPERTY_CONTAINER_REQUEST_FILTERS, 83 | LoggingFilter.class.getName()); 84 | startServer(rc); 85 | 86 | DefaultAhcConfig config = new DefaultAhcConfig(); 87 | AhcHttpClient c = AhcHttpClient.create(config); 88 | 89 | WebResource r = c.resource(getUri().build()); 90 | 91 | assertEquals("NO-COOKIE", r.get(String.class)); 92 | assertEquals("value", r.get(String.class)); 93 | } 94 | 95 | public void testCookieWithState() { 96 | ResourceConfig rc = new DefaultResourceConfig(CookieResource.class); 97 | rc.getProperties().put(ResourceConfig.PROPERTY_CONTAINER_REQUEST_FILTERS, 98 | LoggingFilter.class.getName()); 99 | startServer(rc); 100 | 101 | DefaultAhcConfig config = new DefaultAhcConfig(); 102 | AhcHttpClient c = AhcHttpClient.create(config); 103 | 104 | WebResource r = c.resource(getUri().build()); 105 | 106 | assertEquals("NO-COOKIE", r.get(String.class)); 107 | assertEquals("value", r.get(String.class)); 108 | 109 | } 110 | 111 | public void testSessionCookie() { 112 | ResourceConfig rc = new DefaultResourceConfig(CookieResource.class); 113 | rc.getProperties().put(ResourceConfig.PROPERTY_CONTAINER_REQUEST_FILTERS, 114 | LoggingFilter.class.getName()); 115 | startServer(rc); 116 | 117 | DefaultAhcConfig config = new DefaultAhcConfig(); 118 | AhcHttpClient c = AhcHttpClient.create(config); 119 | 120 | WebResource r = c.resource(getUri().build()); 121 | 122 | assertEquals("NO-COOKIE", r.get(String.class)); 123 | assertEquals("wo-cookie", r.post(String.class)); 124 | assertEquals("value", r.get(String.class)); 125 | } 126 | } -------------------------------------------------------------------------------- /src/test/java/org/sonatype/spice/jersey/client/ahc/tests/tests/GZIPContentEncodingTest.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2010-2011 Sonatype, Inc. 3 | * All rights reserved. This program and the accompanying materials 4 | * are made available under the terms of the Eclipse Public License v1.0 5 | * and Apache License v2.0 which accompanies this distribution. 6 | * The Eclipse Public License is available at 7 | * http://www.eclipse.org/legal/epl-v10.html 8 | * The Apache License v2.0 is available at 9 | * http://www.apache.org/licenses/LICENSE-2.0.html 10 | * You may elect to redistribute this code under either of these licenses. 11 | *******************************************************************************/ 12 | 13 | package org.sonatype.spice.jersey.client.ahc.tests.tests; 14 | 15 | import com.sun.jersey.api.client.ClientResponse; 16 | import com.sun.jersey.api.client.WebResource; 17 | import com.sun.jersey.api.container.filter.GZIPContentEncodingFilter; 18 | import com.sun.jersey.api.core.DefaultResourceConfig; 19 | import com.sun.jersey.api.core.ResourceConfig; 20 | import org.sonatype.spice.jersey.client.ahc.AhcHttpClient; 21 | import org.sonatype.spice.jersey.client.ahc.config.AhcConfig; 22 | import org.sonatype.spice.jersey.client.ahc.config.DefaultAhcConfig; 23 | 24 | import javax.ws.rs.POST; 25 | import javax.ws.rs.Path; 26 | import java.util.Arrays; 27 | 28 | /** 29 | * 30 | * @author Paul.Sandoz@Sun.Com 31 | */ 32 | public class GZIPContentEncodingTest extends AbstractGrizzlyServerTester { 33 | 34 | @Path("/") 35 | public static class Resource { 36 | @POST 37 | public byte[] post(byte[] content) { return content; } 38 | } 39 | 40 | public GZIPContentEncodingTest(String testName) { 41 | super(testName); 42 | } 43 | 44 | 45 | public void testPost() { 46 | ResourceConfig rc = new DefaultResourceConfig(Resource.class); 47 | rc.getProperties().put(ResourceConfig.PROPERTY_CONTAINER_REQUEST_FILTERS, 48 | GZIPContentEncodingFilter.class.getName()); 49 | rc.getProperties().put(ResourceConfig.PROPERTY_CONTAINER_RESPONSE_FILTERS, 50 | GZIPContentEncodingFilter.class.getName()); 51 | startServer(rc); 52 | 53 | AhcHttpClient c = AhcHttpClient.create(); 54 | c.addFilter(new com.sun.jersey.api.client.filter.GZIPContentEncodingFilter()); 55 | 56 | WebResource r = c.resource(getUri().path("/").build()); 57 | byte[] content = new byte[1024 * 1024]; 58 | assertTrue(Arrays.equals(content, r.post(byte[].class, content))); 59 | 60 | ClientResponse cr = r.post(ClientResponse.class, content); 61 | assertTrue(cr.hasEntity()); 62 | cr.close(); 63 | } 64 | 65 | public void testPostChunked() { 66 | ResourceConfig rc = new DefaultResourceConfig(Resource.class); 67 | rc.getProperties().put(ResourceConfig.PROPERTY_CONTAINER_REQUEST_FILTERS, 68 | GZIPContentEncodingFilter.class.getName()); 69 | rc.getProperties().put(ResourceConfig.PROPERTY_CONTAINER_RESPONSE_FILTERS, 70 | GZIPContentEncodingFilter.class.getName()); 71 | startServer(rc); 72 | 73 | DefaultAhcConfig config = new DefaultAhcConfig(); 74 | config.getProperties().put(AhcConfig.PROPERTY_CHUNKED_ENCODING_SIZE, 1024); 75 | AhcHttpClient c = AhcHttpClient.create(config); 76 | c.addFilter(new com.sun.jersey.api.client.filter.GZIPContentEncodingFilter()); 77 | 78 | WebResource r = c.resource(getUri().path("/").build()); 79 | byte[] content = new byte[1024 * 1024]; 80 | assertTrue(Arrays.equals(content, r.post(byte[].class, content))); 81 | 82 | ClientResponse cr = r.post(ClientResponse.class, "POST"); 83 | assertTrue(cr.hasEntity()); 84 | cr.close(); 85 | } 86 | 87 | } -------------------------------------------------------------------------------- /src/test/java/org/sonatype/spice/jersey/client/ahc/tests/tests/HttpHeadersTest.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2010-2011 Sonatype, Inc. 3 | * All rights reserved. This program and the accompanying materials 4 | * are made available under the terms of the Eclipse Public License v1.0 5 | * and Apache License v2.0 which accompanies this distribution. 6 | * The Eclipse Public License is available at 7 | * http://www.eclipse.org/legal/epl-v10.html 8 | * The Apache License v2.0 is available at 9 | * http://www.apache.org/licenses/LICENSE-2.0.html 10 | * You may elect to redistribute this code under either of these licenses. 11 | *******************************************************************************/ 12 | 13 | package org.sonatype.spice.jersey.client.ahc.tests.tests; 14 | 15 | import com.sun.jersey.api.client.ClientResponse; 16 | import com.sun.jersey.api.client.WebResource; 17 | import com.sun.jersey.api.container.filter.LoggingFilter; 18 | import com.sun.jersey.api.core.DefaultResourceConfig; 19 | import com.sun.jersey.api.core.ResourceConfig; 20 | import org.sonatype.spice.jersey.client.ahc.AhcHttpClient; 21 | import org.sonatype.spice.jersey.client.ahc.config.AhcConfig; 22 | import org.sonatype.spice.jersey.client.ahc.config.DefaultAhcConfig; 23 | 24 | import javax.ws.rs.HeaderParam; 25 | import javax.ws.rs.POST; 26 | import javax.ws.rs.Path; 27 | import javax.ws.rs.Produces; 28 | import javax.ws.rs.WebApplicationException; 29 | import javax.ws.rs.core.MediaType; 30 | import javax.ws.rs.core.MultivaluedMap; 31 | import javax.ws.rs.ext.MessageBodyWriter; 32 | import javax.ws.rs.ext.Provider; 33 | import java.io.IOException; 34 | import java.io.OutputStream; 35 | import java.lang.annotation.Annotation; 36 | import java.lang.reflect.Type; 37 | 38 | /** 39 | * 40 | * @author Paul.Sandoz@Sun.Com 41 | */ 42 | public class HttpHeadersTest extends AbstractGrizzlyServerTester { 43 | @Path("/test") 44 | public static class HttpMethodResource { 45 | @POST 46 | public String post( 47 | @HeaderParam("Transfer-Encoding") String transferEncoding, 48 | @HeaderParam("X-CLIENT") String xClient, 49 | @HeaderParam("X-WRITER") String xWriter, 50 | String entity) { 51 | assertEquals("client", xClient); 52 | if (transferEncoding == null || !transferEncoding.equals("chunked")) 53 | assertEquals("writer", xWriter); 54 | return entity; 55 | } 56 | } 57 | 58 | @Provider 59 | @Produces("text/plain") 60 | public static class HeaderWriter implements MessageBodyWriter { 61 | 62 | public boolean isWriteable(Class type, Type genericType, Annotation[] annotations, MediaType mediaType) { 63 | return type == String.class; 64 | } 65 | 66 | public long getSize(String t, Class type, Type genericType, Annotation[] annotations, MediaType mediaType) { 67 | return -1; 68 | } 69 | 70 | public void writeTo(String t, Class type, Type genericType, Annotation[] annotations, MediaType mediaType, MultivaluedMap httpHeaders, OutputStream entityStream) throws IOException, WebApplicationException { 71 | httpHeaders.add("X-WRITER", "writer"); 72 | entityStream.write(t.getBytes()); 73 | } 74 | } 75 | 76 | public HttpHeadersTest(String testName) { 77 | super(testName); 78 | } 79 | 80 | public void testPost() { 81 | startServer(HttpMethodResource.class); 82 | 83 | DefaultAhcConfig config = new DefaultAhcConfig(); 84 | config.getClasses().add(HeaderWriter.class); 85 | AhcHttpClient c = AhcHttpClient.create(config); 86 | 87 | WebResource r = c.resource(getUri().path("test").build()); 88 | 89 | ClientResponse cr = r.header("X-CLIENT", "client").post(ClientResponse.class, "POST"); 90 | assertEquals(200, cr.getStatus()); 91 | assertTrue(cr.hasEntity()); 92 | cr.close(); 93 | } 94 | 95 | public void testPostChunked() { 96 | ResourceConfig rc = new DefaultResourceConfig(HttpMethodResource.class); 97 | rc.getProperties().put(ResourceConfig.PROPERTY_CONTAINER_REQUEST_FILTERS, 98 | LoggingFilter.class.getName()); 99 | startServer(rc); 100 | 101 | DefaultAhcConfig config = new DefaultAhcConfig(); 102 | config.getClasses().add(HeaderWriter.class); 103 | config.getProperties().put(AhcConfig.PROPERTY_CHUNKED_ENCODING_SIZE, 1024); 104 | AhcHttpClient c = AhcHttpClient.create(config); 105 | 106 | WebResource r = c.resource(getUri().path("test").build()); 107 | 108 | ClientResponse cr = r.header("X-CLIENT", "client").post(ClientResponse.class, "POST"); 109 | assertEquals(200, cr.getStatus()); 110 | assertTrue(cr.hasEntity()); 111 | cr.close(); 112 | } 113 | 114 | 115 | 116 | 117 | } -------------------------------------------------------------------------------- /src/test/java/org/sonatype/spice/jersey/client/ahc/tests/tests/HttpMethodTest.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2010-2011 Sonatype, Inc. 3 | * All rights reserved. This program and the accompanying materials 4 | * are made available under the terms of the Eclipse Public License v1.0 5 | * and Apache License v2.0 which accompanies this distribution. 6 | * The Eclipse Public License is available at 7 | * http://www.eclipse.org/legal/epl-v10.html 8 | * The Apache License v2.0 is available at 9 | * http://www.apache.org/licenses/LICENSE-2.0.html 10 | * You may elect to redistribute this code under either of these licenses. 11 | *******************************************************************************/ 12 | 13 | package org.sonatype.spice.jersey.client.ahc.tests.tests; 14 | 15 | import com.sun.jersey.api.client.ClientResponse; 16 | import com.sun.jersey.api.client.UniformInterfaceException; 17 | import com.sun.jersey.api.client.WebResource; 18 | import com.sun.jersey.api.container.filter.LoggingFilter; 19 | import com.sun.jersey.api.core.DefaultResourceConfig; 20 | import com.sun.jersey.api.core.ResourceConfig; 21 | import org.sonatype.spice.jersey.client.ahc.AhcHttpClient; 22 | import org.sonatype.spice.jersey.client.ahc.config.AhcConfig; 23 | import org.sonatype.spice.jersey.client.ahc.config.DefaultAhcConfig; 24 | 25 | import javax.ws.rs.DELETE; 26 | import javax.ws.rs.GET; 27 | import javax.ws.rs.HttpMethod; 28 | import javax.ws.rs.POST; 29 | import javax.ws.rs.PUT; 30 | import javax.ws.rs.Path; 31 | import javax.ws.rs.core.Response; 32 | import java.lang.annotation.ElementType; 33 | import java.lang.annotation.Retention; 34 | import java.lang.annotation.RetentionPolicy; 35 | import java.lang.annotation.Target; 36 | 37 | /** 38 | * 39 | * @author Paul.Sandoz@Sun.Com 40 | */ 41 | public class HttpMethodTest extends AbstractGrizzlyServerTester { 42 | @Target({ElementType.METHOD}) 43 | @Retention(RetentionPolicy.RUNTIME) 44 | @HttpMethod("PATCH") 45 | public @interface PATCH { 46 | } 47 | 48 | @Path("/test") 49 | public static class HttpMethodResource { 50 | @GET 51 | public String get() { 52 | return "GET"; 53 | } 54 | 55 | @POST 56 | public String post(String entity) { 57 | return entity; 58 | } 59 | 60 | @PUT 61 | public String put(String entity) { 62 | return entity; 63 | } 64 | 65 | @DELETE 66 | public String delete() { 67 | return "DELETE"; 68 | } 69 | 70 | @DELETE 71 | @Path("withentity") 72 | public String delete(String entity) { 73 | return entity; 74 | } 75 | 76 | @POST 77 | @Path("noproduce") 78 | public void postNoProduce(String entity) { 79 | } 80 | 81 | @POST 82 | @Path("noconsumeproduce") 83 | public void postNoConsumeProduce() { 84 | } 85 | 86 | @PATCH 87 | public String patch(String entity) { 88 | return entity; 89 | } 90 | } 91 | 92 | public HttpMethodTest(String testName) { 93 | super(testName); 94 | } 95 | 96 | protected AhcHttpClient createClient() { 97 | return AhcHttpClient.create(); 98 | } 99 | 100 | protected AhcHttpClient createClient(AhcConfig cc) { 101 | return AhcHttpClient.create(cc); 102 | } 103 | 104 | public void testHead() { 105 | startServer(HttpMethodResource.class); 106 | WebResource r = createClient().resource(getUri().path("test").build()); 107 | ClientResponse cr = r.head(); 108 | assertFalse(cr.hasEntity()); 109 | } 110 | 111 | public void testOptions() { 112 | startServer(HttpMethodResource.class); 113 | WebResource r = createClient().resource(getUri().path("test").build()); 114 | ClientResponse cr = r.options(ClientResponse.class); 115 | assertTrue(cr.hasEntity()); 116 | cr.close(); 117 | } 118 | 119 | public void testGet() { 120 | startServer(HttpMethodResource.class); 121 | WebResource r = createClient().resource(getUri().path("test").build()); 122 | assertEquals("GET", r.get(String.class)); 123 | 124 | ClientResponse cr = r.get(ClientResponse.class); 125 | assertTrue(cr.hasEntity()); 126 | cr.close(); 127 | } 128 | 129 | public void testPost() { 130 | startServer(HttpMethodResource.class); 131 | WebResource r = createClient().resource(getUri().path("test").build()); 132 | assertEquals("POST", r.post(String.class, "POST")); 133 | 134 | ClientResponse cr = r.post(ClientResponse.class, "POST"); 135 | assertTrue(cr.hasEntity()); 136 | cr.close(); 137 | } 138 | 139 | public void testPostChunked() { 140 | ResourceConfig rc = new DefaultResourceConfig(HttpMethodResource.class); 141 | rc.getProperties().put(ResourceConfig.PROPERTY_CONTAINER_REQUEST_FILTERS, 142 | LoggingFilter.class.getName()); 143 | startServer(rc); 144 | 145 | DefaultAhcConfig config = new DefaultAhcConfig(); 146 | config.getProperties().put(AhcConfig.PROPERTY_CHUNKED_ENCODING_SIZE, 1024); 147 | AhcHttpClient c = createClient(config); 148 | 149 | WebResource r = c.resource(getUri().path("test").build()); 150 | assertEquals("POST", r.post(String.class, "POST")); 151 | 152 | ClientResponse cr = r.post(ClientResponse.class, "POST"); 153 | assertTrue(cr.hasEntity()); 154 | cr.close(); 155 | } 156 | 157 | public void testPostVoid() { 158 | startServer(HttpMethodResource.class); 159 | WebResource r = createClient().resource(getUri().path("test").build()); 160 | 161 | // This test will lock up if ClientResponse is not closed by WebResource. 162 | // TODO need a better way to detect this. 163 | for (int i = 0; i < 100; i++) { 164 | r.post("POST"); 165 | } 166 | } 167 | 168 | public void testPostNoProduce() { 169 | startServer(HttpMethodResource.class); 170 | WebResource r = createClient().resource(getUri().path("test").build()); 171 | assertEquals(204, r.path("noproduce").post(ClientResponse.class, "POST").getStatus()); 172 | 173 | ClientResponse cr = r.path("noproduce").post(ClientResponse.class, "POST"); 174 | assertFalse(cr.hasEntity()); 175 | cr.close(); 176 | } 177 | 178 | public void testPostNoConsumeProduce() { 179 | startServer(HttpMethodResource.class); 180 | WebResource r = createClient().resource(getUri().path("test").build()); 181 | assertEquals(204, r.path("noconsumeproduce").post(ClientResponse.class).getStatus()); 182 | 183 | ClientResponse cr = r.path("noconsumeproduce").post(ClientResponse.class, "POST"); 184 | assertFalse(cr.hasEntity()); 185 | cr.close(); 186 | } 187 | 188 | public void testPut() { 189 | startServer(HttpMethodResource.class); 190 | WebResource r = createClient().resource(getUri().path("test").build()); 191 | assertEquals("PUT", r.put(String.class, "PUT")); 192 | 193 | ClientResponse cr = r.put(ClientResponse.class, "PUT"); 194 | assertTrue(cr.hasEntity()); 195 | cr.close(); 196 | } 197 | 198 | public void testDelete() { 199 | startServer(HttpMethodResource.class); 200 | WebResource r = createClient().resource(getUri().path("test").build()); 201 | assertEquals("DELETE", r.delete(String.class)); 202 | 203 | ClientResponse cr = r.delete(ClientResponse.class); 204 | assertTrue(cr.hasEntity()); 205 | cr.close(); 206 | } 207 | 208 | public void testDeleteWithEntity() { 209 | startServer(HttpMethodResource.class); 210 | WebResource r = createClient().resource(getUri().path("test/withentity").build()); 211 | r.addFilter(new com.sun.jersey.api.client.filter.LoggingFilter()); 212 | assertEquals("DELETE with entity", r.delete(String.class, "DELETE with entity")); 213 | 214 | ClientResponse cr = r.delete(ClientResponse.class, "DELETE with entity"); 215 | assertTrue(cr.hasEntity()); 216 | cr.close(); 217 | } 218 | 219 | public void testPatch() { 220 | startServer(HttpMethodResource.class); 221 | WebResource r = createClient().resource(getUri().path("test").build()); 222 | r.addFilter(new com.sun.jersey.api.client.filter.LoggingFilter()); 223 | assertEquals("PATCH", r.method("PATCH", String.class, "PATCH")); 224 | 225 | ClientResponse cr = r.method("PATCH", ClientResponse.class, "PATCH"); 226 | assertTrue(cr.hasEntity()); 227 | cr.close(); 228 | } 229 | 230 | public void testAll() { 231 | startServer(HttpMethodResource.class); 232 | WebResource r = createClient().resource(getUri().path("test").build()); 233 | 234 | assertEquals("GET", r.get(String.class)); 235 | 236 | assertEquals("POST", r.post(String.class, "POST")); 237 | 238 | assertEquals(204, r.path("noproduce").post(ClientResponse.class, "POST").getStatus()); 239 | 240 | assertEquals(204, r.path("noconsumeproduce").post(ClientResponse.class).getStatus()); 241 | 242 | assertEquals("PUT", r.post(String.class, "PUT")); 243 | 244 | assertEquals("DELETE", r.delete(String.class)); 245 | } 246 | 247 | 248 | @Path("/test") 249 | public static class ErrorResource { 250 | @POST 251 | public Response post(String entity) { 252 | return Response.serverError().build(); 253 | } 254 | 255 | @Path("entity") 256 | @POST 257 | public Response postWithEntity(String entity) { 258 | return Response.serverError().entity("error").build(); 259 | } 260 | } 261 | 262 | public void testPostError() { 263 | startServer(ErrorResource.class); 264 | WebResource r = createClient().resource(getUri().path("test").build()); 265 | 266 | // This test will lock up if ClientResponse is not closed by WebResource. 267 | // TODO need a better way to detect this. 268 | for (int i = 0; i < 100; i++) { 269 | try { 270 | r.post("POST"); 271 | } catch (UniformInterfaceException ex) { 272 | } 273 | } 274 | } 275 | 276 | public void testPostErrorWithEntity() { 277 | startServer(ErrorResource.class); 278 | WebResource r = createClient().resource(getUri().path("test/entity").build()); 279 | 280 | // This test will lock up if ClientResponse is not closed by WebResource. 281 | // TODO need a better way to detect this. 282 | for (int i = 0; i < 100; i++) { 283 | try { 284 | r.post("POST"); 285 | } catch (UniformInterfaceException ex) { 286 | String s = ex.getResponse().getEntity(String.class); 287 | assertEquals("error", s); 288 | } 289 | } 290 | } 291 | } -------------------------------------------------------------------------------- /src/test/java/org/sonatype/spice/jersey/client/ahc/tests/tests/HttpMethodWithClientFilterTest.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2010-2011 Sonatype, Inc. 3 | * All rights reserved. This program and the accompanying materials 4 | * are made available under the terms of the Eclipse Public License v1.0 5 | * and Apache License v2.0 which accompanies this distribution. 6 | * The Eclipse Public License is available at 7 | * http://www.eclipse.org/legal/epl-v10.html 8 | * The Apache License v2.0 is available at 9 | * http://www.apache.org/licenses/LICENSE-2.0.html 10 | * You may elect to redistribute this code under either of these licenses. 11 | *******************************************************************************/ 12 | 13 | package org.sonatype.spice.jersey.client.ahc.tests.tests; 14 | 15 | import com.sun.jersey.api.client.filter.LoggingFilter; 16 | import org.sonatype.spice.jersey.client.ahc.AhcHttpClient; 17 | import org.sonatype.spice.jersey.client.ahc.config.AhcConfig; 18 | 19 | /** 20 | * 21 | * @author Paul.Sandoz@Sun.Com 22 | */ 23 | public class HttpMethodWithClientFilterTest extends HttpMethodTest { 24 | public HttpMethodWithClientFilterTest(String testName) { 25 | super(testName); 26 | } 27 | 28 | @Override 29 | protected AhcHttpClient createClient() { 30 | AhcHttpClient ac = AhcHttpClient.create(); 31 | ac.addFilter(new LoggingFilter()); 32 | return ac; 33 | } 34 | 35 | @Override 36 | protected AhcHttpClient createClient(AhcConfig cc) { 37 | AhcHttpClient ac = AhcHttpClient.create(cc); 38 | ac.addFilter(new LoggingFilter()); 39 | return ac; 40 | } 41 | } -------------------------------------------------------------------------------- /src/test/java/org/sonatype/spice/jersey/client/ahc/tests/tests/NoEntityTest.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2010-2011 Sonatype, Inc. 3 | * All rights reserved. This program and the accompanying materials 4 | * are made available under the terms of the Eclipse Public License v1.0 5 | * and Apache License v2.0 which accompanies this distribution. 6 | * The Eclipse Public License is available at 7 | * http://www.eclipse.org/legal/epl-v10.html 8 | * The Apache License v2.0 is available at 9 | * http://www.apache.org/licenses/LICENSE-2.0.html 10 | * You may elect to redistribute this code under either of these licenses. 11 | *******************************************************************************/ 12 | 13 | package org.sonatype.spice.jersey.client.ahc.tests.tests; 14 | 15 | import javax.ws.rs.GET; 16 | import javax.ws.rs.POST; 17 | import javax.ws.rs.Path; 18 | import javax.ws.rs.core.Response; 19 | import javax.ws.rs.core.Response.Status; 20 | 21 | import org.sonatype.spice.jersey.client.ahc.AhcHttpClient; 22 | import org.sonatype.spice.jersey.client.ahc.config.AhcConfig; 23 | 24 | import com.sun.jersey.api.client.ClientResponse; 25 | import com.sun.jersey.api.client.WebResource; 26 | 27 | /** 28 | * 29 | * @author Paul.Sandoz@Sun.Com 30 | */ 31 | public class NoEntityTest extends AbstractGrizzlyServerTester { 32 | @Path("/test") 33 | public static class HttpMethodResource { 34 | @GET 35 | public Response get() { 36 | return Response.status(Status.CONFLICT).build(); 37 | } 38 | 39 | @POST 40 | public void post(final String entity) { 41 | } 42 | } 43 | 44 | public NoEntityTest(final String testName) { 45 | super(testName); 46 | } 47 | 48 | protected AhcHttpClient createClient() { 49 | return AhcHttpClient.create(); 50 | } 51 | 52 | protected AhcHttpClient createClient(final AhcConfig cc) { 53 | return AhcHttpClient.create(cc); 54 | } 55 | 56 | public void testGet() { 57 | startServer(HttpMethodResource.class); 58 | final WebResource r = createClient().resource(getUri().path("test").build()); 59 | 60 | for (int i = 0; i < 5; i++) { 61 | final ClientResponse cr = r.get(ClientResponse.class); 62 | } 63 | } 64 | 65 | public void testGetWithClose() { 66 | startServer(HttpMethodResource.class); 67 | final WebResource r = createClient().resource(getUri().path("test").build()); 68 | 69 | for (int i = 0; i < 5; i++) { 70 | final ClientResponse cr = r.get(ClientResponse.class); 71 | cr.close(); 72 | } 73 | } 74 | 75 | public void testPost() { 76 | startServer(HttpMethodResource.class); 77 | final WebResource r = createClient().resource(getUri().path("test").build()); 78 | 79 | for (int i = 0; i < 5; i++) { 80 | final ClientResponse cr = r.post(ClientResponse.class); 81 | } 82 | } 83 | 84 | public void testPostWithClose() { 85 | startServer(HttpMethodResource.class); 86 | final WebResource r = createClient().resource(getUri().path("test").build()); 87 | 88 | for (int i = 0; i < 5; i++) { 89 | final ClientResponse cr = r.post(ClientResponse.class); 90 | cr.close(); 91 | } 92 | } 93 | } -------------------------------------------------------------------------------- /src/test/resources/logback-test.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | %d [%thread] %level %logger - %m%n 5 | 6 | 7 | 8 | 9 | 10 | --------------------------------------------------------------------------------