From: Rafael R. <raf...@gm...> - 2011-07-27 00:36:49
|
I was already feeling like OAuth support wasn't really complete on Resteasy and this message<http://sourceforge.net/mailarchive/forum.php?thread_name=4E1B07CE.3080008%40redhat.com&forum_name=resteasy-developers>confirmed. Anyways as I had already coded a few services on top of resteasy (and had already tried other alternatives) I wasn't willing to give up on it... after following some tutorial around of how to use oauth<http://oauth.googlecode.com>to code a client an consume Resteasy coded services I though it'd suffice but I had lost the simplicity for writting the client and also the OO invocation style, that was when I decided to code the missing wrapper. After a small investigation noticed that the missing part was a ClientExecutor that delegated to OAuth libraries... making (already) long history short, I am willing to share my (already working but still deserving improvments) implementation of an OAuthClientExecutor: package org.jboss.resteasy.client.core.executors; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.AbstractMap.SimpleEntry; import java.util.Map.Entry; import javax.ws.rs.core.MultivaluedMap; import javax.ws.rs.core.UriBuilder; import net.oauth.OAuthAccessor; import net.oauth.OAuthConsumer; import net.oauth.OAuthMessage; import net.oauth.OAuthServiceProvider; import net.oauth.ParameterStyle; import net.oauth.client.OAuthClient; import net.oauth.client.OAuthResponseMessage; import net.oauth.http.HttpClient; import org.jboss.resteasy.client.ClientExecutor; import org.jboss.resteasy.client.ClientRequest; import org.jboss.resteasy.client.ClientResponse; import org.jboss.resteasy.client.ProxyFactory; import org.jboss.resteasy.client.core.BaseClientResponse; import org.jboss.resteasy.client.core.BaseClientResponse.BaseClientResponseStreamFactory; import org.jboss.resteasy.plugins.providers.jackson.ResteasyJacksonProvider; import org.jboss.resteasy.spi.ResteasyProviderFactory; import org.jboss.resteasy.util.CaseInsensitiveMap; /** * @author <a href="mailto:raf...@gm...">Rafael Ribeiro</a> * @version $Revision: 1 $ */ public class OAuthClientExecutor implements ClientExecutor { private OAuthAccessor accessor; private OAuthClient client; public OAuthClientExecutor(HttpClient httpclient, String consumerKey, String consumerSecret, String reqUrl, String authzUrl, String accessUrl) { this(httpclient, consumerKey, consumerSecret, reqUrl, authzUrl, accessUrl, null); } public OAuthClientExecutor(HttpClient httpclient, String consumerKey, String consumerSecret, String reqUrl, String authzUrl, String accessUrl, String callbackUrl) { super(); OAuthServiceProvider provider = new OAuthServiceProvider(reqUrl, authzUrl, accessUrl); OAuthConsumer consumer = new OAuthConsumer(callbackUrl, consumerKey, consumerSecret, provider); accessor = new OAuthAccessor(consumer); client = new OAuthClient(httpclient); } public ClientRequest createRequest(String uriTemplate) { return new ClientRequest(uriTemplate, this); } public ClientRequest createRequest(UriBuilder uriBuilder) { return new ClientRequest(uriBuilder, this); } public ClientResponse execute(ClientRequest request) throws Exception { OAuthMessage oauthrequest = null; //remove otherwise Authorization goes twice and OAuthFilter does not see the right one MultivaluedMap headers = request.getHeaders(); headers.remove("Authorization"); List<Entry<String,String>> parameters = new ArrayList<Entry<String,String>>(); if (request.getBody() == null) { oauthrequest = accessor.newRequestMessage(request.getHttpMethod(), request.getUri(), parameters); oauthrequest.getHeaders().addAll(asEntryList(headers)); //there should be another way of achieving this, probably some metadata read from @Consumes annotation //at least it already works... oauthrequest.getHeaders().addAll(addEntry(asEntryList(headers), "Content-Type", ((List<String>) headers.get("Accept")).get(0))); } else { ByteArrayOutputStream bos = new ByteArrayOutputStream(8192); request.writeRequestBody(headers, bos); oauthrequest = accessor.newRequestMessage(request.getHttpMethod(), request.getUri(), parameters, new ByteArrayInputStream(bos.toByteArray())); oauthrequest.getHeaders().addAll(addEntry(asEntryList(headers), "Content-Type", request.getBodyContentType().toString())); } final OAuthResponseMessage oauthresponse = (OAuthResponseMessage) client.invoke(oauthrequest, ParameterStyle.AUTHORIZATION_HEADER); BaseClientResponse response = new BaseClientResponse(new BaseClientResponseStreamFactory() { public InputStream getInputStream() throws IOException { return oauthresponse.getBodyAsStream(); } public void performReleaseConnection() { } }, this); response.setProviderFactory(request.getProviderFactory()); response.setStatus(oauthresponse.getHttpResponse().getStatusCode()); response.setHeaders(asMap(oauthresponse.getHeaders())); return response; } protected MultivaluedMap asMap(List<Entry<String,String>> headers) { MultivaluedMap result = new CaseInsensitiveMap(); for (Entry<String,String> e : headers) { result.add(e.getKey(), e.getValue()); } return result; } protected List<Entry<String,String>> asEntryList(Map<String, List<String>> headers) { List<Entry<String,String>> result = new ArrayList<Entry<String,String>>(); for (Entry<String, List<String>> e : headers.entrySet()) { for (String v : e.getValue()) { result.add(new SimpleEntry(e.getKey(), v)); } } return result; } public List<Entry<String,String>> addEntry(List<Entry<String,String>> existing, String name, String value) { return addEntry(existing, new SimpleEntry(name, value)); } public List<Entry<String,String>> addEntry(List<Entry<String,String>> existing, Entry<String,String> newHeader) { existing.add(newHeader); return existing; } } |