Author: ivol37 at gmail.com
Date: Thu Dec  2 15:47:28 2010
New Revision: 471

Log:
[AMDATU-181] Added oAuth to the reactor build. This implementation now provides 
a basic implementation of an oAuth server and API. Stuff that remains to be 
done but covered by other issues:

- The service consumer registry is not yet persistent. For the moment it stores 
the service consumers in memory. (AMDATU-201)
- The authorization token part of the process is currently a micky mouse 
example. By simply posting a form holding the userid, a request token can be 
authorized for that user id. This needs to be connected to the Amdatu login 
service, or even to a pluggable login service. (AMDATU-202)
- Provide external REST service to validate OAuth messages and retrieve context 
information like userid and consumer key (AMDATU-203)
- Finalize REST API for CRUD operations on service consumers (add HTTP caching 
headers and authorization)(AMDATU-204)
- Support two-legged oAuth (AMDATU-182)
- Explore the possibilities to add additional information to the oAuth tokens, 
like a tenant id.

Added:
   
trunk/amdatu-core/config-filebased/src/main/resources/conf/org.amdatu.authentication.oauth.server.cfg
   
trunk/integration-tests/src/test/java/org/amdatu/test/integration/mock/OAuthProtectedTestServlet.java
   
trunk/integration-tests/src/test/java/org/amdatu/test/integration/mock/OAuthTestConsumer.java
   
trunk/integration-tests/src/test/java/org/amdatu/test/integration/tests/OAuthClientTest.java
   
trunk/integration-tests/src/test/java/org/amdatu/test/integration/tests/OAuthServiceConsumerRegistryTest.java
Modified:
   
trunk/amdatu-authentication/oauth-client/src/main/java/org/amdatu/authentication/oauth/client/OAuthResourceOwnerClient.java
   
trunk/amdatu-authentication/oauth-client/src/main/java/org/amdatu/authentication/oauth/client/OAuthServiceConsumerClient.java
   
trunk/amdatu-authentication/oauth-client/src/main/java/org/amdatu/authentication/oauth/client/internal/OAuthClientBase.java
   
trunk/amdatu-authentication/oauth-client/src/main/java/org/amdatu/authentication/oauth/client/osgi/Activator.java
   
trunk/amdatu-authentication/oauth-server/src/main/java/org/amdatu/authentication/oauth/server/OAuthAccessTokenServlet.java
   
trunk/amdatu-authentication/oauth-server/src/main/java/org/amdatu/authentication/oauth/server/OAuthAuthorizeTokenServlet.java
   
trunk/amdatu-authentication/oauth-server/src/main/java/org/amdatu/authentication/oauth/server/OAuthRequestTokenServlet.java
   
trunk/amdatu-authentication/oauth-server/src/main/java/org/amdatu/authentication/oauth/server/OAuthServerConfig.java
   
trunk/amdatu-authentication/oauth-server/src/main/java/org/amdatu/authentication/oauth/server/OAuthServiceConsumerRegistry.java
   
trunk/amdatu-authentication/oauth-server/src/main/java/org/amdatu/authentication/oauth/server/OAuthTokenProvider.java
   
trunk/amdatu-authentication/oauth-server/src/main/java/org/amdatu/authentication/oauth/server/osgi/Activator.java
   
trunk/amdatu-authentication/oauth-server/src/main/java/org/amdatu/authentication/oauth/server/service/OAuthAccessTokenServletImpl.java
   
trunk/amdatu-authentication/oauth-server/src/main/java/org/amdatu/authentication/oauth/server/service/OAuthAuthorizeTokenServletImpl.java
   
trunk/amdatu-authentication/oauth-server/src/main/java/org/amdatu/authentication/oauth/server/service/OAuthServiceConsumerBean.java
   
trunk/amdatu-authentication/oauth-server/src/main/java/org/amdatu/authentication/oauth/server/service/OAuthServiceConsumerRegistryImpl.java
   
trunk/amdatu-authentication/oauth-server/src/main/java/org/amdatu/authentication/oauth/server/service/OAuthServiceConsumerRegistryREST.java
   
trunk/amdatu-authentication/oauth-server/src/main/java/org/amdatu/authentication/oauth/server/service/OAuthServiceProviderImpl.java
   
trunk/amdatu-authentication/oauth-server/src/main/java/org/amdatu/authentication/oauth/server/service/OAuthTokenProviderImpl.java
   trunk/amdatu-release/pom.xml
   trunk/amdatu-release/src/main/assembly/bin-component.xml
   trunk/integration-tests/pom.xml
   
trunk/integration-tests/src/test/java/org/amdatu/test/integration/base/ConfigProvider.java
   
trunk/integration-tests/src/test/java/org/amdatu/test/integration/base/IntegrationTestBase.java
   trunk/pom.xml
   trunk/src/main/resources/conf/felix-config.properties

Modified: 
trunk/amdatu-authentication/oauth-client/src/main/java/org/amdatu/authentication/oauth/client/OAuthResourceOwnerClient.java
==============================================================================
--- 
trunk/amdatu-authentication/oauth-client/src/main/java/org/amdatu/authentication/oauth/client/OAuthResourceOwnerClient.java
 (original)
+++ 
trunk/amdatu-authentication/oauth-client/src/main/java/org/amdatu/authentication/oauth/client/OAuthResourceOwnerClient.java
 Thu Dec  2 15:47:28 2010
@@ -33,61 +33,82 @@
 import org.apache.commons.httpclient.NameValuePair;
 import org.apache.commons.httpclient.methods.PostMethod;
 
+/**
+ * This class provides a client API to be used by resource owners for invoking 
a OAuth server.
+ * Note that the only actual task of a resource owner (in other words: user) 
is authorizing
+ * the request token in a three-legged oAuth dance. Therefore this client API 
only provides
+ * one method, which can be used to authorize a request token for a specific 
user id.
+ * 
+ * @author ivol
+ */
 public class OAuthResourceOwnerClient extends OAuthClientBase {
     /**
-     * Create a new oAuth consumer client for the specified service consumer 
and service provider.
+     * Create a new oAuth resource owner client for the specified service 
consumer and service provider.
+     * Once created, using this API only tokens can be authorized for this 
specified service consumer
+     * and service provider. If you need to authorize different tokens, you 
will need to construct a
+     * new resource client.
      * 
-     * @param provider The oAuth service provider
-     * @param consumer The oAuth service consumer
+     * @param provider The oAuth service provider that provides the request 
token to be authorized by
+     *        this client
+     * @param consumer The oAuth service consumer for which tokens are 
authorized such that the
+     *        service consumer can retrieve an access token from the service 
provider
      */
     public OAuthResourceOwnerClient(OAuthServiceProvider provider, 
OAuthServiceConsumer consumer) {
         super(provider, consumer);
     }
 
     /**
-        * Authorizes a request token with the specified userId without user 
interaction. 
-        * @param accessor
-        * @param userId
-        * @return
-        * @throws IOException
-        * @throws URISyntaxException
-        * @throws OAuthException
-        * @return The callback url, if the service consumer provided it
-        */
-       public String authorizeToken(OAuthAccessor accessor, String userId) 
throws IOException, URISyntaxException, OAuthException {
-               Map<String, String> paramProps = new HashMap<String, String>();
-               paramProps.put("oauth_token", accessor.requestToken);
-               OAuthMessage response = sendRequest(accessor, paramProps, 
getProvider().getAuthorizeTokenURL());
+     * Authorizes a request token with the specified userId. Note that using 
this client no user
+     * interaction is required to be able to authorize a token.
+     * 
+     * @param accessor The OAuth accessor which contains the request token to 
be authorized. The
+     *        accessor is returned when the request token is received using 
the service consumer client API.
+     * @param userId The id of the user to authorize the token with. The 
userid will become part of
+     *        the access token such that the service provider can retrieve the 
userid and perform
+     *        authorization checks.
+     * @return The callback URL of the service consumer.
+     * @throws IOException In case a I/O exception occurred
+     * @throws URISyntaxException In case some URL could not be parsed
+     * @throws OAuthException If the received request token is invalid
+     * @return The callback url, if the service consumer provided it
+     */
+    public String authorizeToken(OAuthAccessor accessor, String userId) throws 
IOException, URISyntaxException,
+        OAuthException {
+        Map<String, String> paramProps = new HashMap<String, String>();
+        paramProps.put("oauth_token", accessor.requestToken);
+        OAuthMessage response = sendRequest(accessor, paramProps, 
getProvider().getAuthorizeTokenURL());
 
-               // Now the result is an authorization page containing an HTML 
form we are supposed to submit
-               // First read the token and callback from this form
-               String sResponseBody = response.readBodyAsString();
-               String tokenStart = "<input type=\"hidden\" 
name=\"oauth_token\" value=\"";
-               String token = 
sResponseBody.substring(sResponseBody.indexOf(tokenStart) + 
tokenStart.length());
-               token = token.substring(0, token.indexOf("\""));
+        // Now the result is an authorization page containing an HTML form we 
are supposed to submit
+        // First read the token and callback from this form
+        String sResponseBody = response.readBodyAsString();
+        String tokenStart = "<input type=\"hidden\" name=\"oauth_token\" 
value=\"";
+        String token = 
sResponseBody.substring(sResponseBody.indexOf(tokenStart) + 
tokenStart.length());
+        token = token.substring(0, token.indexOf("\""));
 
-               String callbackStart = "<input type=\"hidden\" 
name=\"oauth_callback\" value=\"";
-               String callback = 
sResponseBody.substring(sResponseBody.indexOf(callbackStart) + 
callbackStart.length());
-               callback = callback.substring(0, callback.indexOf("\""));
+        String callbackStart = "<input type=\"hidden\" name=\"oauth_callback\" 
value=\"";
+        String callback = 
sResponseBody.substring(sResponseBody.indexOf(callbackStart) + 
callbackStart.length());
+        callback = callback.substring(0, callback.indexOf("\""));
 
-               // Now build the post request
-               HttpClient httpClient = new HttpClient();
-               NameValuePair[] data = {
-                               new NameValuePair("userId", userId),
-                               new NameValuePair("oauth_token", token),
-                               new NameValuePair("oauth_callback", callback)
-               };
-               PostMethod postMethod = new 
PostMethod(getProvider().getAuthorizeTokenURL());
-               postMethod.setRequestBody(data);
-               int status = httpClient.executeMethod(postMethod);
-               if (status == HttpStatus.SC_OK) {
-                   // Status 200 means authorize token went OK, but service 
consumer did not specify a callback URL
-                   return null;
-               } else if (status == HttpStatus.SC_MOVED_TEMPORARILY) {
-                   // Status 302 means that we are being redirected to the 
callback url provided by the service consumer
-                   return postMethod.getResponseHeader("Location").getValue();
-               } else {
-                       throw new OAuthException("Authorize token form returned 
" + status);
-               }
-       }
+        // Now build the post request
+        HttpClient httpClient = new HttpClient();
+        NameValuePair[] data = {
+            new NameValuePair("userId", userId),
+            new NameValuePair("oauth_token", token),
+            new NameValuePair("oauth_callback", callback)
+            };
+        PostMethod postMethod = new 
PostMethod(getProvider().getAuthorizeTokenURL());
+        postMethod.setRequestBody(data);
+        int status = httpClient.executeMethod(postMethod);
+        if (status == HttpStatus.SC_OK) {
+            // Status 200 means authorize token went OK, but service consumer 
did not specify a callback URL
+            return null;
+        }
+        else if (status == HttpStatus.SC_MOVED_TEMPORARILY) {
+            // Status 302 means that we are being redirected to the callback 
url provided by the service consumer
+            return postMethod.getResponseHeader("Location").getValue();
+        }
+        else {
+            throw new OAuthException("Authorize token form returned " + 
status);
+        }
+    }
 }

Modified: 
trunk/amdatu-authentication/oauth-client/src/main/java/org/amdatu/authentication/oauth/client/OAuthServiceConsumerClient.java
==============================================================================
--- 
trunk/amdatu-authentication/oauth-client/src/main/java/org/amdatu/authentication/oauth/client/OAuthServiceConsumerClient.java
       (original)
+++ 
trunk/amdatu-authentication/oauth-client/src/main/java/org/amdatu/authentication/oauth/client/OAuthServiceConsumerClient.java
       Thu Dec  2 15:47:28 2010
@@ -20,7 +20,6 @@
 import java.net.URISyntaxException;
 import java.util.HashMap;
 import java.util.Map;
-import java.util.Properties;
 
 import net.oauth.OAuth;
 import net.oauth.OAuthAccessor;
@@ -43,25 +42,24 @@
 public class OAuthServiceConsumerClient extends OAuthClientBase {
     /**
      * Create a new oAuth consumer client for the specified service consumer 
and service provider.
-     * 
-     * @param provider The oAuth service provider
-     * @param consumer The oAuth service consumer
+     * Once created, using this API only tokens can be generated for this 
specified service consumer
+     * and service provider. If you need to authorize different tokens, you 
will need to construct a
+     * new consumer client.
+     * @param provider The oAuth service provider to invoke to receive the 
request and access tokens
+     * @param consumer The oAuth service consumer for which to generate the 
request and access tokens.
      */
     public OAuthServiceConsumerClient(OAuthServiceProvider provider, 
OAuthServiceConsumer consumer) {
         super(provider, consumer);
     }
 
     /**
-     * Generates a request token and returns an OAuthAccessor which contains 
the generated token. To create a
-     * request token
-     * 
-     * @param consumerKey The key that identifies the service consumer
-     * @param consumerSecret The secret that belongs to the consumer key
-     * @param callbackUrl The URL
-     * @return
-     * @throws IOException
-     * @throws OAuthException
-     * @throws URISyntaxException
+     * Generates a new request token and returns an OAuthAccessor which 
contains the generated token.
+     * The request token will be available in accessor.requestToken and the 
corresponding token secret
+     * in accessor.tokenSecret.
+     * @return The OAuth accessor containing the request token and associated 
token secret.
+     * @throws IOException In case a I/O exception occurred
+     * @throws OAuthException In case the request token could not be generated.
+     * @throws URISyntaxException In case some URL could not be parsed
      */
     public OAuthAccessor generateRequestToken() throws IOException, 
OAuthException, URISyntaxException {
         OAuthAccessor accessor = createAccessor();
@@ -71,27 +69,47 @@
     }
 
     /**
-     * Exchanges the request token for an access token.
+     * Exchanges the request token for an access token. Note that the request 
token must be authorized 
+     * (for example by using the resource owner client) before this method is 
invoked. If the token 
+     * is not yet authorized, an OAuthException will be thrown.
      * 
-     * @param accessor
-     * @return
-     * @throws IOException
-     * @throws URISyntaxException
-     * @throws OAuthException
+     * @param accessor The OAuth accessor containing the request token and 
associated token secret.
+     * @return The result OAut message, containing the access token 
(message.getToken() and associated 
+     * token secret (message.getParameter("oauth_token_secret"))
+     * @throws IOException In case a I/O exception occurred
+     * @throws URISyntaxException In case some URL could not be parsed
+     * @throws OAuthException In case the request token in the accessor is 
invalid or not yet authorized
      */
-    public OAuthMessage getAccessToken(OAuthAccessor accessor ) throws 
IOException, URISyntaxException, OAuthException {
+    public OAuthMessage getAccessToken(OAuthAccessor accessor) throws 
IOException, URISyntaxException, OAuthException {
         Map<String, String> paramProps = new HashMap<String, String>();
         paramProps.put("oauth_token", accessor.requestToken);
         OAuthMessage response = sendRequest(accessor, paramProps, 
getProvider().getAccessTokenURL());
         return response;
     }
     
+    /**
+     * Access a protected resource which is hosted by the specified URL. The 
accessor passed must 
+     * provide the access token and associated token secret received before by 
performing an 
+     * oAuth negotiation (request token, authorize token and access token). 
This method 
+     * @param accessor The OAuth accessor holding the access token and 
associated token secret to
+     * use for invoking the protected resource.
+     * @param url The URL to invoke (currently only a GET to this URL is 
supported)
+     * @return An OAuth message encapsulating the result of the http method 
call.
+     * @throws IOException In case a I/O exception occurred
+     * @throws URISyntaxException In case some URL could not be parsed
+     * @throws OAuthException  In case the request token in the accessor is 
invalid or not yet authorized
+     */
     public OAuthMessage accessResource(OAuthAccessor accessor, String url) 
throws IOException, URISyntaxException, OAuthException {
         Map<String, String> paramProps = new HashMap<String, String>();
         paramProps.put("oauth_token", accessor.accessToken);
         return sendRequest(accessor, paramProps, url);
     }
 
+    /**
+     * Converts accessor attributes to a String.
+     * @param accessor The OAuth accessor to convert
+     * @return Attributes of the OAuth accessor represented as a single String
+     */
     public String toString(OAuthAccessor accessor) {
         String result = "";
         result += OAuth.OAUTH_TOKEN + "=" + 
accessor.getProperty(OAuth.OAUTH_TOKEN) + " ";

Modified: 
trunk/amdatu-authentication/oauth-client/src/main/java/org/amdatu/authentication/oauth/client/internal/OAuthClientBase.java
==============================================================================
--- 
trunk/amdatu-authentication/oauth-client/src/main/java/org/amdatu/authentication/oauth/client/internal/OAuthClientBase.java
 (original)
+++ 
trunk/amdatu-authentication/oauth-client/src/main/java/org/amdatu/authentication/oauth/client/internal/OAuthClientBase.java
 Thu Dec  2 15:47:28 2010
@@ -33,6 +33,11 @@
 import org.amdatu.authentication.oauth.api.OAuthServiceConsumer;
 import org.amdatu.authentication.oauth.api.OAuthServiceProvider;
 
+/**
+ * This is the base class for OAuth clients.
+ * 
+ * @author ivol
+ */
 public class OAuthClientBase {
     private OAuthServiceProvider m_oAuthServiceProvider;
     private OAuthServiceConsumer m_oAuthServiceConsumer;

Modified: 
trunk/amdatu-authentication/oauth-client/src/main/java/org/amdatu/authentication/oauth/client/osgi/Activator.java
==============================================================================
--- 
trunk/amdatu-authentication/oauth-client/src/main/java/org/amdatu/authentication/oauth/client/osgi/Activator.java
   (original)
+++ 
trunk/amdatu-authentication/oauth-client/src/main/java/org/amdatu/authentication/oauth/client/osgi/Activator.java
   Thu Dec  2 15:47:28 2010
@@ -21,18 +21,14 @@
 import org.osgi.framework.BundleContext;
 
 /**
- * This is the activator for the authorization bundle
+ * This is the activator for the authentication bundle.
+ * 
  * @author ivol
  */
 public class Activator extends DependencyActivatorBase {
-
-
-    @Override
     public void init(BundleContext context, DependencyManager manager) throws 
Exception {
     }
 
- 
-    @Override
     public void destroy(BundleContext context, DependencyManager manager) 
throws Exception {
     }
 }

Modified: 
trunk/amdatu-authentication/oauth-server/src/main/java/org/amdatu/authentication/oauth/server/OAuthAccessTokenServlet.java
==============================================================================
--- 
trunk/amdatu-authentication/oauth-server/src/main/java/org/amdatu/authentication/oauth/server/OAuthAccessTokenServlet.java
  (original)
+++ 
trunk/amdatu-authentication/oauth-server/src/main/java/org/amdatu/authentication/oauth/server/OAuthAccessTokenServlet.java
  Thu Dec  2 15:47:28 2010
@@ -18,6 +18,11 @@
 
 import 
org.amdatu.authentication.oauth.server.service.OAuthResourceProviderImpl;
 
+/**
+ * Represents the servlet that is responsible for generating OAuth access 
tokens.
+ * 
+ * @author ivol
+ */
 public interface OAuthAccessTokenServlet {
     /**
      * The servlet alias of the access token servlet.

Modified: 
trunk/amdatu-authentication/oauth-server/src/main/java/org/amdatu/authentication/oauth/server/OAuthAuthorizeTokenServlet.java
==============================================================================
--- 
trunk/amdatu-authentication/oauth-server/src/main/java/org/amdatu/authentication/oauth/server/OAuthAuthorizeTokenServlet.java
       (original)
+++ 
trunk/amdatu-authentication/oauth-server/src/main/java/org/amdatu/authentication/oauth/server/OAuthAuthorizeTokenServlet.java
       Thu Dec  2 15:47:28 2010
@@ -18,9 +18,14 @@
 
 import 
org.amdatu.authentication.oauth.server.service.OAuthResourceProviderImpl;
 
+/**
+ * Represents the servlet that is responsible for authorizing OAuth request 
tokens.
+ * 
+ * @author ivol
+ */
 public interface OAuthAuthorizeTokenServlet {
     /**
-     * The servlet alias of the request token servlet.
+     * The servlet alias of the authorize token servlet.
      */
     final static String SERVLET_ALIAS = "/" + 
OAuthResourceProviderImpl.RESOURCE_ID + "/authorizetoken";
 }

Modified: 
trunk/amdatu-authentication/oauth-server/src/main/java/org/amdatu/authentication/oauth/server/OAuthRequestTokenServlet.java
==============================================================================
--- 
trunk/amdatu-authentication/oauth-server/src/main/java/org/amdatu/authentication/oauth/server/OAuthRequestTokenServlet.java
 (original)
+++ 
trunk/amdatu-authentication/oauth-server/src/main/java/org/amdatu/authentication/oauth/server/OAuthRequestTokenServlet.java
 Thu Dec  2 15:47:28 2010
@@ -18,6 +18,11 @@
 
 import 
org.amdatu.authentication.oauth.server.service.OAuthResourceProviderImpl;
 
+/**
+ * Represents the servlet that is responsible for generating OAuth request 
tokens.
+ * 
+ * @author ivol
+ */
 public interface OAuthRequestTokenServlet {
     /**
      * The servlet alias of the request token servlet.

Modified: 
trunk/amdatu-authentication/oauth-server/src/main/java/org/amdatu/authentication/oauth/server/OAuthServerConfig.java
==============================================================================
--- 
trunk/amdatu-authentication/oauth-server/src/main/java/org/amdatu/authentication/oauth/server/OAuthServerConfig.java
        (original)
+++ 
trunk/amdatu-authentication/oauth-server/src/main/java/org/amdatu/authentication/oauth/server/OAuthServerConfig.java
        Thu Dec  2 15:47:28 2010
@@ -16,6 +16,11 @@
  */
 package org.amdatu.authentication.oauth.server;
 
+/**
+ * Holds the PID and property names of the configuration properties stored in 
Config Admin.
+ * 
+ * @author ivol
+ */
 public class OAuthServerConfig {
     /**
      * The PID of the configuration of this service.

Modified: 
trunk/amdatu-authentication/oauth-server/src/main/java/org/amdatu/authentication/oauth/server/OAuthServiceConsumerRegistry.java
==============================================================================
--- 
trunk/amdatu-authentication/oauth-server/src/main/java/org/amdatu/authentication/oauth/server/OAuthServiceConsumerRegistry.java
     (original)
+++ 
trunk/amdatu-authentication/oauth-server/src/main/java/org/amdatu/authentication/oauth/server/OAuthServiceConsumerRegistry.java
     Thu Dec  2 15:47:28 2010
@@ -22,7 +22,10 @@
  * The oAuth server uses a service consumer registry to identify from which 
consumers
  * token requests are received. Each token request holds the consumer key such 
that the
  * oAuth server knows which consumer is asking for access. Tokens will only be 
distributed
- * to service conusmers that are known in this registry.
+ * to service consumers that are known in this registry. It is up to the 
resource itself (or service
+ * that manipulates the resource) to do something (i.e. authorization checks) 
with this information.
+ * Based on the consumer key and user id stored in the OAuth request the 
resource can decide to
+ * allow or disallow to apply a certain operation for a specific consumer and 
user.
  * 
  * @author ivol
  */
@@ -32,7 +35,7 @@
      * a ConsumerNotFoundException is thrown.
      * @param consumerKey Key of the consumer to find
      * @return The consumer if found
-     * @throws ConsumerNotFoundException If tno consumer could be found 
matching the specified consumer key
+     * @throws ConsumerNotFoundException If no consumer could be found 
matching the specified consumer key
      */
     OAuthServiceConsumer getConsumer(String consumerKey) throws 
ConsumerNotFoundException;
     

Modified: 
trunk/amdatu-authentication/oauth-server/src/main/java/org/amdatu/authentication/oauth/server/OAuthTokenProvider.java
==============================================================================
--- 
trunk/amdatu-authentication/oauth-server/src/main/java/org/amdatu/authentication/oauth/server/OAuthTokenProvider.java
       (original)
+++ 
trunk/amdatu-authentication/oauth-server/src/main/java/org/amdatu/authentication/oauth/server/OAuthTokenProvider.java
       Thu Dec  2 15:47:28 2010
@@ -31,74 +31,83 @@
 
 /**
  * Interface of an oAuth token provider. A oAuth token provider provides 
request and access tokens and facilitates
- * marking access token as authorized.
+ * marking access token as authorized. The token provider therefore contacts 
its consumer registry, tokens are only
+ * distributed for service consumers known in this registry.
+ * 
  * @author ivol
- *
  */
 public interface OAuthTokenProvider {
     /**
-     * Returns an oAtuth consumer that matched the consumer key as defined in 
the oAuth message. The oAuth message
-     * is generated from a normal http request, but contains only the oAuth 
headers that are relevant to oAuth.
+     * Returns an oAuth consumer that matches the consumer key as defined in 
the oAuth message. The oAuth message
+     * is generated from a normal HTTP request, but contains only the oAuth 
headers that are relevant to oAuth.
+     * 
      * @param requestMessage The oAuth request message
      * @return The consumer that matches the consumer key in the oAuth message
-     * @throws IOException
-     * @throws OAuthProblemException
+     * @throws IOException In case a I/O exception occurred
+     * @throws OAuthProblemException In case validation of the OAuth message 
failed
      */
     OAuthConsumer getConsumer(OAuthMessage requestMessage) throws IOException, 
OAuthProblemException;
-    
+
     /**
-     * Returns the oAuth validator. The validator facilitates validating 
received oAuth messages. Validation includes 
+     * Returns the oAuth validator. The validator facilitates validating 
received oAuth messages. Validation includes
      * checking if the token is expired, if the nonce is valid and if the 
provided (encrypted) consumer secret is correct.
-     * @return The OAuthValidator
+     * 
+     * @return The OAuth validator class which can be used to validate OAuth 
messages.
      */
     OAuthValidator getOAuthValidator();
-    
+
     /**
      * Generates a new fresh request token for the given accessor. An accessor 
holds the service consumer and
-     * adds the request token, token secret and access token.
-     * @param accessor
-     * @throws OAuthException
+     * service provider, this method sets the request token and corresponding 
token secret in the accessor.
+     * 
+     * @param accessor The OAuth accessor holding information about the 
service consumer.
+     * @throws OAuthException In case information in the provided accessor is 
invalid.
      */
     void generateRequestToken(OAuthAccessor accessor) throws OAuthException;
-    
+
     /**
-     * An accessor contains provided tokens for a specific service consumer. 
When a request token is generated, an 
-     * accessor is added for the service consumer holding the request token 
and token secret. So an accessor is a 
-     * kind of 'oAuth session'. When the request token is authorized, the 
access token is added to the accessor. 
+     * An accessor contains provided tokens for a specific service consumer. 
When a request token is generated, the
+     * request token and token secret are added tp the accessor. When a 
request token is exchanged for an access token,
+     * the request token is removed from the accessor and the access token and 
associated token secret are added.
+     * So an accessor is a kind of 'oAuth session'.
      * This method returns the accessor from the given oAuth message, which 
holds the relevant oAuth headers
      * posted in the oAuth request.
+     * 
      * @return The accessor, holding the distributed tokens for a particular 
oAuth session for a service consumer
      */
     OAuthAccessor getAccessor(OAuthMessage requestMessage) throws IOException, 
OAuthProblemException;
-    
+
     /**
      * Handles an exception thrown by any token servlet.
-     * @param e
-     * @param request
-     * @param response
-     * @param sendBody
-     * @throws IOException
-     * @throws ServletException
+     * 
+     * @param e The exception thrown
+     * @param request The HTTP servlet request
+     * @param response The HTTP servlet responde
+     * @param sendBody Whether information about the cause of the exception 
must be set in the
+     *        mesasge body or not
+     * @throws IOException In case of a I/O exception
+     * @throws ServletException In case of a servlet exception
      */
     void handleException(Exception e, HttpServletRequest request, 
HttpServletResponse response,
         boolean sendBody) throws IOException, ServletException;
-    
+
     /**
-     * Marks the request token as authorized. The accessor represents the 
generated tokens for the service 
-     * consumer and the userId
-     * @param accessor
-     * @param userId
-     * @throws OAuthException
+     * Marks the request token in the accessor as authorized. Request tokens 
are marked as authorized after
+     * authorizing the token, for which usually the user first needs to login 
and explicitly grant access to
+     * the service consumer.
+     * 
+     * @param accessor The OAuth accessor
+     * @param userId the user id that authorized the token
+     * @throws OAuthException In case the provided oAuth tokens in the 
accessor are invalid
      */
     void markAsAuthorized(OAuthAccessor accessor, String userId) throws 
OAuthException;
-    
 
     /**
      * Exchange the request token for an access token. This call is typically 
invoked after a request token
      * has been authorized, however this method does not validate that. The 
token servlets are supposed to
      * perform all token validations.
      * 
-     * @throws OAuthException
+     * @throws OAuthException In case the oAuth token stored in the accessor 
is invalid.
      */
     void generateAccessToken(OAuthAccessor accessor) throws OAuthException;
 }

Modified: 
trunk/amdatu-authentication/oauth-server/src/main/java/org/amdatu/authentication/oauth/server/osgi/Activator.java
==============================================================================
--- 
trunk/amdatu-authentication/oauth-server/src/main/java/org/amdatu/authentication/oauth/server/osgi/Activator.java
   (original)
+++ 
trunk/amdatu-authentication/oauth-server/src/main/java/org/amdatu/authentication/oauth/server/osgi/Activator.java
   Thu Dec  2 15:47:28 2010
@@ -28,6 +28,7 @@
 import org.amdatu.authentication.oauth.server.OAuthRequestTokenServlet;
 import org.amdatu.authentication.oauth.server.OAuthServiceConsumerRegistry;
 import org.amdatu.authentication.oauth.server.OAuthTokenProvider;
+import org.amdatu.authentication.oauth.server.OAuthServerConfig;
 import 
org.amdatu.authentication.oauth.server.service.OAuthAccessTokenServletImpl;
 import 
org.amdatu.authentication.oauth.server.service.OAuthAuthorizeTokenServletImpl;
 import 
org.amdatu.authentication.oauth.server.service.OAuthRequestTokenServletImpl;
@@ -60,42 +61,42 @@
             .setImplementation(OAuthTokenProviderImpl.class)
             
.add(createServiceDependency().setService(LogService.class).setRequired(true))
             
.add(createServiceDependency().setService(OAuthServiceConsumer.class).setCallbacks("onAdded",
 "onRemoved")));
-        
+
         // Create and register the resource provider
         manager.add(
             createComponent()
             .setInterface(ResourceProvider.class.getName(), null)
             .setImplementation(OAuthResourceProviderImpl.class)
-            
.add(createServiceDependency().setService(HttpContextServiceFactory.class).setRequired(true)));
        
-        
+            
.add(createServiceDependency().setService(HttpContextServiceFactory.class).setRequired(true)));
+
         // Create and register the OAuth service provider
         manager.add(
             createComponent()
             .setInterface(new String[]{OAuthServiceProvider.class.getName(), 
ManagedService.class.getName()}, null)
             .setImplementation(OAuthServiceProviderImpl.class)
-            
.add(createConfigurationDependency().setPid(OAuthServiceProviderImpl.PID)));    
 
-        
+            
.add(createConfigurationDependency().setPid(OAuthServerConfig.PID)));
+
         // Create and register the oAuth service consumer registry service
         manager.add(
             createComponent()
             .setInterface(OAuthServiceConsumerRegistry.class.getName(), null)
             .setImplementation(OAuthServiceConsumerRegistryImpl.class)
-            
.add(createServiceDependency().setService(LogService.class).setRequired(true)));
     
-        
+            
.add(createServiceDependency().setService(LogService.class).setRequired(true)));
+
         // Create and register the oAuth service consumer registry REST service
         manager.add(
             createComponent()
             .setInterface(ResourceProvider.class.getName(), null)
             .setImplementation(OAuthServiceConsumerRegistryREST.class)
             
.add(createServiceDependency().setService(LogService.class).setRequired(true))
-            
.add(createServiceDependency().setService(OAuthServiceConsumerRegistry.class).setRequired(true)));
 
-        
+            
.add(createServiceDependency().setService(OAuthServiceConsumerRegistry.class).setRequired(true)));
+
         // Create and register the OAuth servlet components.
         manager.add(createComponent(OAuthRequestTokenServlet.SERVLET_ALIAS, 
OAuthRequestTokenServlet.class, OAuthRequestTokenServletImpl.class));
         manager.add(createComponent(OAuthAuthorizeTokenServlet.SERVLET_ALIAS, 
OAuthAuthorizeTokenServlet.class, OAuthAuthorizeTokenServletImpl.class));
         manager.add(createComponent(OAuthAccessTokenServlet.SERVLET_ALIAS, 
OAuthAccessTokenServlet.class, OAuthAccessTokenServletImpl.class));
     }
-    
+
     private Component createComponent(String alias, Class<?> servletInterface, 
Class<?> servletClass) {
         Dictionary<String, String> servletProperties = new Hashtable<String, 
String>();
         servletProperties.put("alias", alias);

Modified: 
trunk/amdatu-authentication/oauth-server/src/main/java/org/amdatu/authentication/oauth/server/service/OAuthAccessTokenServletImpl.java
==============================================================================
--- 
trunk/amdatu-authentication/oauth-server/src/main/java/org/amdatu/authentication/oauth/server/service/OAuthAccessTokenServletImpl.java
      (original)
+++ 
trunk/amdatu-authentication/oauth-server/src/main/java/org/amdatu/authentication/oauth/server/service/OAuthAccessTokenServletImpl.java
      Thu Dec  2 15:47:28 2010
@@ -68,11 +68,12 @@
             }
             // generate access token and secret
             m_tokenProvider.generateAccessToken(accessor);
-            m_logService.log(LogService.LOG_DEBUG, "Generated access token " + 
accessor.accessToken);
+            m_logService.log(LogService.LOG_DEBUG, "Generated access token " + 
accessor.accessToken + ", with token secret " + accessor.tokenSecret);
             
             response.setContentType("text/plain");
             OutputStream out = null;
             try {
+                // TODO: We need to explore the possibilities to add 
additional information to the oAuth tokens, like a tenant id.
                out = response.getOutputStream();
                 OAuth.formEncode(OAuth.newList("oauth_token", 
accessor.accessToken, "oauth_token_secret",
                     accessor.tokenSecret), out);

Modified: 
trunk/amdatu-authentication/oauth-server/src/main/java/org/amdatu/authentication/oauth/server/service/OAuthAuthorizeTokenServletImpl.java
==============================================================================
--- 
trunk/amdatu-authentication/oauth-server/src/main/java/org/amdatu/authentication/oauth/server/service/OAuthAuthorizeTokenServletImpl.java
   (original)
+++ 
trunk/amdatu-authentication/oauth-server/src/main/java/org/amdatu/authentication/oauth/server/service/OAuthAuthorizeTokenServletImpl.java
   Thu Dec  2 15:47:28 2010
@@ -101,6 +101,9 @@
         // Create a request wrapper returning the path of the JSP servlet 
instead of this servlet
         HttpServletRequestWrapper wrapper = new 
HttpServletRequestWrapper(request) {
             public String getPathInfo() {
+                // TODO: This JSP is currently a Micky Mouse example. By 
simply posting a form holding 
+                // the userid, a request token can be authorized for that user 
id. This needs to be 
+                // connected to the Amdatu login service, or even to a 
pluggable login service.
                 return "/" + OAuthResourceProviderImpl.RESOURCE_ID + 
"/jsp/authorize.jsp";
             }
         };

Modified: 
trunk/amdatu-authentication/oauth-server/src/main/java/org/amdatu/authentication/oauth/server/service/OAuthServiceConsumerBean.java
==============================================================================
--- 
trunk/amdatu-authentication/oauth-server/src/main/java/org/amdatu/authentication/oauth/server/service/OAuthServiceConsumerBean.java
 (original)
+++ 
trunk/amdatu-authentication/oauth-server/src/main/java/org/amdatu/authentication/oauth/server/service/OAuthServiceConsumerBean.java
 Thu Dec  2 15:47:28 2010
@@ -1,3 +1,19 @@
+/*
+    Copyright (C) 2010 Amdatu.org
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
 package org.amdatu.authentication.oauth.server.service;
 
 import java.lang.reflect.InvocationTargetException;
@@ -15,6 +31,10 @@
 @SuppressWarnings("restriction")
 @XmlRootElement(name = "consumer")
 @XmlAccessorType(XmlAccessType.PUBLIC_MEMBER)
+
+/**
+ * Implementation of JAXB bean used by the oAuth service consumer registry 
REST service.
+ */
 public class OAuthServiceConsumerBean implements OAuthServiceConsumer {
 
     private String m_consumerKey;
@@ -79,6 +99,4 @@
         bean.addLink(thisLink, "alternate");
         return bean;
     }
-    
-
 }

Modified: 
trunk/amdatu-authentication/oauth-server/src/main/java/org/amdatu/authentication/oauth/server/service/OAuthServiceConsumerRegistryImpl.java
==============================================================================
--- 
trunk/amdatu-authentication/oauth-server/src/main/java/org/amdatu/authentication/oauth/server/service/OAuthServiceConsumerRegistryImpl.java
 (original)
+++ 
trunk/amdatu-authentication/oauth-server/src/main/java/org/amdatu/authentication/oauth/server/service/OAuthServiceConsumerRegistryImpl.java
 Thu Dec  2 15:47:28 2010
@@ -26,6 +26,8 @@
 import org.osgi.service.log.LogService;
 
 public class OAuthServiceConsumerRegistryImpl implements 
OAuthServiceConsumerRegistry {
+    // TODO: for now this simple implementation stores consumer in memory, 
this must be replaced
+    // by a persistent storage.
     Map<String, OAuthServiceConsumer> m_consumers = new HashMap<String, 
OAuthServiceConsumer>();
     private LogService m_logService;
     

Modified: 
trunk/amdatu-authentication/oauth-server/src/main/java/org/amdatu/authentication/oauth/server/service/OAuthServiceConsumerRegistryREST.java
==============================================================================
--- 
trunk/amdatu-authentication/oauth-server/src/main/java/org/amdatu/authentication/oauth/server/service/OAuthServiceConsumerRegistryREST.java
 (original)
+++ 
trunk/amdatu-authentication/oauth-server/src/main/java/org/amdatu/authentication/oauth/server/service/OAuthServiceConsumerRegistryREST.java
 Thu Dec  2 15:47:28 2010
@@ -41,28 +41,31 @@
 
 /**
  * This class provides a REST interface on top of the oAuth service consumer 
registry
+ * TODO: This REST API needs to be finalized by adding HTTP caching headers, 
authorization checks and
+ * possibly additional methods.
+ * 
  * @author ivol
- *
  */
 @Path("oauth/consumers")
 public class OAuthServiceConsumerRegistryREST implements ResourceProvider {
     // The oAuth service consumer registry
     private volatile OAuthServiceConsumerRegistry m_registry;
     private volatile LogService m_logService;
-    
+
     public void start() {
         m_logService.log(LogService.LOG_DEBUG, "OAuth Service Consumer 
registry REST service started.");
     }
-   
+
     /**
      * REST interface: GET 
/rest/services/oauth/consumers/oauth/consumers/{consumerKey}
      * Returns the requested consumer in application/xml or application/json 
format.
+     * 
      * @param consumerKey The key of the consumer to retrieve.
      * @return The consumer matching the key in xml or json format
      */
     @GET
-    @Path("{consumerKey}") 
-    @Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
+    @Path("{consumerKey}")
+    @Produces( { MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
     public OAuthServiceConsumer getConsumer(@PathParam("consumerKey") final 
String consumerKey, @Context UriInfo uriInfo) {
         try {
             return 
OAuthServiceConsumerBean.copy(m_registry.getConsumer(consumerKey), uriInfo);
@@ -77,14 +80,15 @@
             throw new WebApplicationException(e, 
Response.Status.INTERNAL_SERVER_ERROR);
         }
     }
-    
+
     /**
      * REST interface: PUT /rest/services/oauth/consumers/oauth/consumers
      * Adds a new consumer with the properties of the posted values in 
application/xml or application/json format.
+     * 
      * @return The http response object
      */
     @PUT
-    @Consumes({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
+    @Consumes( { MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
     public Response addConsumer(OAuthServiceConsumerBean consumer) {
         try {
             m_registry.addConsumer(consumer);
@@ -94,16 +98,17 @@
             throw new WebApplicationException(Response.Status.NOT_MODIFIED);
         }
     }
-    
+
     /**
      * REST interface: PUT 
/rest/services/oauth/consumers/oauth/consumers/{consumerKey}
      * Updates an existing consumer with the properties of the posted values 
in application/xml or application/json format.
+     * 
      * @param consumerKey The key of the consumer to update.
      * @return The http response object
      */
     @PUT
-    @Consumes({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
-    @Path("{consumerKey}") 
+    @Consumes( { MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
+    @Path("{consumerKey}")
     public Response updateConsumer(@PathParam("consumerKey") final String 
consumerKey, OAuthServiceConsumerBean consumer) {
         try {
             m_registry.updateConsumer(consumer);
@@ -113,14 +118,15 @@
             throw new WebApplicationException(Response.Status.NOT_FOUND);
         }
     }
-    
-    
+
     /**
      * REST interface: PUT /rest/services/oauth/consumers/oauth/consumers
      * Adds a new consumer with the properties of the posted values in 
application/xml or application/json format.
+     * 
      * @return The http response object
      */
     @DELETE
+    @Path("{consumerKey}")
     public Response deleteConsumer(@PathParam("consumerKey") final String 
consumerKey) {
         try {
             m_registry.removeConsumer(m_registry.getConsumer(consumerKey));

Modified: 
trunk/amdatu-authentication/oauth-server/src/main/java/org/amdatu/authentication/oauth/server/service/OAuthServiceProviderImpl.java
==============================================================================
--- 
trunk/amdatu-authentication/oauth-server/src/main/java/org/amdatu/authentication/oauth/server/service/OAuthServiceProviderImpl.java
 (original)
+++ 
trunk/amdatu-authentication/oauth-server/src/main/java/org/amdatu/authentication/oauth/server/service/OAuthServiceProviderImpl.java
 Thu Dec  2 15:47:28 2010
@@ -21,6 +21,7 @@
 import org.amdatu.authentication.oauth.api.OAuthServiceProvider;
 import org.amdatu.authentication.oauth.server.OAuthAccessTokenServlet;
 import org.amdatu.authentication.oauth.server.OAuthAuthorizeTokenServlet;
+import static org.amdatu.authentication.oauth.server.OAuthServerConfig.*;
 import org.osgi.service.cm.ConfigurationException;
 import org.osgi.service.cm.ManagedService;
 

Modified: 
trunk/amdatu-authentication/oauth-server/src/main/java/org/amdatu/authentication/oauth/server/service/OAuthTokenProviderImpl.java
==============================================================================
--- 
trunk/amdatu-authentication/oauth-server/src/main/java/org/amdatu/authentication/oauth/server/service/OAuthTokenProviderImpl.java
   (original)
+++ 
trunk/amdatu-authentication/oauth-server/src/main/java/org/amdatu/authentication/oauth/server/service/OAuthTokenProviderImpl.java
   Thu Dec  2 15:47:28 2010
@@ -89,6 +89,8 @@
     }
 
     public OAuthValidator getOAuthValidator() {
+        // TODO: We need to provide an external REST service to validate OAuth 
messages and 
+        // retrieve context information like userid and consumer key
         return m_oAuthValidator;
     }
 

Added: 
trunk/amdatu-core/config-filebased/src/main/resources/conf/org.amdatu.authentication.oauth.server.cfg
==============================================================================
--- (empty file)
+++ 
trunk/amdatu-core/config-filebased/src/main/resources/conf/org.amdatu.authentication.oauth.server.cfg
       Thu Dec  2 15:47:28 2010
@@ -0,0 +1,3 @@
+# The hostname and portnr
+hostname=${server.hostname}
+portnr=${server.port}
\ No newline at end of file

Modified: trunk/amdatu-release/pom.xml
==============================================================================
--- trunk/amdatu-release/pom.xml        (original)
+++ trunk/amdatu-release/pom.xml        Thu Dec  2 15:47:28 2010
@@ -11,6 +11,29 @@
   <name>Amdatu Release</name>
 
   <dependencies>
+    <!-- Authentication bundles -->
+    <dependency>
+      <groupId>org.amdatu.authentication.oauth</groupId>
+      <artifactId>api</artifactId>    
+      <version>${platform.version}</version>
+      <scope>compile</scope>
+      <type>bundle</type>
+    </dependency>    
+    <dependency>
+      <groupId>org.amdatu.authentication.oauth</groupId>
+      <artifactId>server</artifactId>    
+      <version>${platform.version}</version>
+      <scope>compile</scope>
+      <type>bundle</type>
+    </dependency>
+    <dependency>
+      <groupId>org.amdatu.authentication.oauth</groupId>
+      <artifactId>client</artifactId>    
+      <version>${platform.version}</version>
+      <scope>compile</scope>
+      <type>bundle</type>
+    </dependency>    
+    
     <!-- Authorization bundles -->
     <dependency>
       <groupId>org.amdatu.authorization.login</groupId>

Modified: trunk/amdatu-release/src/main/assembly/bin-component.xml
==============================================================================
--- trunk/amdatu-release/src/main/assembly/bin-component.xml    (original)
+++ trunk/amdatu-release/src/main/assembly/bin-component.xml    Thu Dec  2 
15:47:28 2010
@@ -13,6 +13,8 @@
       
<outputFileNameMapping>${artifact.groupId}.${artifact.artifactId}-${artifact.version}.${artifact.extension}
       </outputFileNameMapping>
       <includes>
+        <include>org.amdatu.authentication:*</include>
+        <include>org.amdatu.authentication.*:*</include>
         <include>org.amdatu.authorization:*</include>
         <include>org.amdatu.authorization.*:*</include>
         <include>org.amdatu.cassandra:*</include>

Modified: trunk/integration-tests/pom.xml
==============================================================================
--- trunk/integration-tests/pom.xml     (original)
+++ trunk/integration-tests/pom.xml     Thu Dec  2 15:47:28 2010
@@ -175,6 +175,27 @@
       <scope>test</scope>
       <type>bundle</type>
     </dependency>
+    <dependency>
+      <groupId>org.amdatu.authentication.oauth</groupId>
+      <artifactId>api</artifactId>    
+      <version>${platform.version}</version>
+      <scope>test</scope>
+      <type>bundle</type>
+    </dependency>    
+    <dependency>
+      <groupId>org.amdatu.authentication.oauth</groupId>
+      <artifactId>server</artifactId>    
+      <version>${platform.version}</version>
+      <scope>test</scope>
+      <type>bundle</type>
+    </dependency>
+    <dependency>
+      <groupId>org.amdatu.authentication.oauth</groupId>
+      <artifactId>client</artifactId>    
+      <version>${platform.version}</version>
+      <scope>test</scope>
+      <type>bundle</type>
+    </dependency>    
 
     <dependency>
       <groupId>org.apache.felix</groupId>
@@ -242,7 +263,12 @@
       <version>${org.apache.sling.commons.osgi.version}</version>
       <scope>test</scope>
     </dependency>
-
+    <dependency>
+      <groupId>org.json</groupId>
+      <artifactId>json</artifactId>
+      <version>20090211</version>
+      <scope>test</scope>
+    </dependency>
   </dependencies>
 
   <build>

Modified: 
trunk/integration-tests/src/test/java/org/amdatu/test/integration/base/ConfigProvider.java
==============================================================================
--- 
trunk/integration-tests/src/test/java/org/amdatu/test/integration/base/ConfigProvider.java
  (original)
+++ 
trunk/integration-tests/src/test/java/org/amdatu/test/integration/base/ConfigProvider.java
  Thu Dec  2 15:47:28 2010
@@ -21,6 +21,7 @@
 import java.net.URL;
 import java.util.Properties;
 
+import org.amdatu.authentication.oauth.server.OAuthServerConfig;
 import org.amdatu.cassandra.application.CassandraConfigurationService;
 import org.amdatu.core.config.templates.ConfigTemplateManager;
 import org.amdatu.core.tenant.TenantStorageProvider;
@@ -39,6 +40,13 @@
     public final static String PORTNR = "3737";
     public final static String SECURE_PORTNR = "3738";
 
+    public void addLogConfig(ConfigurationAdmin configAdmin) throws 
IOException {
+        Configuration config = 
configAdmin.getConfiguration("org.amdatu.core.loghandler", null);
+        Properties properties = new Properties();
+        properties.put("console.mininum.loglevel", "DEBUG");
+        config.update(properties);
+    }
+    
     public void addCassandraConfig(ConfigurationAdmin configAdmin) throws 
IOException {
         Configuration config = 
configAdmin.getConfiguration(CassandraConfigurationService.PID, null);
         Properties properties = new Properties();
@@ -141,6 +149,14 @@
         properties.put(TenantStorageProvider.DATA_DIRECTORY, 
"work/useradminstore");
         config.update(properties);
     }
+    
+    public void addOAuthConfig(ConfigurationAdmin configAdmin) throws 
IOException {
+        Configuration config = 
configAdmin.getConfiguration(OAuthServerConfig.PID, null);
+        Properties properties = new Properties();
+        properties.put(OAuthServerConfig.HOSTNAME, ConfigProvider.HOSTNAME);
+        properties.put(OAuthServerConfig.PORTNR, ConfigProvider.PORTNR);
+        config.update(properties);
+    }
 
     /**
      * Wait until the service at the specified URL returns the specified 
response code with a timeout as specified.

Modified: 
trunk/integration-tests/src/test/java/org/amdatu/test/integration/base/IntegrationTestBase.java
==============================================================================
--- 
trunk/integration-tests/src/test/java/org/amdatu/test/integration/base/IntegrationTestBase.java
     (original)
+++ 
trunk/integration-tests/src/test/java/org/amdatu/test/integration/base/IntegrationTestBase.java
     Thu Dec  2 15:47:28 2010
@@ -28,12 +28,15 @@
 
 import java.io.File;
 import java.io.FileFilter;
+import java.io.IOException;
+import java.util.List;
 import java.util.concurrent.Semaphore;
 import java.util.concurrent.TimeUnit;
 
 import org.apache.felix.dm.Component;
 import org.apache.felix.dm.ComponentStateListener;
 import org.apache.felix.dm.DependencyManager;
+import org.apache.felix.dm.ServiceDependency;
 import org.apache.felix.dm.tracker.ServiceTracker;
 import org.junit.Assert;
 import org.junit.Before;
@@ -121,7 +124,7 @@
      * Gets a list of Component objects which should be started before
      * the test can start. You can include the test class in this too, so
      * you can get the services you depend on injected.
-     * 
+     *
      * Note that you <em>can</em> add components to the dependency manager 
directly,
      * but the test will only wait for them if you return them in this method. 
If you do,
      * you should not add them to the dependency manager yourself.
@@ -131,7 +134,9 @@
     }
 
     @Before
-    public void setupTest() {
+    public void setupTest() throws Exception {
+        initConfiguration();
+        
         m_manager = new DependencyManager(m_bundleContext);
         Component[] components = getDependencies(m_manager);
 
@@ -152,14 +157,36 @@
         // And wait for all the services to become active.
         try {
             if (!semaphore.tryAcquire(SERVICE_TIMEOUT, TimeUnit.SECONDS)) {
+                // Generate more background information about the exact 
services that were missing.
+                String moreInfo = "";
+                for (Component component : components) {
+                   if (component.getService() == null) {
+                       moreInfo = "\nComponent that failed to start: " + 
component;
+                       List<ServiceDependency> dependencies = 
component.getDependencies();
+                       for (ServiceDependency dependency : dependencies) {
+                           if (dependency.getState() == 
ServiceDependency.STATE_UNAVAILABLE_REQUIRED) {
+                               moreInfo += "\nThe component depends on the 
following unavailable service: " + dependency.getName();
+                           }
+                       }
+                   }
+                }
+                
                 Assert.fail("Timed out waiting for all services to get 
started, still "
-                    + (1 - semaphore.availablePermits()) + " to go.");
+                    + (1 - semaphore.availablePermits()) + " to go." + 
moreInfo);
             }
         }
         catch (InterruptedException e) {
             Assert.fail("Interrupted while waiting for services to get 
started.");
         }
     }
+    
+    /**
+     * Override to provide the initial configuration. Configuration must be 
provided before 
+     * service dependencies are provided since some managed services can only 
start when their
+     * config has been provided.
+     */
+    protected void initConfiguration() throws IOException {
+    }
 
     /**
      * Helper class that releases the given semaphore when each service it is
@@ -300,6 +327,18 @@
         return 
mavenBundle().groupId("org.amdatu.web").artifactId("httpcontext").versionAsInProject();
     }
 
+    protected static MavenArtifactProvisionOption amdatuOAuthAPI() {
+        return 
mavenBundle().groupId("org.amdatu.authentication.oauth").artifactId("api").versionAsInProject();
+    }
+
+    protected static MavenArtifactProvisionOption amdatuOAuthClient() {
+        return 
mavenBundle().groupId("org.amdatu.authentication.oauth").artifactId("client").versionAsInProject();
+    }
+
+    protected static MavenArtifactProvisionOption amdatuOAuthServer() {
+        return 
mavenBundle().groupId("org.amdatu.authentication.oauth").artifactId("server").versionAsInProject();
+    }
+
     protected static MavenArtifactProvisionOption fileBasedConfiguration() {
         return 
mavenBundle().groupId("org.amdatu.core.config").artifactId("filebased").versionAsInProject();
     }
@@ -387,6 +426,10 @@
         return 
wrappedBundle(mavenBundle().groupId("commons-codec").artifactId("commons-codec"));
     }
 
+    protected static WrappedUrlProvisionOption json() {
+        return 
wrappedBundle(mavenBundle().groupId("org.json").artifactId("json").versionAsInProject());
+    }
+
     protected static WrappedUrlProvisionOption javaxServlet() {
         // We need to create a bundle holding the 2.3 servlet API (required by 
SLF4J used by Cassandra) if the http service
         // is not deployed. Since the org.osgi.compendium_4 and other bundles 
include javax.servlet with explicit version

Added: 
trunk/integration-tests/src/test/java/org/amdatu/test/integration/mock/OAuthProtectedTestServlet.java
==============================================================================
--- (empty file)
+++ 
trunk/integration-tests/src/test/java/org/amdatu/test/integration/mock/OAuthProtectedTestServlet.java
       Thu Dec  2 15:47:28 2010
@@ -0,0 +1,87 @@
+/*
+ Copyright (C) 2010 Amdatu.org
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+package org.amdatu.test.integration.mock;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.net.URISyntaxException;
+
+import javax.servlet.Servlet;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import net.oauth.OAuthAccessor;
+import net.oauth.OAuthException;
+import net.oauth.OAuthMessage;
+import net.oauth.OAuthProblemException;
+import net.oauth.server.OAuthServlet;
+
+import org.amdatu.authentication.oauth.server.OAuthTokenProvider;
+import org.osgi.service.log.LogService;
+
+public class OAuthProtectedTestServlet extends HttpServlet implements Servlet {
+    // The serial version UID of thi servlet
+    private static final long serialVersionUID = 8834974378869705614L;
+
+    public static final String SERVLET_ALIAS = "/test/oauth/protectedresource";
+
+    private volatile LogService m_logService;
+    private volatile OAuthTokenProvider m_tokenProvider;
+
+    public void doGet(HttpServletRequest request, HttpServletResponse response)
+    throws IOException, ServletException {
+        processRequest(request, response);
+    }
+
+    public void doPost(HttpServletRequest request, HttpServletResponse 
response)
+    throws IOException, ServletException {
+        processRequest(request, response);
+    }
+
+    public void processRequest(HttpServletRequest request, HttpServletResponse 
response)
+    throws IOException, ServletException {
+        m_logService.log(LogService.LOG_DEBUG, "Protected resource test 
servlet received incoming request, validating token");
+
+        try {
+            // Validate the token
+            OAuthMessage requestMessage = OAuthServlet.getMessage(request, 
null);
+            OAuthAccessor accessor = 
m_tokenProvider.getAccessor(requestMessage);
+            
m_tokenProvider.getOAuthValidator().validateMessage(requestMessage, accessor);
+            String userId = (String) accessor.getProperty("user");
+
+            response.setContentType("text/plain");
+            PrintWriter out = null;
+            try {
+                out = response.getWriter();
+                out.print("userid=" + userId);
+            } finally {
+                out.close();
+            }
+        }
+        catch (OAuthProblemException e) {
+            throw new ServletException(e);
+        }
+        catch (OAuthException e) {
+            throw new ServletException(e);
+        }
+        catch (URISyntaxException e) {
+            throw new ServletException(e);
+        }
+    }
+}

Added: 
trunk/integration-tests/src/test/java/org/amdatu/test/integration/mock/OAuthTestConsumer.java
==============================================================================
--- (empty file)
+++ 
trunk/integration-tests/src/test/java/org/amdatu/test/integration/mock/OAuthTestConsumer.java
       Thu Dec  2 15:47:28 2010
@@ -0,0 +1,113 @@
+/*
+ Copyright (C) 2010 Amdatu.org
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+package org.amdatu.test.integration.mock;
+
+import org.amdatu.authentication.oauth.api.OAuthServiceConsumer;
+import org.json.JSONException;
+import org.json.JSONObject;
+import org.json.XML;
+
+public class OAuthTestConsumer implements OAuthServiceConsumer {
+    // Defaults
+       public final static String DEFAULT_CONSUMER_NAME = "Integration Test 
Consumer inc.";
+    public final static String DEFAULT_CONSUMER_KEY = 
"IntegrationTestConsumerKey";
+    public final static String DEFAULT_CONSUMER_SECRET = 
"IntegrationTestConsumerSecret";
+    public final static String DEFAULT_CALLBACK_URL = 
"http://localhost/dummy/callback/url";;
+    
+    // Instance variables
+    private String m_name = DEFAULT_CONSUMER_NAME;
+    private String m_consumerKey = DEFAULT_CONSUMER_KEY;
+    private String m_consumerSecret = DEFAULT_CONSUMER_SECRET;
+    private String m_callbackUrl = DEFAULT_CALLBACK_URL;
+    
+    public void setName(String name) {
+        m_name = name;
+    }
+    public String getName() {
+       return m_name;
+    }
+    
+    public void setCallbackUrl(String callbackUrl) {
+        m_callbackUrl = callbackUrl;
+    }
+    
+    public String getCallbackUrl() {
+        return m_callbackUrl;
+    }
+
+    public void setConsumerKey(String consumerKey) {
+        m_consumerKey = consumerKey;
+    }
+    
+    public String getConsumerKey() {
+        return m_consumerKey;
+    }
+
+    public void setConsumerSecret(String consumerSecret) {
+        m_consumerSecret = consumerSecret;
+    }
+    
+    public String getConsumerSecret() {
+        return m_consumerSecret;
+    }
+    
+    public JSONObject toJson() throws JSONException {
+        JSONObject consumer = new JSONObject();
+        consumer.put("name", getName());
+        consumer.put("callbackUrl", getCallbackUrl());
+        consumer.put("consumerKey", getConsumerKey());
+        consumer.put("consumerSecret", getConsumerSecret());
+        return  new JSONObject().put("consumer", consumer);
+    }
+    
+    public String toXML() throws JSONException {
+        JSONObject consumer = toJson();
+        return XML.toString(consumer);
+    }
+    
+    public static OAuthTestConsumer fromJson(String json) throws JSONException 
{
+        JSONObject jsonObject = new JSONObject(json).getJSONObject("consumer");
+        OAuthTestConsumer consumer = new OAuthTestConsumer();
+        consumer.setName(jsonObject.getString("name"));
+        consumer.setConsumerKey(jsonObject.getString("consumerKey"));
+        consumer.setConsumerSecret(jsonObject.getString("consumerSecret"));
+        consumer.setCallbackUrl(jsonObject.getString("callbackUrl"));
+        return consumer;
+    }
+    
+    public static OAuthTestConsumer fromXML(String xml) throws JSONException {
+        return fromJson(XML.toJSONObject(xml).toString());
+    }
+    
+    @Override
+    public boolean equals(Object obj) {
+        if (!(obj instanceof OAuthTestConsumer)) {
+            return false;
+        }
+        OAuthTestConsumer consumer = (OAuthTestConsumer) obj;
+        return consumer.getName().equals(getName()) 
+            && consumer.getConsumerKey().equals(getConsumerKey())
+            && consumer.getConsumerSecret().equals(getConsumerSecret())
+            && consumer.getCallbackUrl().equals(getCallbackUrl());
+    }
+    
+    @Override
+    public String toString() {
+        return "Test consumer: name=" + getName() + ", key=" + 
getConsumerKey() + ", secret=" 
+            + getConsumerSecret() + ", callbackurl=" + getCallbackUrl();
+    }
+}

Added: 
trunk/integration-tests/src/test/java/org/amdatu/test/integration/tests/OAuthClientTest.java
==============================================================================
--- (empty file)
+++ 
trunk/integration-tests/src/test/java/org/amdatu/test/integration/tests/OAuthClientTest.java
        Thu Dec  2 15:47:28 2010
@@ -0,0 +1,206 @@
+/*
+ Copyright (C) 2010 Amdatu.org
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+package org.amdatu.test.integration.tests;
+
+import static org.ops4j.pax.exam.CoreOptions.provision;
+
+import java.io.IOException;
+import java.util.Dictionary;
+import java.util.Hashtable;
+
+import javax.servlet.Servlet;
+
+import net.oauth.OAuth;
+import net.oauth.OAuthAccessor;
+import net.oauth.OAuthConsumer;
+import net.oauth.OAuthMessage;
+import net.oauth.OAuthProblemException;
+
+import org.amdatu.authentication.oauth.api.OAuthServiceConsumer;
+import org.amdatu.authentication.oauth.api.OAuthServiceProvider;
+import org.amdatu.authentication.oauth.client.OAuthResourceOwnerClient;
+import org.amdatu.authentication.oauth.client.OAuthServiceConsumerClient;
+import org.amdatu.authentication.oauth.server.OAuthRequestTokenServlet;
+import org.amdatu.authentication.oauth.server.OAuthTokenProvider;
+import org.amdatu.test.integration.base.ConfigProvider;
+import org.amdatu.test.integration.base.IntegrationTestBase;
+import org.amdatu.test.integration.mock.OAuthProtectedTestServlet;
+import org.amdatu.test.integration.mock.OAuthTestConsumer;
+import org.apache.felix.dm.Component;
+import org.apache.felix.dm.DependencyManager;
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.ops4j.pax.exam.Option;
+import org.ops4j.pax.exam.junit.Configuration;
+import org.ops4j.pax.exam.junit.JUnit4TestRunner;
+import org.osgi.service.cm.ConfigurationAdmin;
+import org.osgi.service.log.LogService;
+
+ at RunWith(JUnit4TestRunner.class)
+public class OAuthClientTest extends IntegrationTestBase {
+    private volatile DependencyManager m_dependencyManager;
+    private volatile LogService m_logService;
+    private volatile OAuthTokenProvider m_tokenProvider;
+    private volatile OAuthServiceProvider m_oAuthServiceProvider;
+    private volatile ConfigurationAdmin m_configAdmin;
+    
+    @Configuration
+    public Option[] configure() {
+        return super.configure();
+    }
+    
+    protected void initConfiguration() throws IOException {
+        m_configAdmin = getService(ConfigurationAdmin.class);
+        
+        // Add cassandra and templates configs
+        ConfigProvider configProvider = new ConfigProvider();
+        configProvider.addHttpServiceConfig(m_configAdmin);
+        configProvider.addOAuthConfig(m_configAdmin);
+        configProvider.addLogConfig(m_configAdmin);
+    }
+
+    protected Component[] getDependencies(DependencyManager manager) {
+        // Now register a test servlet
+        OAuthProtectedTestServlet m_testServlet = new 
OAuthProtectedTestServlet();
+        Dictionary<String, String> servletProperties = new Hashtable<String, 
String>();
+        servletProperties.put("alias", 
OAuthProtectedTestServlet.SERVLET_ALIAS);
+        servletProperties.put("contextId", 
OAuthProtectedTestServlet.SERVLET_ALIAS);
+        Component servletComponent = manager.createComponent()
+            .setImplementation(m_testServlet)
+            .setInterface(new String[] { Servlet.class.getName() }, 
servletProperties)
+            
.add(manager.createServiceDependency().setService(LogService.class).setRequired(true))
+            
.add(manager.createServiceDependency().setService(OAuthTokenProvider.class).setRequired(true));
+
+        Component testComponent = manager.createComponent()
+            .setImplementation(this)
+            
.add(manager.createServiceDependency().setService(OAuthRequestTokenServlet.class).setRequired(true))
+            
.add(manager.createServiceDependency().setService(OAuthTokenProvider.class).setRequired(true))
+            
.add(manager.createServiceDependency().setService(OAuthServiceProvider.class).setRequired(true))
+            
.add(manager.createServiceDependency().setService(ConfigurationAdmin.class).setRequired(true))
+            
.add(manager.createServiceDependency().setService(LogService.class).setRequired(true));
+
+        return new Component[] { servletComponent, testComponent };
+    }
+
+    protected Option provisionBundles() {
+        return provision(
+            felixHttpServiceJetty(),
+            felixHttpServiceWhiteboard(),
+            slingMime(),
+            slingCommons(),
+            commonsCodec(),
+            commonsLogging(),
+            commonsHttpClient(),
+            paxSwissbox(),
+            ops4jBaseLang(),
+            json(),
+            amdatuHttpContext(),
+            amdatuJaxRs(),
+            amdatuOAuthAPI(),
+            amdatuOAuthClient(),
+            amdatuOAuthServer(),
+            amdatuJspSupport());
+    }
+
+    @Test
+    // Test the three-legged oAuth dance
+    public void testThreeLeggedOAuth() throws Exception {
+        // Step 1: Register a service consumer
+        m_logService.log(LogService.LOG_DEBUG, "*** Step 1: Register service 
consumer ***");
+        OAuthServiceConsumer consumer = registerServiceConsumer();
+
+        // Step 2: Create an OAuthClient for our Amdatu OAuth server
+        m_logService.log(LogService.LOG_DEBUG, "*** Step 2: Create OAuth 
Clients ***");
+        OAuthServiceConsumerClient consumerClient = new 
OAuthServiceConsumerClient(m_oAuthServiceProvider, consumer);
+        OAuthResourceOwnerClient userClient = new 
OAuthResourceOwnerClient(m_oAuthServiceProvider, consumer);
+
+        // Step 3: Generate a request token for our service consumer
+        m_logService.log(LogService.LOG_DEBUG, "*** Step 3: Generate request 
token ***");
+        OAuthAccessor accessor = createRequestToken(consumerClient);
+
+        // Step 4: Authorize the request token for a user we define
+        m_logService.log(LogService.LOG_DEBUG, "*** Step 4: Authorize the 
request token ***");
+        String callback = userClient.authorizeToken(accessor, "ivol");
+        
Assert.assertTrue(callback.startsWith(OAuthTestConsumer.DEFAULT_CALLBACK_URL + 
"?oauth_token="));
+        m_logService.log(LogService.LOG_DEBUG, "Callback URL received: " + 
callback);
+
+        // Step 5: Exchange our request token for an access token
+        m_logService.log(LogService.LOG_DEBUG, "*** Step 5: Get access token 
***");
+        OAuthMessage message = consumerClient.getAccessToken(accessor);
+        accessor.accessToken =  message.getToken();
+        accessor.tokenSecret = message.getParameter("oauth_token_secret");
+        accessor.requestToken = null;
+        m_logService.log(LogService.LOG_DEBUG, "Access token received: " + 
accessor.accessToken + ", with secret " + accessor.tokenSecret);
+
+        // Step 6: Access a protected resource
+        m_logService.log(LogService.LOG_DEBUG, "*** Step 6: Access protected 
resource ***");
+        String url = "http://"; + ConfigProvider.HOSTNAME + ":" + 
ConfigProvider.PORTNR + OAuthProtectedTestServlet.SERVLET_ALIAS;
+        message = consumerClient.accessResource(accessor, url);
+        String body = message.readBodyAsString();
+        m_logService.log(LogService.LOG_DEBUG, "Protected resource returns 
response: '" + body + "'");
+        Assert.assertTrue(body.equals("userid=ivol"));
+    }
+
+    // Step 1: Register a service consumer
+    private OAuthServiceConsumer registerServiceConsumer() throws Exception {
+        Dictionary<String, String> properties = new Hashtable<String, 
String>();
+        properties.put("consumer_key", OAuthTestConsumer.DEFAULT_CONSUMER_KEY);
+        OAuthTestConsumer testConsumer = new OAuthTestConsumer();
+        m_dependencyManager.add(
+            m_dependencyManager.createComponent()
+            .setInterface(OAuthServiceConsumer.class.getName(), properties)
+            .setImplementation(testConsumer));
+
+        // Check if it becomes available
+        Assert.assertTrue("OAuth service consumer is not begin registered", 
getService(OAuthServiceConsumer.class,
+            "consumer_key=" + OAuthTestConsumer.DEFAULT_CONSUMER_KEY) != null);
+
+        // We have to wait until the service consumer is picked up by our 
token provider. We retry this for a
+        // maximum amount of 5 times
+        OAuthMessage message = new OAuthMessage(null, null, null);
+        message.addParameter(OAuth.OAUTH_CONSUMER_KEY, 
OAuthTestConsumer.DEFAULT_CONSUMER_KEY);
+        OAuthConsumer consumer = null;
+        int retryCount = 0;
+        while (consumer == null && retryCount < 5) {
+            try {
+                consumer = m_tokenProvider.getConsumer(message);
+            }
+            catch (IOException e) {}
+            catch (OAuthProblemException e) {}
+            if (consumer == null) {
+                m_logService.log(LogService.LOG_DEBUG,
+                    "OAuth consumer not yet picked by by token provider, 
retrycount=" + (retryCount + 1));
+                Thread.sleep(1000);
+                retryCount++;
+            }
+        }
+        Assert.assertTrue("OAuth service consumer seems not being picked up by 
the token provider", consumer != null);
+        m_logService.log(LogService.LOG_DEBUG, "Service consumer registered 
successfully");
+        return testConsumer;
+    }
+
+    // Step 3: Generate a request token for our service consumer
+    private OAuthAccessor createRequestToken(OAuthServiceConsumerClient 
client) throws Exception {
+        OAuthAccessor accessor = client.generateRequestToken();
+        String requestToken = accessor.requestToken;
+        String tokenSecret = accessor.tokenSecret;
+        m_logService.log(LogService.LOG_DEBUG, "Request token received: " + 
requestToken + ", token secret="
+            + tokenSecret);
+        return accessor;
+    }
+}
\ No newline at end of file

Added: 
trunk/integration-tests/src/test/java/org/amdatu/test/integration/tests/OAuthServiceConsumerRegistryTest.java
==============================================================================
--- (empty file)
+++ 
trunk/integration-tests/src/test/java/org/amdatu/test/integration/tests/OAuthServiceConsumerRegistryTest.java
       Thu Dec  2 15:47:28 2010
@@ -0,0 +1,220 @@
+/*
+ Copyright (C) 2010 Amdatu.org
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+package org.amdatu.test.integration.tests;
+
+import static org.ops4j.pax.exam.CoreOptions.provision;
+
+import java.io.IOException;
+
+import org.amdatu.authentication.oauth.server.OAuthServiceConsumerRegistry;
+import org.amdatu.test.integration.base.ConfigProvider;
+import org.amdatu.test.integration.base.IntegrationTestBase;
+import org.amdatu.test.integration.mock.OAuthTestConsumer;
+import org.apache.commons.httpclient.HttpClient;
+import org.apache.commons.httpclient.HttpException;
+import org.apache.commons.httpclient.methods.DeleteMethod;
+import org.apache.commons.httpclient.methods.GetMethod;
+import org.apache.commons.httpclient.methods.PutMethod;
+import org.apache.commons.httpclient.methods.RequestEntity;
+import org.apache.commons.httpclient.methods.StringRequestEntity;
+import org.apache.felix.dm.Component;
+import org.apache.felix.dm.DependencyManager;
+import org.apache.http.HttpStatus;
+import org.json.JSONException;
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.ops4j.pax.exam.Option;
+import org.ops4j.pax.exam.junit.Configuration;
+import org.ops4j.pax.exam.junit.JUnit4TestRunner;
+import org.osgi.service.cm.ConfigurationAdmin;
+import org.osgi.service.log.LogService;
+
+ at RunWith(JUnit4TestRunner.class)
+public class OAuthServiceConsumerRegistryTest extends IntegrationTestBase {
+    private final static String CONSUMERS_REST_RESOURCE = 
"/rest/services/oauth/consumers/oauth/consumers";
+
+    private volatile LogService m_logService;
+    private volatile ConfigurationAdmin m_configAdmin;
+    
+    private String m_baseUrl;
+
+    @Configuration
+    public Option[] configure() {
+        return super.configure();
+    }
+    
+    protected void initConfiguration() throws IOException {
+        m_configAdmin = getService(ConfigurationAdmin.class);
+        
+        // Add cassandra and templates configs
+        ConfigProvider configProvider = new ConfigProvider();
+        configProvider.addHttpServiceConfig(m_configAdmin);
+        configProvider.addOAuthConfig(m_configAdmin);
+        configProvider.addLogConfig(m_configAdmin);
+    }
+
+    protected Component[] getDependencies(DependencyManager manager) {
+        Component testComponent = manager.createComponent()
+            .setImplementation(this)
+            
.add(manager.createServiceDependency().setService(ConfigurationAdmin.class).setRequired(true))
+            
.add(manager.createServiceDependency().setService(OAuthServiceConsumerRegistry.class).setRequired(true))
+            
.add(manager.createServiceDependency().setService(LogService.class).setRequired(true));
+
+        return new Component[] { testComponent };
+    }
+
+    protected Option provisionBundles() {
+        return provision(
+            felixHttpServiceJetty(),
+            felixHttpServiceWhiteboard(),
+            slingMime(),
+            slingCommons(),
+            json(),
+            commonsCodec(),
+            commonsLogging(),
+            commonsHttpClient(),
+            paxSwissbox(),
+            ops4jBaseLang(),
+            amdatuWink(),
+            amdatuHttpContext(),
+            amdatuJaxRs(),
+            amdatuOAuthAPI(),
+            amdatuOAuthClient(),
+            amdatuOAuthServer(),
+            amdatuJspSupport());
+    }
+
+    @Test
+    // Test the REST service that provides CRUD operations on the consumer 
registry of the oAuth server
+    public void testRestService() throws Exception {
+        m_baseUrl = "http://"; + ConfigProvider.HOSTNAME + ":" + 
ConfigProvider.PORTNR;
+        m_logService.log(LogService.LOG_DEBUG, "Base URL = " + m_baseUrl);
+
+        HttpClient httpClient = new HttpClient();
+        
+        // First add a new consumer using the JSON format
+        OAuthTestConsumer consumer = new OAuthTestConsumer();
+        int statusCode = putConsumer(httpClient, "application/json", consumer, 
false);
+        Assert.assertTrue("OAuth Service Consumer registry REST service 
returns " + statusCode + " on addConsumer", 
+            statusCode == HttpStatus.SC_OK);
+        
+        // Retrieve the new consumer in XML and JSON format
+        OAuthTestConsumer testConsumer = getConsumer(httpClient, 
"application/json", consumer.getConsumerKey());
+        Assert.assertTrue("Returned JSON consumer is incorrect: " + 
testConsumer.toString(), 
+            consumer.equals(testConsumer));
+        testConsumer = getConsumer(httpClient, "application/xml", 
consumer.getConsumerKey());
+        Assert.assertTrue("Returned XML consumer is incorrect", 
+            consumer.equals(testConsumer));
+        
+        // Now try to add another consumer using the Atom XML format, this 
should result in a 304 since the consumer
+        // already exists
+        statusCode = putConsumer(httpClient, "application/json", consumer, 
false);
+        Assert.assertTrue("OAuth Service Consumer registry REST service 
returns " + statusCode + " on addConsumer", 
+            statusCode == HttpStatus.SC_NOT_MODIFIED);
+        
+        // Now update the test consumer
+        consumer.setConsumerSecret("new " + 
OAuthTestConsumer.DEFAULT_CONSUMER_SECRET);
+        consumer.setCallbackUrl("new " + 
OAuthTestConsumer.DEFAULT_CALLBACK_URL);
+        consumer.setName("new " + OAuthTestConsumer.DEFAULT_CONSUMER_NAME);
+        statusCode = putConsumer(httpClient, "application/json", consumer, 
true);
+        Assert.assertTrue("OAuth Service Consumer registry REST service 
returns " + statusCode + " on updateConsumer", 
+            statusCode == HttpStatus.SC_OK);
+        
+        // And check if the update was handled properly
+        testConsumer = getConsumer(httpClient, "application/json", 
consumer.getConsumerKey());
+        Assert.assertTrue("Returned JSON consumer is incorrect: " + 
testConsumer.toString(), 
+            consumer.equals(testConsumer));
+        testConsumer = getConsumer(httpClient, "application/xml", 
consumer.getConsumerKey());
+        Assert.assertTrue("Returned XML consumer is incorrect", 
+            consumer.equals(testConsumer));
+        
+        // Now delete our test consumer
+        statusCode = deleteConsumer(httpClient, "application/json", 
consumer.getConsumerKey());
+        Assert.assertTrue("OAuth Service Consumer registry REST service 
returns " + statusCode + " on deleteConsumer", 
+            statusCode == HttpStatus.SC_OK);
+    }
+
+    private OAuthTestConsumer getConsumer(HttpClient httpClient, String 
mimeType, String consumerKey) throws HttpException, IOException, JSONException {
+        String url = m_baseUrl + CONSUMERS_REST_RESOURCE;
+        GetMethod getMethod = new GetMethod(url + "/" + consumerKey);
+        try {
+            // We want JSON!
+            getMethod.setRequestHeader("Accept", mimeType);
+            int statusCode = httpClient.executeMethod(getMethod);
+            Assert.assertTrue("OAuth Service Consumer registry REST service 
returns " + statusCode + " on getConsumer", 
+                statusCode == HttpStatus.SC_OK);
+            String body = new String(getMethod.getResponseBody(), "UTF-8");
+            m_logService.log(LogService.LOG_DEBUG, "Returned content for 
getConsumer in format " + mimeType + ": " + body);
+            if ("application/json".equals(mimeType)) {
+                return OAuthTestConsumer.fromJson(body);
+            } else if ("application/xml".equals(mimeType)) {
+                return OAuthTestConsumer.fromXML(body);
+            } else {
+                return null;
+            }
+        }
+        finally {
+            // Release the connection.
+            getMethod.releaseConnection();
+        }
+    }
+    
+    private int putConsumer(HttpClient httpClient, String mimeType, 
OAuthTestConsumer consumer, boolean update) throws JSONException, 
HttpException, IOException {
+        String url = m_baseUrl + CONSUMERS_REST_RESOURCE;
+        PutMethod method;
+        if (update) {
+            method = new PutMethod(url + "/" + consumer.getConsumerKey());
+        } else {
+            method = new PutMethod(url);
+        }
+        String body = null;
+        if ("application/xml".equals(mimeType)) {
+            body = consumer.toXML();
+        } else if ("application/json".equals(mimeType)) {
+            body = consumer.toJson().toString();
+        }
+        m_logService.log(LogService.LOG_DEBUG, "Adding consumer for " + 
mimeType + ", input=" + body);
+        RequestEntity requestEntity = new StringRequestEntity(body, mimeType, 
"UTF-8");
+        method.setRequestEntity(requestEntity);
+
+        // Execute the method, this should return a 200
+        try {
+            method.setRequestHeader("Content-type", mimeType);
+            return httpClient.executeMethod(method);
+        }
+        finally {
+            // Release the connection.
+            method.releaseConnection();
+        }
+    }
+    
+    private int deleteConsumer(HttpClient httpClient, String mimeType, String 
consumerKey) throws JSONException, HttpException, IOException {
+        String url = m_baseUrl + CONSUMERS_REST_RESOURCE;
+        DeleteMethod method = new DeleteMethod(url + "/" + consumerKey);
+        m_logService.log(LogService.LOG_DEBUG, "Deleting consumer for " + 
mimeType + ", input=" + consumerKey);
+
+        // Execute the method, this should return a 200
+        try {
+            return httpClient.executeMethod(method);
+        }
+        finally {
+            // Release the connection.
+            method.releaseConnection();
+        }
+    }
+}

Modified: trunk/pom.xml
==============================================================================
--- trunk/pom.xml       (original)
+++ trunk/pom.xml       Thu Dec  2 15:47:28 2010
@@ -346,6 +346,7 @@
   <modules>
     <!-- AMDATU-157 buildsupport must be first in reactor -->
     <module>amdatu-buildsupport</module>
+    <module>amdatu-authentication</module>
     <module>amdatu-authorization</module>
     <module>amdatu-cassandra</module>
     <module>amdatu-core</module>

Modified: trunk/src/main/resources/conf/felix-config.properties
==============================================================================
--- trunk/src/main/resources/conf/felix-config.properties       (original)
+++ trunk/src/main/resources/conf/felix-config.properties       Thu Dec  2 
15:47:28 2010
@@ -77,49 +77,52 @@
 # component is the target start level. Any number of these properties
 # may be specified for different start levels.
 
felix.auto.start.1=reference:file:amdatu-system/org.apache.felix.configadmin-1.2.4.jar
 \
-                                       
reference:file:amdatu-system/org.apache.felix.dependencymanager-3.0.0-SNAPSHOT.jar
 \
-                                       
reference:file:amdatu-system/org.apache.felix.eventadmin-1.2.2.jar \
-                                       
reference:file:amdatu-system/org.apache.felix.fileinstall-3.0.0.jar \
-                                       
reference:file:amdatu-system/org.apache.felix.log-1.0.0.jar \
-                                       
reference:file:amdatu-system/org.apache.felix.main-2.0.5.jar \
-                                       
reference:file:amdatu-system/org.apache.felix.metatype-1.0.4.jar \
-                                       
reference:file:amdatu-system/org.apache.felix.shell.tui-1.4.1.jar \
-                                       
reference:file:amdatu-system/org.apache.felix.shell-1.4.2.jar \
-                                       
reference:file:amdatu-system/org.apache.felix.webconsole-3.1.2.jar \
-                                       
reference:file:amdatu-system/org.apache.sling.commons.mime-2.1.4.jar \
-                                       
reference:file:amdatu-system/org.apache.sling.commons.osgi-2.0.6.jar \
-                                       
reference:file:amdatu-system/org.osgi.compendium-${org.osgi.version}.jar \
-                                       
reference:file:amdatu-system/org.osgi.core-${org.osgi.version}.jar \
-                                       
reference:file:amdatu-system/pax-useradmin-service-0.0.1-SNAPSHOT.jar \
-                                       
reference:file:amdatu-system/org.apache.felix.http.jetty-${org.apache.felix.http.version}.jar
 \
-                                       
reference:file:amdatu-system/org.apache.felix.http.whiteboard-${org.apache.felix.http.version}.jar
 \
-                                       
reference:file:amdatu-system/pax-swissbox-core-${pax.swissbox.version}.jar \
-                                       
reference:file:amdatu-system/ops4j-base-lang-1.2.2.jar \
-                                       
reference:file:amdatu-system/org.apache.felix.scr-1.6.0.jar
+          
reference:file:amdatu-system/org.apache.felix.dependencymanager-3.0.0-SNAPSHOT.jar
 \
+          reference:file:amdatu-system/org.apache.felix.eventadmin-1.2.2.jar \
+          reference:file:amdatu-system/org.apache.felix.fileinstall-3.0.0.jar \
+          reference:file:amdatu-system/org.apache.felix.log-1.0.0.jar \
+          reference:file:amdatu-system/org.apache.felix.main-2.0.5.jar \
+          reference:file:amdatu-system/org.apache.felix.metatype-1.0.4.jar \
+          reference:file:amdatu-system/org.apache.felix.shell.tui-1.4.1.jar \
+          reference:file:amdatu-system/org.apache.felix.shell-1.4.2.jar \
+          reference:file:amdatu-system/org.apache.felix.webconsole-3.1.2.jar \
+          reference:file:amdatu-system/org.apache.sling.commons.mime-2.1.4.jar 
\
+          reference:file:amdatu-system/org.apache.sling.commons.osgi-2.0.6.jar 
\
+          
reference:file:amdatu-system/org.osgi.compendium-${org.osgi.version}.jar \
+          reference:file:amdatu-system/org.osgi.core-${org.osgi.version}.jar \
+          
reference:file:amdatu-system/pax-useradmin-service-0.0.1-SNAPSHOT.jar \
+          
reference:file:amdatu-system/org.apache.felix.http.jetty-${org.apache.felix.http.version}.jar
 \
+          
reference:file:amdatu-system/org.apache.felix.http.whiteboard-${org.apache.felix.http.version}.jar
 \
+          
reference:file:amdatu-system/pax-swissbox-core-${pax.swissbox.version}.jar \
+          reference:file:amdatu-system/ops4j-base-lang-1.2.2.jar \
+          reference:file:amdatu-system/org.apache.felix.scr-1.6.0.jar
 
felix.auto.start.2=reference:file:amdatu-core/org.amdatu.core.config.filebased-${platform.version}.jar
 \
-                                       
reference:file:amdatu-application/org.amdatu.cassandra.application-${platform.version}.jar
 \
-                                       
reference:file:amdatu-application/org.amdatu.cassandra.listener-${platform.version}.jar
 \
-                                       
reference:file:amdatu-application/org.amdatu.cassandra.persistencemanager-${platform.version}.jar
 \
-                                       
reference:file:amdatu-core/org.amdatu.core.loghandler-${platform.version}.jar \
-                                       
reference:file:amdatu-core/org.amdatu.core.tenant-${platform.version}.jar \
-                                       
reference:file:amdatu-core/org.amdatu.core.config.templates-${platform.version}.jar
 \
-                                       
reference:file:amdatu-application/org.amdatu.cassandra.tenantstore-${platform.version}.jar
 \
-                                       
reference:file:amdatu-application/org.amdatu.cassandra.useradminstore-${platform.version}.jar
 \
-                                       
reference:file:amdatu-application/org.amdatu.web.rest.jaxrs-${platform.version}.jar
 \
-                                       
reference:file:amdatu-application/org.amdatu.web.rest.wink-${platform.version}.jar
 
+          
reference:file:amdatu-application/org.amdatu.cassandra.application-${platform.version}.jar
 \
+          
reference:file:amdatu-application/org.amdatu.cassandra.listener-${platform.version}.jar
 \
+          
reference:file:amdatu-application/org.amdatu.cassandra.persistencemanager-${platform.version}.jar
 \
+          
reference:file:amdatu-core/org.amdatu.core.loghandler-${platform.version}.jar \
+          
reference:file:amdatu-core/org.amdatu.core.tenant-${platform.version}.jar \
+          
reference:file:amdatu-core/org.amdatu.core.config.templates-${platform.version}.jar
 \
+          
reference:file:amdatu-application/org.amdatu.cassandra.tenantstore-${platform.version}.jar
 \
+          
reference:file:amdatu-application/org.amdatu.cassandra.useradminstore-${platform.version}.jar
 \
+          
reference:file:amdatu-application/org.amdatu.web.rest.jaxrs-${platform.version}.jar
 \
+          
reference:file:amdatu-application/org.amdatu.web.rest.wink-${platform.version}.jar
 
 
felix.auto.start.10=reference:file:amdatu-application/org.amdatu.opensocial.shindig-${platform.version}.jar
 \
-                                       
reference:file:amdatu-application/org.amdatu.opensocial.profile-${platform.version}.jar
 \
-                                       
reference:file:amdatu-application/org.amdatu.authorization.login.service-${platform.version}.jar
 \
-                                       
reference:file:amdatu-application/org.amdatu.web.httpcontext-${platform.version}.jar
 \
-                                       
reference:file:amdatu-application/org.amdatu.semanticweb.sesame-${platform.version}.jar
 \
-                                       
reference:file:amdatu-application/org.amdatu.opensocial.dashboard-${platform.version}.jar
 \
-                                       
reference:file:amdatu-application/org.amdatu.opensocial.gadgetmanagement-${platform.version}.jar
 \
-                                       
reference:file:amdatu-application/org.amdatu.web.jsp-${platform.version}.jar \
-                                       
reference:file:amdatu-application/org.amdatu.semanticweb.sparqlendpoint-${platform.version}.jar
 \
-                                       
reference:file:amdatu-application/org.amdatu.authorization.login.gadget-${platform.version}.jar
+          
reference:file:amdatu-application/org.amdatu.opensocial.profile-${platform.version}.jar
 \
+          
reference:file:amdatu-application/org.amdatu.authorization.login.service-${platform.version}.jar
 \
+          
reference:file:amdatu-application/org.amdatu.web.httpcontext-${platform.version}.jar
 \
+          
reference:file:amdatu-application/org.amdatu.semanticweb.sesame-${platform.version}.jar
 \
+          
reference:file:amdatu-application/org.amdatu.opensocial.dashboard-${platform.version}.jar
 \
+          
reference:file:amdatu-application/org.amdatu.opensocial.gadgetmanagement-${platform.version}.jar
 \
+          
reference:file:amdatu-application/org.amdatu.web.jsp-${platform.version}.jar \
+          
reference:file:amdatu-application/org.amdatu.semanticweb.sparqlendpoint-${platform.version}.jar
 \
+          
reference:file:amdatu-application/org.amdatu.authorization.login.gadget-${platform.version}.jar
 \
+          
reference:file:amdatu-application/org.amdatu.authentication.oauth.api-${platform.version}.jar
 \
+          
reference:file:amdatu-application/org.amdatu.authentication.oauth.client-${platform.version}.jar
 \
+          
reference:file:amdatu-application/org.amdatu.authentication.oauth.server-${platform.version}.jar
 
felix.auto.start.20=reference:file:amdatu-examples/org.amdatu.example.friends.gadget-${platform.version}.jar
 \
-                                       
reference:file:amdatu-examples/org.amdatu.example.course.gadget-${platform.version}.jar
 \
-                                       
reference:file:amdatu-examples/org.amdatu.example.course.service-${platform.version}.jar
+          
reference:file:amdatu-examples/org.amdatu.example.course.gadget-${platform.version}.jar
 \
+          
reference:file:amdatu-examples/org.amdatu.example.course.service-${platform.version}.jar
 
 # Sets the initial start level of the framework upon startup.
 org.osgi.framework.startlevel.beginning=30

Reply via email to