Browse files

Merge from pete dolye providing fixes for GRAILSPLUGINS-2459, GRAILSP…

…LUGINS-2449, GRAILSPLUGINS-2458, GRAILSPLUGINS-2457, GRAILSPLUGINS-2456, GRAILSPLUGINS-2455, GRAILSPLUGINS-2454, GRAILSPLUGINS-2453,GRAILSPLUGINS-2452, GRAILSPLUGINS-2451, GRAILSPLUGINS-2450, GRAILSPLUGINS-2449, GRAILSPLUGINS-2438, GRAILSPLUGINS-2437. In addition, small code style fixes, typos and documentation updates.
  • Loading branch information...
2 parents 4dea0b1 + 59fd951 commit 1d7185889921480049f4c3f2891f8c9d92c7be8c acampbell3000 committed Sep 8, 2010
View
16 oauth-plugin/CHANGES.txt
@@ -3,13 +3,27 @@ Version 0.10
Potential improvements:
- Unit test coverage.
-Release notes 0.10 (TBA)
+Release notes 0.10 (8th September, 2010)
+- Fix for GRAILSPLUGINS-2459, Add support for PUT/DELETE/HEAD/OPTIONS.
+- Fix for GRAILSPLUGINS-2458, Don't wrap all exceptions in OauthServiceException (Allow for easier handling of
+ different types of failures).
+- Fix for GRAILSPLUGINS-2457, Add support for signing (and not executing) custom HttpUriRequest objects.
+- Fix for GRAILSPLUGINS-2456, Add support for signing and executing custom HttpUriRequest objects.
+- Fix for GRAILSPLUGINS-2455, Add support for retrieving an HttpResponse instead of just the body.
+- Fix for GRAILSPLUGINS-2454, Add shortcut for setting Accept header.
+- Fix for GRAILSPLUGINS-2453, Add support for setting Content-Type.
+- Fix for GRAILSPLUGINS-2452, Add support for adding body content.
+- Fix for GRAILSPLUGINS-2451, Add support for adding headers.
+- Fix for GRAILSPLUGINS-2450, Use HttpClient instead of HttpURLConnection.
+- Fix for GRAILSPLUGINS-2449, Better support for REST API calls.
- Fix for GRAILSPLUGINS-2438, OauthService#getRequest(Map) does not set access token on OAuthConsumer.
- Fix for GRAILSPLUGINS-2437, OauthService should not re-use provider/consumer objects.
- Make getRequest() append params to the URL's query string. Services such as the Twitter API expect
the params as URL parameters and will ignore headers. Unfortunately, for now we still add
headers otherwise signpost doesn't seem to sign them correctly.
- Do not add params to "both" the query string and headers.
+- Code style tweaks.
+- README tweaks to provide HttpClient 4.x resources.
Release notes 0.9 (31 August, 2010)
- Fix the HttpURLConnection to apply the request method (i.e. GET, POST etc).
View
2 oauth-plugin/README.txt
@@ -324,6 +324,7 @@ documentation:
* http://oauth.net
* http://code.google.com/p/oauth-signpost
+ * http://hc.apache.org/httpcomponents-client/index.html
------------------------
Example usage
@@ -340,3 +341,4 @@ If you wish to contribute to the project you can find the full
source available on GitHub.org:
* http://wiki.github.com/dhou/grails-oauth
+
View
3 oauth-plugin/grails-app/conf/BuildConfig.groovy
@@ -14,7 +14,8 @@ grails.project.dependency.resolution = {
dependencies {
//runtime 'net.oauth:oauth-core:20090531'
- runtime 'oauth.signpost:signpost-core:1.2'
+ runtime 'oauth.signpost:signpost-core:1.2.1.1'
+ runtime 'oauth.signpost:signpost-commonshttp4:1.2.1.1'
}
plugins {
View
527 oauth-plugin/grails-app/services/org/grails/plugins/oauth/OauthService.groovy
@@ -22,16 +22,53 @@ import org.codehaus.groovy.grails.commons.ConfigurationHolder as C
import oauth.signpost.OAuth
import oauth.signpost.OAuthConsumer
import oauth.signpost.OAuthProvider
-import oauth.signpost.basic.DefaultOAuthConsumer
-import oauth.signpost.basic.DefaultOAuthProvider
-
+import oauth.signpost.commonshttp.CommonsHttpOAuthConsumer;
+import oauth.signpost.commonshttp.CommonsHttpOAuthProvider;
+
+import org.apache.http.HttpResponse
+import org.apache.http.HttpVersion
+import org.apache.http.NameValuePair
+import org.apache.http.conn.ClientConnectionManager;
+import org.apache.http.conn.scheme.PlainSocketFactory;
+import org.apache.http.conn.scheme.Scheme;
+import org.apache.http.conn.scheme.SchemeRegistry;
+import org.apache.http.conn.ssl.SSLSocketFactory;
+import org.apache.http.client.HttpClient
+import org.apache.http.client.entity.UrlEncodedFormEntity
+import org.apache.http.client.methods.HttpUriRequest;
+import org.apache.http.client.methods.HttpDelete;
+import org.apache.http.client.methods.HttpGet;
+import org.apache.http.client.methods.HttpHead;
+import org.apache.http.client.methods.HttpOptions;
+import org.apache.http.client.methods.HttpPost;
+import org.apache.http.client.methods.HttpPut;
+import org.apache.http.client.utils.URLEncodedUtils;
+import org.apache.http.entity.StringEntity
+import org.apache.http.impl.client.DefaultHttpClient
+import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager;
+import org.apache.http.message.BasicNameValuePair
+import org.apache.http.params.HttpProtocolParams
+import org.apache.http.params.HttpParams
+import org.apache.http.params.BasicHttpParams
+import org.apache.http.protocol.HTTP
+import org.apache.http.util.EntityUtils
+
+/**
+ * OAuth Service to provide OAuth functionality to a
+ * Grails application.
+ *
+ * @author Damien Hou
+ * @author Anthony Campbell (anthonycampbell.co.uk)
+ * @author Pete Doyle
+ */
class OauthService implements InitializingBean {
// Transactional service
boolean transactional = false
// Service properties
def providers = [:]
def consumers = [:]
+ private HttpClient httpClient
String callback = ""
/**
@@ -146,6 +183,29 @@ class OauthService implements InitializingBean {
}
}
+ // Release old connections on service resets
+ if (httpClient) {
+ httpClient.getConnectionManager().shutdown()
+ }
+
+ /*
+ * Prepare HTTP protocol parameters.
+ * Note: Twitter requires "expect continue" to be disabled.
+ */
+ final HttpParams clientParams = new BasicHttpParams()
+ HttpProtocolParams.setVersion(clientParams, HttpVersion.HTTP_1_1)
+ HttpProtocolParams.setContentCharset(clientParams, HTTP.UTF_8)
+ HttpProtocolParams.setUseExpectContinue(clientParams, false)
+
+ // Scheme registry
+ final SchemeRegistry schemeRegistry = new SchemeRegistry()
+ schemeRegistry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80))
+ schemeRegistry.register(new Scheme("https", SSLSocketFactory.getSocketFactory(), 443))
+
+ // Prepare connection managed and initialise new client
+ final ClientConnectionManager manager = new ThreadSafeClientConnManager(clientParams, schemeRegistry)
+ httpClient = new DefaultHttpClient(manager, clientParams)
+
log?.info "${this.getClass().getSimpleName()} intialisation complete\n"
}
@@ -160,8 +220,8 @@ class OauthService implements InitializingBean {
try {
// Get consumer and provider
- final DefaultOAuthConsumer consumer = getConsumer(consumerName)
- final DefaultOAuthProvider provider = getProvider(consumerName)
+ final OAuthConsumer consumer = getConsumer(consumerName)
+ final OAuthProvider provider = getProvider(consumerName)
// Retrieve request token
final def authorisationURL = provider?.retrieveRequestToken(consumer, callback)
@@ -192,13 +252,16 @@ class OauthService implements InitializingBean {
log.debug "Going to exchange for access token"
try {
- final DefaultOAuthConsumer consumer = getConsumer(consumerName)
- final DefaultOAuthProvider provider = getProvider(consumerName)
+ final OAuthConsumer consumer = getConsumer(consumerName)
+ final OAuthProvider provider = getProvider(consumerName)
// Set the request token
consumer.setTokenWithSecret(requestToken.key, requestToken.secret)
- // Set to OAuth 1.0a if necessary (to make signpost add 'oath_verifier' from callback to request)
+ /*
+ * Set to OAuth 1.0a if necessary (to make signpost add 'oath_verifier'
+ * from callback to request)
+ */
if (requestToken.isOAuth10a) {
provider.setOAuth10a(true)
}
@@ -213,9 +276,9 @@ class OauthService implements InitializingBean {
log.debug "Token secret: $tokenSecret\n"
if (!accessToken || !tokenSecret) {
- final def errorMessage = "Unable to fetch access token, access token is missing! " +
- "consumerName = $consumerName, requestToken = $requestToken, " +
- "accessToken = $accessToken, tokenSecret = $tokenSecret"
+ final def errorMessage = "Unable to fetch access token, access token is missing! (" +
+ "consumerName=$consumerName, requestToken=$requestToken, " +
+ "accessToken=$accessToken, tokenSecret=$tokenSecret)"
log.error(errorMessage, ex)
throw new OauthServiceException(errorMessage, ex)
@@ -224,187 +287,389 @@ class OauthService implements InitializingBean {
[key: accessToken, secret: tokenSecret]
} catch (Exception ex) {
- final def errorMessage = "Unable to fetch access token: consumerName = $consumerName, " +
- "requestToken = $requestToken"
+ final def errorMessage = "Unable to fetch access token! (consumerName=$consumerName, " +
+ "requestToken=$requestToken)"
log.error(errorMessage, ex)
throw new OauthServiceException(errorMessage, ex)
}
}
+
+ /**
+ * Helper function with default parameters to access an OAuth protected resource.
+ *
+ * @param url the url to the protected resource.
+ * @param consumer the consumer name.
+ * @param token the access token.
+ * @param method (OPTIONAL) the HTTP method to use. Defaults to 'GET'. One of 'GET',
+ * 'PUT', 'POST', 'DELETE', 'HEAD', or 'OPTIONS'.
+ * @param params (OPTIONAL) a map of parameters to add to the request.
+ * @param headers (OPTIONAL) a map of headers to add to the request.
+ * @param body (OPTIONAL) the request body.
+ * @param accept (OPTIONAL) the content type you're willing to accept (sets the Accept header).
+ * @param contentType (OPTIONAL) the content type you're sending (sets the Content-Type header).
+ *
+ * @return The response body as a {@code String}.
+ *
+ * @throws OauthServiceException
+ * If {@code method} is neither unset (defaults to 'GET') nor one of 'GET', 'PUT', 'POST',
+ * 'DELETE', 'HEAD', or 'OPTIONS'.
+ * @throws OauthServiceException
+ * If {@code args.token} does not contain both a 'key' and 'secret'.
+ * @throws OauthServiceException
+ * If {@code args.consumer} does not represent an existing consumer.
+ */
+ def accessResource(final def url, final def consumer, final def token,
+ final def method = 'GET', final def params = null, final def headers = [:],
+ final def body = null, final def accept = null, final def contentType = null) {
+
+ accessResource(url: url, consumer: consumer, token: token, method: method,
+ params: params, headers: headers, body: body, accept: accept, contentType: contentType)
+ }
/**
- * Performs a request and returns request object can be used to obtain
- * any desired request info.
+ * Helper function with named parameters to access an OAuth protected resource.
*
- * @param args access resource arguments.
+ * @param args
+ * A map of arguments to use (i.e. by using Groovy named parameters).<br/>
+ * Required arguments: url, consumer, token<br/>
+ * Valid arguments: url, consumer, token, method, params, headers, body, accept,
+ * and contentType.<br/>
+ *
+ * @return the response body as a {@code String}.
+ *
+ * @throws OauthServiceException
+ * If {@code method} is neither unset (defaults to 'GET') nor one of 'GET', 'PUT', 'POST',
+ * 'DELETE', 'HEAD', or 'OPTIONS'.
+ * @throws OauthServiceException
+ * If {@code args.token} does not contain both a 'key' and 'secret'.
+ * @throws OauthServiceException
+ * If {@code args.consumer} does not represent an existing consumer.
*/
- protected def getRequest(final def Map args) {
- // Declare request parameters
- def method
- def params
- URL url
- DefaultOAuthConsumer consumer
+ def accessResource(final def Map args) {
+ final HttpResponse response = doRequest(args)
+ String body = ""
try {
- method = args?.get('method','GET')
- params = args?.params
- url = new URL(args?.url)
- consumer = getConsumer(args?.consumer)
+ log.debug "Reading response body"
- if (!consumer) {
- final def errorMessage = "Unable to access to procected resource, invalid consumer: " +
- "method = $method, params = $params, url = $url, consumer = $consumer"
+ body = EntityUtils.toString(response.getEntity())
- log.error(errorMessage)
- throw new OauthServiceException(errorMessage)
- }
+ log.debug "Response body read successfully"
- // Attempt to retrieve token
- final def token = args?.token
- if (!token || !token?.key || !token?.secret) {
- final def errorMessage = "Unable to access to procected resource, invalid token: " +
- "method = $method, params = $params, url = $url, consumer = $consumer, " +
- "token = $token, token.key = ${token?.key}, token.secret = ${token?.secret}"
+ } catch (Exception ex) {
+ final def errorMessage = "Unable to read response from protected resource request! " +
+ "(args=$args)"
- log.error(errorMessage)
- throw new OauthServiceException(errorMessage)
- }
+ log.error(errorMessage, ex)
+ throw new OauthServiceException(errorMessage, ex)
+ }
- // Set OAuth access token and secret
- consumer.setTokenWithSecret(token.key, token.secret)
+ // Provide response
+ return body
+ }
- if (params) {
- log.debug "Putting additional params as URL params: $params"
+ /**
+ * Performs a request and returns an {@link HttpResponse} object that can be
+ * used to obtain any desired response info.
+ *
+ * @param url the url.
+ * @param consumer the consumer name.
+ * @param token the access token.
+ * @param method (OPTIONAL) the HTTP method to use. Defaults to 'GET'. One of 'GET',
+ * 'PUT', 'POST', 'DELETE', 'HEAD', or 'OPTIONS'.
+ * @param params (OPTIONAL) a map of parameters to add to the request.
+ * @param headers (OPTIONAL) a map of headers to add to the request.
+ * @param body (OPTIONAL) the request body.
+ * @param accept (OPTIONAL) the content type you're willing to accept (sets the Accept header).
+ * @param contentType (OPTIONAL) the content type you're sending (sets the Content-Type header).
+ *
+ * @return the resulting {@link HttpResponse}.
+ *
+ * @throws OauthServiceException
+ * If {@code method} is neither unset (defaults to 'GET') nor one of 'GET', 'PUT', 'POST',
+ * 'DELETE', 'HEAD', or 'OPTIONS'.
+ * @throws OauthServiceException
+ * If {@code args.token} does not contain both a 'key' and 'secret'.
+ * @throws OauthServiceException
+ * If {@code args.consumer} does not represent an existing consumer.
+ */
+ def doRequest(final def url, final String consumer, final def token,
+ final def method = 'GET', final def params = [:], final def headers = [:],
+ final def body = null, final def accept = null, final def contentType = null) {
+
+ doRequest(url: url, consumer: consumer, token: token, method: method,
+ params: params, headers: headers, body: body, accept: accept, contentType: contentType)
+ }
- StringBuffer queryParams = new StringBuffer()
- queryParams.append("?")
- params.eachWithIndex { key, value, i ->
- if( i > 0 ) {
- queryParams.append("&")
- }
+ /**
+ * <p>Helper function which allows for use of named parameters to call
+ * {@link doRequest(url, consumer, token, method, params, headers, body, contentType)}.</p>
+ *
+ * <p>Performs a request and returns an {@link HttpResponse} object that can be
+ * used to obtain any desired response info.</p>
+ *
+ * @param args
+ * A map of arguments to use (i.e. by using Groovy named parameters).<br/>
+ * Required arguments: url, consumer, token<br/>
+ * Valid arguments: url, consumer, token, method, params, headers, body, accept, and
+ * contentType.<br/>
+ *
+ * @return the resulting {@link HttpResponse}.
+ *
+ * @throws OauthServiceException
+ * If {@code method} is neither unset (defaults to 'GET') nor one of 'GET', 'PUT', 'POST',
+ * 'DELETE', 'HEAD', or 'OPTIONS'.
+ * @throws OauthServiceException
+ * If {@code args.token} does not contain both a 'key' and 'secret'.
+ * @throws OauthServiceException
+ * If {@code args.consumer} does not represent an existing consumer.
+ */
+ def doRequest(final Map args) {
+ // Declare request arguments
+ final String consumer = args.consumer
+ def url = args.url
+ def token = args.token
+ def method = args.method ?: 'GET'
+ def params = args.params ?: [:]
+ def headers = args.headers ?: [:]
+ def body = args.body
+ def accept = args.accept
+ def contentType = args.contentType
- queryParams.append(key)
- queryParams.append("=")
- queryParams.append(URLEncoder.encode("$value", "utf-8"))
- }
+ log.debug "Attempting to access protected resource"
- if (queryParams.length() > 0 ) {
- url = new URL(url.toString() + queryParams.toString())
- log.debug "URL is now: ${url.toString()}"
- }
- }
+ if (!token || !token?.key || !token?.secret) {
+ final def errorMessage = "Unable to access protected resource, invalid token! (" +
+ "method=$method, url=$url, params=$params, consumer=$consumer, " +
+ "token=$token, token.key=${token?.key}, token.secret=${token?.secret}, "
+ "headers=$headers, contentType=$contentType, " +
+ "body=${body?.length() < 100 ? body : body?.substring(0, 99) + '...'})"
- log.debug "Open connection to $url"
+ log.error(errorMessage)
+ throw new OauthServiceException(errorMessage)
+ }
- // Create an HTTP request to a protected resource
- final HttpURLConnection request = (HttpURLConnection) url.openConnection()
-
- // Set the request method (i.e. GET, POST, etc)
- request.setRequestMethod(method)
+ if (url instanceof URL) {
+ url = url?.toURI()
+ }
- // Sign the request
- consumer.sign(request)
+ // Declare request method
+ HttpUriRequest requestMethod
+
+ // Set request method
+ switch(method?.toUpperCase()) {
+ case "GET":
+ requestMethod = new HttpGet(url)
+ break;
+ case "PUT":
+ requestMethod = new HttpPut(url)
+ break;
+ case "POST":
+ requestMethod = new HttpPost(url)
+ break;
+ case "DELETE":
+ requestMethod = new HttpDelete(url)
+ break;
+ case "HEAD":
+ requestMethod = new HttpHead(url)
+ break;
+ case "OPTIONS":
+ requestMethod = new HttpOptions(url)
+ break;
+ default:
+ throw new OauthServiceException("Unsupported request method! (method=$method)")
+ break
+ }
- log.debug "Send request..."
+ // Prepare parameters
+ final List<NameValuePair> parameters = new ArrayList<NameValuePair>()
+ params?.each { k, v ->
+ log.debug("Adding param: [$k: $v]")
+ parameters.add(new BasicNameValuePair("$k", "$v"))
+ }
- // Send the request
- request.connect()
+ // Set the parameters on the request
+ if (parameters.size() > 0) {
+ // POST with params, no body, and no contentType should use x-www-form-urlencoded
+ if (!body && (!contentType || contentType?.equalsIgnoreCase("x-www-form-urlencoded")) &&
+ method == "POST") {
+ log.debug("POSTing params in an 'x-www-form-urlencoded' body")
+ UrlEncodedFormEntity formEncodedEntity = new UrlEncodedFormEntity(parameters, HTTP.UTF_8)
+ requestMethod.setEntity(formEncodedEntity)
+
+ } else {
+ final def queryString = "?" + URLEncodedUtils.format(parameters, HTTP.UTF_8)
+ log.debug("Adding params as query string (queryString=$queryString)")
+ requestMethod.setURI(new URI(requestMethod.getURI()?.toString() + queryString))
+ }
+ }
- log.debug "Return request...\n"
+ // Set the body
+ if (body) {
+ log.debug("Set body content as request entity")
+ requestMethod.setEntity(new StringEntity(body))
+ }
- // Return the request
- request
+ // Set the headers
+ headers?.each { k, v ->
+ log.debug("Adding header: [$k: $v]")
+ requestMethod.addHeader("$k", "$v")
+ }
- } catch (Exception ex) {
- final def errorMessage = "Unable to access to procected resource: method = $method, " +
- "params = $params, url = $url, consumer = $consumer"
+ // Set the Content-Type header
+ if (contentType) {
+ log.debug("Set the Content-Type header to '$contentType'")
+ requestMethod.setHeader(HTTP.CONTENT_TYPE, "$contentType")
+ }
- log.error(errorMessage, ex)
- throw new OauthServiceException(errorMessage, ex)
+ // Set the Accept header
+ if (accept) {
+ log.debug("Set the Accept header to '$accept'")
+ requestMethod.setHeader("Accept", "$accept")
}
+
+ // Sign, execute and return HttpResponse
+ execute(requestMethod, consumer, token)
}
/**
- * Helper function with default parameters to access an OAuth protected resource.
+ * Signs the given {@link HttpUriRequest}, executes it, and returns the
+ * {@link HttpResponse}. A utility method which allows for custom setup
+ * of any {@link HttpUriRequest} request.
+ *
+ * @param request
+ * The {@link HttpUriRequest} (for example, an {@link HttpGet} or {@link HttpPost}).
+ * @param consumerName
+ * The name of the consumer.
+ * @param accessToken
+ * The access token. An object (usually a Map) containing a 'key' and a 'secret'.
+ * @return The {@link HttpResponse}
*
- * @param url URL to the protected resource.
- * @param consumer the consumer.
- * @param token the access token.
- * @param method HTTP method, whether to use POST or GET.
- * @param params any request parameters.
- * @return the response from the server.
+ * @throws OauthServiceException
+ * If {@code accessToken} does not contain both a 'key' and 'secret'.
+ * @throws OauthServiceException
+ * If {@code consumerName} does not represent an existing consumer.
*/
- def accessResource(final def url, final def consumer, final def token,
- final def method = 'GET', final def params = null) {
+ def HttpResponse execute(final HttpUriRequest request, final String consumerName,
+ final def accessToken) {
+ // Validate token
+ assertAccessToken(accessToken)
+
+ log.debug("Executing ${request?.getMethod()} to ${request?.getURI()}")
- accessResource(url: url, consumer: consumer, token: token, method: method, params: params)
+ try {
+ // Sign the request
+ sign(request, consumerName, accessToken)
+
+ // Execute it, return the HttpResponse
+ httpClient.execute(request)
+
+ } catch (Exception ex) {
+ final def errorMessage = "Unable to sign execute HTTP method! (request=$request, " +
+ "consumerName=$consumerName, accessToken=$accessToken)"
+
+ log.error(errorMessage, ex)
+ throw new OauthServiceException(errorMessage, ex)
+ }
}
-
+
/**
- * Helper function with named parameters to access an OAuth protected resource.
+ * Signs the given {@link HttpUriRequest} without executing it.
+ * This method allows you to set up any {@link HttpUriRequest} to your
+ * specifications, sign it, then later execute it using your own instance of
+ * {@link HttpClient} (i.e. using custom {@link HttpParams}).
*
- * @param args access resource arguments.
- * @return the response from the server.
+ * @param request
+ * The {@link HttpUriRequest} to sign (i.e. {@link HttpGet}, {@link HttpPost}, etc.
+ * @param consumerName
+ * The name of the consumer.
+ * @param accessToken
+ * The access token. An object (usually a Map) containing a 'key' and a 'secret'.
+ *
+ * @throws OauthServiceException
+ * If {@code accessToken} does not contain both a 'key' and 'secret'.
+ * @throws OauthServiceException
+ * If {@code consumerName} does not represent an existing consumer.
*/
- def accessResource(final def Map args) {
- log.debug "Attempting to access protected resource"
-
- // Declare response variables
- BufferedReader streamReader
- StringBuilder response
- String line
+ def sign(final HttpUriRequest request, final String consumerName, final def accessToken) {
+ // Check access token is valid
+ assertAccessToken(accessToken)
try {
- // Get input stream from request
- streamReader = new BufferedReader(
- new InputStreamReader(getRequest(args).getInputStream())
- );
-
- // Read response
- log.debug "Initialized request reader"
- response = new StringBuilder();
- while ((line = streamReader.readLine()) != null) {
- response.append(line + "\n")
- }
-
- // Return
- log.debug "Content read successfully"
- response.toString()
+ final OAuthConsumer consumer = getConsumer(consumerName)
+ consumer.setTokenWithSecret(accessToken.key, accessToken.secret)
+ consumer.sign(request)
- } catch (Exception ex) { // Should be only IOException here
- final def errorMessage = "Unable to read data from procected resource: " +
- "args = $args"
+ } catch (Exception ex) {
+ final def errorMessage = "Unable to sign HTTP request! (request=$request, " +
+ "consumerName=$consumerName, accessToken=$accessToken)"
log.error(errorMessage, ex)
throw new OauthServiceException(errorMessage, ex)
-
- } finally {
- streamReader = null
- response = null
- line = null
}
}
-
+
/**
* Returns the current consumer for the provided name.
*
* @param consumerName the consumer name.
* @return the consumer instance by name.
+ *
+ * @throws OauthServiceException
+ * If {@code consumerName} does not represent an existing consumer.
*/
- def getConsumer(final def consumerName) {
+ private def getConsumer(final String consumerName) {
+ // Get values
final def consumerValues = consumers[consumerName]
- return new DefaultOAuthConsumer(consumerValues.key, consumerValues.secret )
+
+ // Validate
+ if (!consumerValues) {
+ throw new OauthServiceException("Unknown consumer: '$consumerName'")
+ }
+
+ // Initialise new consumer
+ return new CommonsHttpOAuthConsumer(consumerValues.key, consumerValues.secret)
}
/**
* Returns the current provider for the provided consumer.
*
- * @param consumerName the consumer name.
+ * @param providerName the provider name.
* @return the provider instance by name.
+ *
+ * @throws OauthServiceException
+ * If {@code providerName} does not represent an existing provider.
*/
- def getProvider(final def consumerName) {
- final def providerValues = providers[consumerName]
- return new DefaultOAuthProvider(providerValues.requestTokenUrl, providerValues.accessTokenUrl,
- providerValues.authUrl)
+ private def getProvider(final String providerName) {
+ // Get values
+ final def providerValues = providers[providerName]
+
+ // Validate
+ if (!providerValues) {
+ throw new OauthServiceException("Unknown provider! (providerName=$providerName)")
+ }
+
+ // Initialise new provider
+ return new CommonsHttpOAuthProvider(providerValues.requestTokenUrl,
+ providerValues.accessTokenUrl, providerValues.authUrl, httpClient)
}
+
+ /**
+ * Validate the provided OAuth access token.
+ *
+ * Simple check to see that the provided token also contains a token and secret.
+ *
+ * @param the token to validate.
+ * @throws OauthServiceException when provided token is invalid.
+ */
+ private def assertAccessToken(def token) {
+ if (!token || !token?.key || !token?.secret) {
+ final def errorMessage = "Invalid access token! (token=$token, token.key=${token?.key}, " +
+ "token.secret=${token?.secret})"
+
+ log.error(errorMessage)
+ throw new OauthServiceException(errorMessage)
+ }
+ }
}

0 comments on commit 1d71858

Please sign in to comment.