Author: ivol37 at gmail.com
Date: Wed Jan  5 16:00:04 2011
New Revision: 565

Log:
First context patch

Added:
   sandbox/ivol/
   sandbox/ivol/r564-context-patch.patch

Added: sandbox/ivol/r564-context-patch.patch
==============================================================================
--- (empty file)
+++ sandbox/ivol/r564-context-patch.patch       Wed Jan  5 16:00:04 2011
@@ -0,0 +1,3280 @@
+Index: amdatu-authentication/contextmanager/pom.xml
+===================================================================
+--- amdatu-authentication/contextmanager/pom.xml       (revision 0)
++++ amdatu-authentication/contextmanager/pom.xml       (revision 0)
+@@ -0,0 +1,31 @@
++<?xml version="1.0" encoding="UTF-8"?>
++<project xmlns="http://maven.apache.org/POM/4.0.0"; 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
++  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
http://maven.apache.org/maven-v4_0_0.xsd";>
++  <modelVersion>4.0.0</modelVersion>
++  <parent>
++    <groupId>org.amdatu</groupId>
++    <artifactId>org.amdatu.authentication</artifactId>
++    <version>0.1.0-SNAPSHOT</version>
++  </parent>
++  <groupId>org.amdatu.authentication</groupId>
++  <artifactId>contextmanager</artifactId>
++  <packaging>bundle</packaging>
++  <name>Amdatu Authentication - Context manager</name>
++  <description>This bundle provides a generic pluggable context 
manager</description>
++
++  <build>
++    <plugins>
++      <plugin>
++        <groupId>org.apache.felix</groupId>
++        <artifactId>maven-bundle-plugin</artifactId>
++        <configuration>
++          <instructions>
++            
<Bundle-Activator>org.amdatu.authentication.contextmanager.osgi.Activator</Bundle-Activator>
++            
<Bundle-SymbolicName>org.amdatu.authentication.contextmanager</Bundle-SymbolicName>
++            
<Export-Package>org.amdatu.authentication.contextmanager</Export-Package>
++          </instructions>
++        </configuration>
++      </plugin>
++    </plugins>
++  </build>
++</project>
+Index: 
amdatu-authentication/contextmanager/src/main/java/org/amdatu/authentication/contextmanager/ContextManager.java
+===================================================================
+--- 
amdatu-authentication/contextmanager/src/main/java/org/amdatu/authentication/contextmanager/ContextManager.java
    (revision 0)
++++ 
amdatu-authentication/contextmanager/src/main/java/org/amdatu/authentication/contextmanager/ContextManager.java
    (revision 0)
+@@ -0,0 +1,51 @@
++/*
++    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.contextmanager;
++
++import java.util.Map;
++
++/**
++ * The Context Manager is responsible for managing context providers. It 
keeps a list of all available
++ * context providers. It will only add providers to this registry when their 
ID has not been added yet;
++ * each context provider MUST have a unique identifier identifying itself.
++ * The context manager provides methods to retrieve properties from the 
context and to resolve context
++ * information from any property (i.e. a HTTP request). The context manager 
in fact just delegates these calls
++ * to the available context providers.
++ * 
++ * @author ivol
++ */
++public interface ContextManager {
++    /**
++     * Retrieves a value from a context.
++     * @param providerId The id of the provider to retrieve the value from.
++     * @param property The name of the property to retrieve
++     * @return The value of the context property retrieved from the specified 
provider, null if the property
++     * could not be found or is not availble.
++     * @throws UnknownProviderException In case no provider is available in 
the provider registry that matches
++     * the specified identifier.
++     */
++    String getValue(String providerId, String property) throws 
UnknownProviderException;
++
++    /**
++     * Resolves context(s) from the specified map of properties. This method 
will be delegated to each
++     * available context provider. The map of properties may contain any 
arbitrary property. Default
++     * properties that may be available are covered by ContextProvider (i.e. 
ContextProvider.PROPERTY_HTTP_REQUEST).
++     * @param context A map of arbitrary properties that may resolve to 
certain contextual information in
++     * available context providers.
++     */
++    void resolve(Map<String, Object> properties);
++}
+Index: 
amdatu-authentication/contextmanager/src/main/java/org/amdatu/authentication/contextmanager/ContextProvider.java
+===================================================================
+--- 
amdatu-authentication/contextmanager/src/main/java/org/amdatu/authentication/contextmanager/ContextProvider.java
   (revision 0)
++++ 
amdatu-authentication/contextmanager/src/main/java/org/amdatu/authentication/contextmanager/ContextProvider.java
   (revision 0)
+@@ -0,0 +1,60 @@
++/*
++    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.contextmanager;
++
++import java.util.Map;
++
++/**
++ * A context provider represents one specific piece of the overall context. 
It is responsible for
++ * managing that piece of context in terms of retrieving values from it and 
resolving the context
++ * from a given set of properties.
++ * Context providers are managed by the Context Manager, which keeps a 
registry of available
++ * context providers. Each context provider MUST have a unique identifier 
(returned by getId()). The
++ *  set of available properties in this context is up to the implementation 
as well as resolving
++ *  the context properties from a set of arbitrary properties.
++ * @author ivol
++ */
++public interface ContextProvider {
++    /**
++     * Name of a context resolver property holding a HTTP request.
++     */
++    String PROPERTY_HTTP_REQUEST = "httprequest";
++
++    /**
++     * Returns the unique identifier of this context provider. If multiple 
context provider try to
++     * claim the same identifier, one of them will not be registered in the 
ContextManager
++     * and will this be unusable.
++     * @return The unique identifier of this context provider.
++     */
++    String getId();
++
++    /**
++     * Returns a value managed by this context provider.
++     * @param propertyName Name of the property to retrieve
++     * @return The value of this property or null if no such property exists
++     */
++    String getValue(String propertyName);
++
++    /**
++     * Invoked to allow the context provider to resolve a given set of 
arbitrary properties to
++     * a certain context. The map contains an arbitrary set of properties, 
but a default list of
++     * properties that may be available is covered by this interface (i.e. 
PROPERTY_HTTP_REQUEST).
++     * @param properties Map of arbitrary properties which could be resolved 
to a context by
++     * this context provider.
++     */
++    void resolve(Map<String, Object> properties);
++}
+Index: 
amdatu-authentication/contextmanager/src/main/java/org/amdatu/authentication/contextmanager/osgi/Activator.java
+===================================================================
+--- 
amdatu-authentication/contextmanager/src/main/java/org/amdatu/authentication/contextmanager/osgi/Activator.java
    (revision 0)
++++ 
amdatu-authentication/contextmanager/src/main/java/org/amdatu/authentication/contextmanager/osgi/Activator.java
    (revision 0)
+@@ -0,0 +1,43 @@
++/*
++    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.contextmanager.osgi;
++
++import org.amdatu.authentication.contextmanager.ContextManager;
++import org.amdatu.authentication.contextmanager.ContextProvider;
++import org.amdatu.authentication.contextmanager.service.ContextManagerImpl;
++import org.apache.felix.dm.DependencyActivatorBase;
++import org.apache.felix.dm.DependencyManager;
++import org.osgi.framework.BundleContext;
++
++/**
++ * This is the activator for the context manager bundle
++ * @author ivol
++ */
++public class Activator extends DependencyActivatorBase {
++    @Override
++    public void init(BundleContext context, DependencyManager manager) throws 
Exception {
++        // Register the ContextManager service
++        manager.add(createComponent()
++            .setInterface(ContextManager.class.getName(), null)
++            .setImplementation(ContextManagerImpl.class)
++            
.add(createServiceDependency().setService(ContextProvider.class).setCallbacks("onAdded",
 "onRemoved")));
++    }
++
++    @Override
++    public void destroy(BundleContext bundleContext, DependencyManager 
dependencyManager) throws Exception {
++    }
++}
+Index: 
amdatu-authentication/contextmanager/src/main/java/org/amdatu/authentication/contextmanager/service/ContextManagerImpl.java
+===================================================================
+--- 
amdatu-authentication/contextmanager/src/main/java/org/amdatu/authentication/contextmanager/service/ContextManagerImpl.java
        (revision 0)
++++ 
amdatu-authentication/contextmanager/src/main/java/org/amdatu/authentication/contextmanager/service/ContextManagerImpl.java
        (revision 0)
+@@ -0,0 +1,100 @@
++/*
++    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.contextmanager.service;
++
++import java.util.ArrayList;
++import java.util.List;
++import java.util.Map;
++
++import org.amdatu.authentication.contextmanager.ContextManager;
++import org.amdatu.authentication.contextmanager.ContextProvider;
++import org.amdatu.authentication.contextmanager.UnknownProviderException;
++import org.osgi.framework.ServiceReference;
++
++/**
++ * This class implements the ContextManager.
++ * 
++ * @author ivol
++ */
++public class ContextManagerImpl implements ContextManager {
++    // List of available context providers.
++    private List<ContextProvider> m_contextProviders = new 
ArrayList<ContextProvider>();
++
++    // Invoked when a service provider comes available
++    public void onAdded(ServiceReference ref, Object service) {
++        if (service instanceof ContextProvider) {
++            addContextProvider((ContextProvider) service);
++        }
++    }
++
++    // Invoked when a service provider comes unavailable
++    public void onRemoved(ServiceReference ref, Object service) {
++        if (service instanceof ContextProvider) {
++            removeContextProvider((ContextProvider) service);
++        }
++    }
++
++    // Adds a context provider to the registry, but only if no provider is 
available that
++    // mtaches the id of the context provider to be added.
++    private void addContextProvider(ContextProvider contextProvider) {
++        if (contextProvider.getId() == null || 
contextProvider.getId().trim().isEmpty()) {
++            // Reject context providers with empty id
++            return;
++        }
++        if (getContextProvider(contextProvider.getId()) != null) {
++            // Reject adding context providers that already exist with this id
++            return;
++        }
++        m_contextProviders.add(contextProvider);
++    }
++
++    // Removed the context provider from the registry
++    private void removeContextProvider(ContextProvider contextProvider) {
++        ContextProvider provider = 
getContextProvider(contextProvider.getId());
++        if (provider != null) {
++            m_contextProviders.remove(provider);
++            return;
++        }
++    }
++
++    // Returns a context provider that matches the specified id
++    private ContextProvider getContextProvider(String id) {
++        for (ContextProvider provider : m_contextProviders) {
++            if (provider.getId().equals(id)) {
++                return provider;
++            }
++        }
++        return null;
++    }
++
++    // Returns the value from the specified property from the specified 
provider
++    public String getValue(String providerId, String property) throws 
UnknownProviderException {
++        ContextProvider provider = getContextProvider(providerId);
++        if (provider != null) {
++            return provider.getValue(property);
++        } else {
++            throw new UnknownProviderException("Provider '" + providerId + "' 
is not available");
++        }
++    }
++
++    // Resolve contexts; just delegate to all available context providers
++    public void resolve(Map<String, Object> context) {
++        for (ContextProvider provider : m_contextProviders) {
++            provider.resolve(context);
++        }
++    }
++}
+Index: 
amdatu-authentication/contextmanager/src/main/java/org/amdatu/authentication/contextmanager/UnknownProviderException.java
+===================================================================
+--- 
amdatu-authentication/contextmanager/src/main/java/org/amdatu/authentication/contextmanager/UnknownProviderException.java
  (revision 0)
++++ 
amdatu-authentication/contextmanager/src/main/java/org/amdatu/authentication/contextmanager/UnknownProviderException.java
  (revision 0)
+@@ -0,0 +1,48 @@
++/*
++    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.contextmanager;
++
++/**
++ * Exception thrown by the ContextManager in case a property is requested 
from a provider id that
++ * is not available.
++ * 
++ * @author ivol
++ */
++public class UnknownProviderException extends Exception {
++    /**
++     * Serial version UID of this class.
++     */
++    private static final long serialVersionUID = -5721742545697762926L;
++
++    /**
++     * Constructs a UnknownProviderException.
++     *
++     * @param msg An error message providing more information about the cause 
of the error.
++     */
++    public UnknownProviderException(String msg) {
++        super(msg);
++    }
++
++    /**
++     * Constructs a new UnknownProviderException.
++     *
++     * @param t An exception providing more information about the cause of 
the error.
++     */
++    public UnknownProviderException(Throwable t) {
++        super(t);
++    }
++}
+\ No newline at end of file
+Index: amdatu-authentication/oauth-server/pom.xml
+===================================================================
+--- amdatu-authentication/oauth-server/pom.xml (revision 564)
++++ amdatu-authentication/oauth-server/pom.xml (working copy)
+@@ -12,7 +12,7 @@
+   <packaging>bundle</packaging>
+   <name>Amdatu Authentication - oAuth server</name>
+   <description>This bundle includes an API for oAuth service 
providers</description>
+-  
++
+   <dependencies>
+     <dependency>
+       <groupId>org.amdatu.web</groupId>
+@@ -31,7 +31,7 @@
+     <dependency>
+       <groupId>org.amdatu.authentication.oauth</groupId>
+       <artifactId>api</artifactId>
+-      <version>${platform.version}</version>   
++      <version>${platform.version}</version>
+       <scope>provided</scope>
+       <type>bundle</type>
+     </dependency>
+@@ -77,9 +77,23 @@
+       <artifactId>tokenprovider</artifactId>
+       <version>${platform.version}</version>
+       <scope>provided</scope>
+-    </dependency>    
++    </dependency>
++    <dependency>
++      <groupId>org.amdatu.authentication</groupId>
++      <artifactId>contextmanager</artifactId>
++      <version>${platform.version}</version>
++      <scope>provided</scope>
++      <type>bundle</type>
++    </dependency>
++    <dependency>
++      <groupId>org.amdatu.authorization.login</groupId>
++      <artifactId>service</artifactId>
++      <version>${platform.version}</version>
++      <scope>provided</scope>
++      <type>bundle</type>
++    </dependency>
+   </dependencies>
+-  
++
+   <build>
+     <plugins>
+       <plugin>
+@@ -100,5 +114,5 @@
+         </configuration>
+       </plugin>
+     </plugins>
+-  </build> 
++  </build>
+ </project>
+Index: 
amdatu-authentication/oauth-server/src/main/java/org/amdatu/authentication/oauth/server/service/OAuthAuthorizeTokenServletImpl.java
+===================================================================
+--- 
amdatu-authentication/oauth-server/src/main/java/org/amdatu/authentication/oauth/server/service/OAuthAuthorizeTokenServletImpl.java
        (revision 564)
++++ 
amdatu-authentication/oauth-server/src/main/java/org/amdatu/authentication/oauth/server/service/OAuthAuthorizeTokenServletImpl.java
        (working copy)
+@@ -18,11 +18,9 @@
+ 
+ import java.io.IOException;
+ import java.io.PrintWriter;
+-import java.util.Map;
+ 
+ import javax.servlet.ServletConfig;
+ import javax.servlet.ServletException;
+-import javax.servlet.http.Cookie;
+ import javax.servlet.http.HttpServlet;
+ import javax.servlet.http.HttpServletRequest;
+ import javax.servlet.http.HttpServletRequestWrapper;
+@@ -37,27 +35,26 @@
+ import org.amdatu.authentication.oauth.api.OAuthServiceProvider;
+ import org.amdatu.authentication.oauth.server.OAuthAuthorizeTokenServlet;
+ import org.amdatu.authentication.oauth.server.OAuthTokenProvider;
+-import org.amdatu.authentication.tokenprovider.InvalidTokenException;
+-import org.amdatu.authentication.tokenprovider.TokenProvider;
+-import org.amdatu.authentication.tokenprovider.TokenProviderException;
++import org.amdatu.authentication.contextmanager.ContextManager;
++import org.amdatu.authorization.login.service.LoginContextProvider;
+ import org.osgi.service.log.LogService;
+ 
+ public class OAuthAuthorizeTokenServletImpl extends HttpServlet implements 
OAuthAuthorizeTokenServlet {
+     // The serial version UID of this servlet
+     private static final long serialVersionUID = -3589350956712947896L;
+-    
++
+     // Service dependencies, injected by the Felix dependency manager
+     private volatile LogService m_logService;
+-    private volatile TokenProvider m_tokenProvider;
+     private volatile OAuthTokenProvider m_oAuthTokenProvider;
+     private volatile OAuthServiceProvider m_serviceProvider;
+-    
++    private volatile ContextManager m_contextManager;
++
+     public void init(ServletConfig config) throws ServletException {
+         super.init(config);
+     }
+ 
+     public void doGet(HttpServletRequest request, HttpServletResponse 
response) throws IOException, ServletException {
+-       try {
++        try {
+             OAuthMessage requestMessage = OAuthServlet.getMessage(request, 
null);
+             OAuthAccessor accessor = 
m_oAuthTokenProvider.getAccessor(requestMessage);
+             if (Boolean.TRUE.equals(accessor.getProperty("authorized"))) {
+@@ -80,7 +77,7 @@
+         try {
+             OAuthMessage requestMessage = OAuthServlet.getMessage(request, 
null);
+             OAuthAccessor accessor = 
m_oAuthTokenProvider.getAccessor(requestMessage);
+-            String userId = getUserId(request);
++            String userId = 
m_contextManager.getValue(LoginContextProvider.ID, 
LoginContextProvider.USERNAME);
+             if (userId == null) {
+                 // If there is no userid available now, we throw a permission 
denied as it won't happen in a normal situation!
+                 // Maybe it's a hack attempt.
+@@ -97,7 +94,7 @@
+     }
+ 
+     private void sendToAuthorizePage(HttpServletRequest request, 
HttpServletResponse response, OAuthAccessor accessor)
+-        throws IOException, ServletException {
++    throws IOException, ServletException {
+         String callback = request.getParameter("oauth_callback");
+         if (callback == null || callback.length() <= 0) {
+             callback = "none";
+@@ -108,26 +105,26 @@
+         request.setAttribute("TOKEN", accessor.requestToken);
+         m_logService.log(LogService.LOG_DEBUG, "Forwarding authorize token 
request to " + m_serviceProvider.getAuthorizeURL()
+             + ", token=" + accessor.requestToken + ", callback=" + callback);
+-       
++
+         // Create a request wrapper returning the path of the JSP servlet 
instead of this servlet
+         HttpServletRequestWrapper wrapper = new 
HttpServletRequestWrapper(request) {
+             public String getPathInfo() {
+                 return m_serviceProvider.getAuthorizeURL();
+             }
+         };
+-        
++
+         // Dispatch the request to the authorize JSP
+         
request.getRequestDispatcher(m_serviceProvider.getAuthorizeURL()).forward(wrapper,
 response);
+     }
+ 
+     private void returnToConsumer(HttpServletRequest request,
+         HttpServletResponse response, OAuthAccessor accessor)
+-        throws IOException, ServletException {
++    throws IOException, ServletException {
+         // send the user back to site's callBackUrl
+         String callback = request.getParameter("oauth_callback");
+         if ("none".equals(callback)
+-            && accessor.consumer.callbackURL != null
+-            && accessor.consumer.callbackURL.length() > 0) {
++                        && accessor.consumer.callbackURL != null
++                        && accessor.consumer.callbackURL.length() > 0) {
+             // first check if we have something in our properties file
+             callback = accessor.consumer.callbackURL;
+         }
+@@ -144,8 +141,9 @@
+         }
+         else {
+             // if callback is not passed in, use the callback from config
+-            if (callback == null || callback.length() <= 0)
++            if (callback == null || callback.length() <= 0) {
+                 callback = accessor.consumer.callbackURL;
++            }
+             String token = accessor.requestToken;
+             if (token != null) {
+                 callback = OAuth.addParameters(callback, "oauth_token", 
token);
+@@ -155,15 +153,4 @@
+             response.setHeader("Location", callback);
+         }
+     }
+-    
+-    private String getUserId(HttpServletRequest request) throws 
TokenProviderException, InvalidTokenException {
+-        // Get the token, retrieve attributes stored in it and get the 
USERNAME from it
+-        String token = m_tokenProvider.getTokenFromRequest(request);
+-        if (token != null) {
+-            Map<String, String> attributes = 
m_tokenProvider.verifyToken(token);
+-            return attributes.get(TokenProvider.USERNAME);
+-        } else {
+-            return null;
+-        }
+-    }
+ }
+Index: amdatu-authentication/pom.xml
+===================================================================
+--- amdatu-authentication/pom.xml      (revision 564)
++++ amdatu-authentication/pom.xml      (working copy)
+@@ -11,21 +11,22 @@
+   <name>Amdatu Authentication</name>
+   <description>This module consists of all Authentication related 
bundles</description>
+   <packaging>pom</packaging>
+-  
++
+   <dependencies>
+     <dependency>
+       <groupId>servletapi</groupId>
+       <artifactId>servletapi</artifactId>
+       <version>2.4</version>
+       <scope>provided</scope>
+-    </dependency>   
++    </dependency>
+   </dependencies>
+-  
++
+   <modules>
+     <module>oauth-api</module>
+     <module>oauth-client</module>
+     <module>oauth-server</module>
+     <module>oauth-consumerregistry-fs</module>
++    <module>contextmanager</module>
+     <module>tokenprovider</module>
+     <module>tokenstore-mem</module>
+   </modules>
+Index: 
amdatu-authentication/tokenprovider/src/main/java/org/amdatu/authentication/tokenprovider/osgi/Activator.java
+===================================================================
+--- 
amdatu-authentication/tokenprovider/src/main/java/org/amdatu/authentication/tokenprovider/osgi/Activator.java
      (revision 564)
++++ 
amdatu-authentication/tokenprovider/src/main/java/org/amdatu/authentication/tokenprovider/osgi/Activator.java
      (working copy)
+@@ -46,7 +46,7 @@
+             
.add(createServiceDependency().setService(LogService.class).setRequired(true))
+             
.add(createServiceDependency().setService(TokenStorageProvider.class).setRequired(true)));
+ 
+-        // Create and register the REST API for the token provider service 
component. 
++        // Create and register the REST API for the token provider service 
component.
+         // TODO: This REST interface is disabled for now for security reasons.
+         // See http://jira.amdatu.org/jira/browse/AMDATU-230
+         /*  manager.add(
+@@ -54,11 +54,11 @@
+             .setInterface(TokenRESTResource.class.getName(), null)
+             .setImplementation(TokenRESTResourceImpl.class)
+             
.add(createServiceDependency().setService(LogService.class).setRequired(true))
+-            
.add(createServiceDependency().setService(TokenProvider.class).setRequired(true)));
    */    
++            
.add(createServiceDependency().setService(TokenProvider.class).setRequired(true)));
    */
+     }
+ 
+     @Override
+     public void destroy(BundleContext bundleContext, DependencyManager 
dependencyManager) throws Exception {
+     }
+-    
++
+ }
+Index: 
amdatu-authentication/tokenprovider/src/main/java/org/amdatu/authentication/tokenprovider/service/TokenProviderImpl.java
+===================================================================
+--- 
amdatu-authentication/tokenprovider/src/main/java/org/amdatu/authentication/tokenprovider/service/TokenProviderImpl.java
   (revision 564)
++++ 
amdatu-authentication/tokenprovider/src/main/java/org/amdatu/authentication/tokenprovider/service/TokenProviderImpl.java
   (working copy)
+@@ -30,8 +30,6 @@
+ import javax.crypto.KeyGenerator;
+ import javax.crypto.NoSuchPaddingException;
+ import javax.crypto.SecretKey;
+-import javax.servlet.http.Cookie;
+-import javax.servlet.http.HttpServletRequest;
+ 
+ import org.amdatu.authentication.tokenprovider.InvalidTokenException;
+ import org.amdatu.authentication.tokenprovider.TokenProvider;
+@@ -43,9 +41,6 @@
+ import org.osgi.service.log.LogService;
+ 
+ public class TokenProviderImpl implements TokenProvider {
+-    // Name the authorization header when a token is passed in the 
"Authorization" header of a HTTP request
+-    public final static String AUTHORIZATION_HEADER = "Amdatu";
+-
+     // Service dependencies
+     private volatile LogService m_logService;
+ 
+@@ -251,27 +246,4 @@
+     public void invalidateToken(String encryptedToken) {
+         m_tokenStore.removeToken(encryptedToken);
+     }
+-
+-    public String getTokenFromRequest(HttpServletRequest request) {
+-        // Use case 1: The token is send along in a cookie with the request. 
The cookie is send
+-        // automatically when a request is send directly from the end users 
browser to the Amdatu server.
+-        if (request.getCookies() != null) {
+-            for (Cookie cookie : request.getCookies()) {
+-                if (TokenProvider.TOKEN_COOKIE_NAME.equals(cookie.getName())) 
{
+-                    return cookie.getValue();
+-                }
+-            }
+-        }
+-
+-        // Use case 2: When requests are not send from a browser (for example 
calls to gadgets.ui.makeRequest
+-        // proxied via an openSocial container) the token can be send in the 
Authorization header (like Basic
+-        // and Digest HTTP authentication).
+-        String authHeader = request.getHeader("Authorization");
+-        if (authHeader != null && !authHeader.isEmpty()) {
+-            if (authHeader.startsWith(AUTHORIZATION_HEADER + " ")) {
+-                return authHeader.substring(authHeader.indexOf(" ") + 1);
+-            }
+-        }
+-        return null;
+-    }
+ }
+Index: 
amdatu-authentication/tokenprovider/src/main/java/org/amdatu/authentication/tokenprovider/TokenProvider.java
+===================================================================
+--- 
amdatu-authentication/tokenprovider/src/main/java/org/amdatu/authentication/tokenprovider/TokenProvider.java
       (revision 564)
++++ 
amdatu-authentication/tokenprovider/src/main/java/org/amdatu/authentication/tokenprovider/TokenProvider.java
       (working copy)
+@@ -18,8 +18,6 @@
+ 
+ import java.util.SortedMap;
+ 
+-import javax.servlet.http.HttpServletRequest;
+-
+ /**
+  * This service facilitates generating tokens. A token is an encrypted set of 
attributes and a
+  * signature. The signature is generated from these attributes and a private 
key, only known to
+@@ -49,33 +47,38 @@
+      * Name of the cookie that stores an amdatu token.
+      */
+     final String TOKEN_COOKIE_NAME = "amdatu_token";
+-    
++
+     /**
++     *  Name of the authorization header when a token is passed in the 
"Authorization" header of a HTTP request
++     */
++    final String TOKEN_AUTHORIZATION_HEADER = "Amdatu";
++
++    /**
+      * Name under which the nonce parameter is stored.
+      */
+     final String NONCE = "token_nonce";
+-    
++
+     /**
+      * Name under which the timestamp parameter is stored.
+      */
+     final String TIMESTAMP = "token_timestamp";
+-    
++
+     /**
+      * Name under which a username parameter can be stored (this is optional).
+      */
+     final String USERNAME = "token_username";
+-    
++
+     /**
+      * Generates a new token for the specified set of token attributes. First 
of all a signature is created
+      * from the set of attributes using a private key, only known by this 
token provider. The atributes are
+-     * converted to a single String and together with the signature this 
forms the unencrypted token. 
++     * converted to a single String and together with the signature this 
forms the unencrypted token.
+      * Finally, the token is encrypted using aAES encryption method, again 
using a private key only known
+      * by this token provider. This encrypted token is returned.
+      * Note that to this list of attributes always a nonce and a timestamp 
are added. Therefore attributes
+      * with names NONCE or TIMESTAMP are preserved and should not be used. A 
TokenProviderException is thrown
+      * in case the map of attributes already contains these attributes.
+      * 
+-     * @param attributes The attributes to create the token for. May be empty 
or null, in which case the 
++     * @param attributes The attributes to create the token for. May be empty 
or null, in which case the
+      * token is generated from only a nonce and a timestamp.
+      * @return The generated encrypted token
+      * @throws TokenProviderException In case an unexpected error aoccurred 
during token generation.
+@@ -83,7 +86,7 @@
+     String generateToken(SortedMap<String, String> attributes) throws 
TokenProviderException;
+ 
+     /**
+-     * Verifies if the token is valid. If the token is valid, a map of 
attributes is returned which 
++     * Verifies if the token is valid. If the token is valid, a map of 
attributes is returned which
+      * are included in the token. This is the same list as provided when the 
token was generated, but
+      * with additional nonce and timestamp attributes. If the token is 
invalid, a InvalidTokenException
+      * is thrown.
+@@ -99,11 +102,4 @@
+      * @param encryptedToken the token to invalidate.
+      */
+     void invalidateToken(String encryptedToken);
+-    
+-    /**
+-     * Returns the request token associated with the specified request or 
null of none is associated.
+-     * @param request The request to get the token from
+-     * @return the request token associated with the specified request
+-     */
+-    String getTokenFromRequest(HttpServletRequest request);
+ }
+Index: amdatu-authorization/login-service/pom.xml
+===================================================================
+--- amdatu-authorization/login-service/pom.xml (revision 564)
++++ amdatu-authorization/login-service/pom.xml (working copy)
+@@ -12,15 +12,22 @@
+   <packaging>bundle</packaging>
+   <name>Amdatu Authorization - Login service</name>
+   <description>Provides a service for login and logout 
functionality</description>
+-  
+-  <dependencies>  
++
++  <dependencies>
+     <dependency>
+       <groupId>org.amdatu.web</groupId>
+       <artifactId>httpcontext</artifactId>
+       <scope>provided</scope>
+       <type>bundle</type>
+-    </dependency>   
++    </dependency>
+     <dependency>
++      <groupId>org.amdatu.authentication</groupId>
++      <artifactId>contextmanager</artifactId>
++      <version>${platform.version}</version>
++      <scope>provided</scope>
++      <type>bundle</type>
++    </dependency>
++    <dependency>
+       <groupId>org.amdatu.web.rest</groupId>
+       <artifactId>jaxrs</artifactId>
+       <version>${platform.version}</version>
+@@ -64,6 +71,6 @@
+       </plugin>
+ 
+     </plugins>
+-    
+-  </build> 
++
++  </build>
+ </project>
+Index: 
amdatu-authorization/login-service/src/main/java/org/amdatu/authorization/login/service/LoginContextProvider.java
+===================================================================
+--- 
amdatu-authorization/login-service/src/main/java/org/amdatu/authorization/login/service/LoginContextProvider.java
  (revision 0)
++++ 
amdatu-authorization/login-service/src/main/java/org/amdatu/authorization/login/service/LoginContextProvider.java
  (revision 0)
+@@ -0,0 +1,39 @@
++/*
++    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.authorization.login.service;
++
++import org.amdatu.authentication.contextmanager.ContextProvider;
++
++public interface LoginContextProvider extends ContextProvider {
++    /**
++     * Id of the login context provider.
++     */
++    String ID = "org.amdatu.authorization.login.contextprovider";
++
++    /**
++     * Name of the username property in this context. The username represents 
a user authenticated
++     * against a User in UserAdmin.
++     */
++    String USERNAME = "username";
++
++    /**
++     * Name of the user token property in this context. Each user that is 
logged in in Amdatu will
++     * be associated with this token. The token contains an arbitrary map of 
information, decryptable
++     * from the token. As such, the token holds non-persistent state 
information.
++     */
++    String USER_TOKEN = "token";
++}
+Index: 
amdatu-authorization/login-service/src/main/java/org/amdatu/authorization/login/service/LoginService.java
+===================================================================
+--- 
amdatu-authorization/login-service/src/main/java/org/amdatu/authorization/login/service/LoginService.java
  (revision 564)
++++ 
amdatu-authorization/login-service/src/main/java/org/amdatu/authorization/login/service/LoginService.java
  (working copy)
+@@ -16,12 +16,16 @@
+  */
+ package org.amdatu.authorization.login.service;
+ 
+-import javax.ws.rs.core.Response;
+-import javax.servlet.http.HttpServletRequest;
++import java.util.SortedMap;
+ 
++import javax.security.auth.login.LoginException;
+ 
+ /**
+- * This interface defines the authorization service.
++ * The login service is responsible for verifying user credentials against 
those stored in UserAdmin.
++ * It provides login and logout methods. Upon successful login, the 
information about the fact that
++ * this user logged in successfully is written to the login context. Upon 
logout, this information
++ * is removed from the context.
++ * 
+  * @author ivol
+  */
+ public interface LoginService {
+@@ -34,40 +38,37 @@
+      * Key under which the password is stored in the credentials of the User.
+      */
+     String PASSWORD_CREDENTIAL_KEY = "password";
+-    
++
+     /**
+-     * NB: Do NOT use this method since it will be removed from future 
versions. For more information,
+-     * see http://jira.amdatu.org/jira/browse/AMDATU-166.
+-     * 
+-     * Shows the login status of the user.
+-     * @param request The current httprequest
+-     * @return Response the username of the current user is logged in or an
+-     * empty string if the user is not logged in.
++     * Verifies use credentials against those stored in UserAdmin. If the 
logion fails for any reason,
++     * a LoginException is thrown. If the login was successful, this 
information is added to the login
++     * context.
++     * @param username Username of the user to login
++     * @param password Password credential of this user
++     * @throws LoginException in case login failed for any reason. This may 
be an invalid username, invalid
++     * password or any other internal error
+      */
+-    @Deprecated
+-    public Response getLoginStatus(HttpServletRequest request);
+-    
++    void login(String username, String password) throws LoginException;
++
+     /**
+-     * NB: Do NOT use this method since it will be removed from future 
versions. For more information,
+-     * see http://jira.amdatu.org/jira/browse/AMDATU-166.
+-     * 
+-     * Enables the user login with a username and password.
+-     * @param username The username 
+-     * @param password The plain text password
+-     * @param request The current httprequest
+-     * @return Response The result of the login.
++     * Verifies use credentials against those stored in UserAdmin. If the 
logion fails for any reason,
++     * a LoginException is thrown. If the login was successful, this 
information is added to the login
++     * context. Additional login attributes can be passed, which will be 
added to the generated
++     * Amdatu token in the login context. This information will this be 
available in the login context
++     * by subsequent invocations accessing the login context.
++     * @param username Username of the user to login
++     * @param password Password credential of this user
++     * @param attributes Sorted map of additional attributes which will be 
added to the generated Amdatu
++     * token, and therefore will also be available in the login context (as 
the Amdatu token is stored in
++     * the login context).
++     * @throws LoginException in case login failed for any reason. This may 
be an invalid username, invalid
++     * password or any other internal error
+      */
+-    @Deprecated
+-    public Response login(String username, String password, 
HttpServletRequest request);
++    void login(String username, String password, SortedMap<String, String> 
attributes) throws LoginException;
+ 
+     /**
+-     * NB: Do NOT use this method since it will be removed from future 
versions. For more information,
+-     * see http://jira.amdatu.org/jira/browse/AMDATU-166.
+-     * 
+-     * Enables the user logout.
+-     * @param request The current httprequest
+-     * @return Response The result of the logout.
++     * Logs out the user in the current login context, if a current (logged 
in) user is available in the
++     * current login context. If no current user is available in the current 
context this method does nothing.
+      */
+-    @Deprecated
+-      public Response logout(HttpServletRequest request);
++    void logout();
+ }
+\ No newline at end of file
+Index: 
amdatu-authorization/login-service/src/main/java/org/amdatu/authorization/login/service/osgi/Activator.java
+===================================================================
+--- 
amdatu-authorization/login-service/src/main/java/org/amdatu/authorization/login/service/osgi/Activator.java
        (revision 564)
++++ 
amdatu-authorization/login-service/src/main/java/org/amdatu/authorization/login/service/osgi/Activator.java
        (working copy)
+@@ -16,11 +16,15 @@
+  */
+ package org.amdatu.authorization.login.service.osgi;
+ 
++import org.amdatu.authentication.contextmanager.ContextManager;
+ import org.amdatu.authentication.tokenprovider.TokenProvider;
++import org.amdatu.authorization.login.service.LoginContextProvider;
+ import org.amdatu.authorization.login.service.LoginService;
++import org.amdatu.authorization.login.service.service.LoginRESTServiceImpl;
+ import org.amdatu.authorization.login.service.service.LoginServiceImpl;
+ import org.amdatu.libraries.utilities.osgi.ServiceDependentActivator;
+ import org.amdatu.web.httpcontext.HttpContextServiceFactory;
++import org.amdatu.web.httpcontext.ResourceProvider;
+ import org.amdatu.web.rest.jaxrs.JaxRsSpi;
+ import org.apache.felix.dm.DependencyManager;
+ import org.osgi.framework.BundleContext;
+@@ -43,21 +47,29 @@
+ 
+     @Override
+     public void initWithDependencies(BundleContext context, DependencyManager 
manager) throws Exception {
+-        // Create and register the authorization service.
++        // Create and register the login service.
+         manager.add(
+-                createComponent()
+-                .setInterface(LoginService.class.getName(), null)
+-                .setImplementation(LoginServiceImpl.class)
+-                
.add(createServiceDependency().setService(HttpContextServiceFactory.class).setRequired(true))
+-                
.add(createServiceDependency().setService(TokenProvider.class).setRequired(true))
+-                
.add(createServiceDependency().setService(LogService.class).setRequired(true))
+-                
.add(createServiceDependency().setService(UserAdmin.class).setRequired(true)));
+-        
+-        
++            createComponent()
++            .setInterface(LoginService.class.getName(), null)
++            .setImplementation(LoginServiceImpl.class)
++            
.add(createServiceDependency().setService(TokenProvider.class).setRequired(true))
++            
.add(createServiceDependency().setService(LogService.class).setRequired(true))
++            
.add(createServiceDependency().setService(UserAdmin.class).setRequired(true)));
++
++        // Create and register the login REST API.
++        manager.add(
++            createComponent()
++            .setInterface(ResourceProvider.class.getName(), null)
++            .setImplementation(LoginRESTServiceImpl.class)
++            
.add(createServiceDependency().setService(HttpContextServiceFactory.class).setRequired(true))
++            
.add(createServiceDependency().setService(LoginService.class).setRequired(true))
++            
.add(createServiceDependency().setService(LoginContextProvider.class).setRequired(true))
++            
.add(createServiceDependency().setService(ContextManager.class).setRequired(true))
++            
.add(createServiceDependency().setService(LogService.class).setRequired(true)));
+     }
+ 
+     @Override
+     public void destroy(BundleContext bundleContext, DependencyManager 
dependencyManager) throws Exception {
+     }
+-    
++
+ }
+Index: 
amdatu-authorization/login-service/src/main/java/org/amdatu/authorization/login/service/service/LoginContextProviderImpl.java
+===================================================================
+--- 
amdatu-authorization/login-service/src/main/java/org/amdatu/authorization/login/service/service/LoginContextProviderImpl.java
      (revision 0)
++++ 
amdatu-authorization/login-service/src/main/java/org/amdatu/authorization/login/service/service/LoginContextProviderImpl.java
      (revision 0)
+@@ -0,0 +1,132 @@
++/*
++    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.authorization.login.service.service;
++
++import java.util.HashMap;
++import java.util.Map;
++import java.util.SortedMap;
++
++import javax.servlet.http.Cookie;
++import javax.servlet.http.HttpServletRequest;
++
++import org.amdatu.authentication.contextmanager.ContextProvider;
++import org.amdatu.authentication.tokenprovider.InvalidTokenException;
++import org.amdatu.authentication.tokenprovider.TokenProvider;
++import org.amdatu.authentication.tokenprovider.TokenProviderException;
++import org.amdatu.authorization.login.service.LoginContextProvider;
++import org.osgi.service.log.LogService;
++
++/**
++ * Implements a login context provider. The login context provider provides 
login related context information;
++ * the username of the user currently logged in and the Amdatu token 
distributed to that user to authenticate itself
++ * in subsequent requests.
++ * 
++ * @author ivol
++ */
++public class LoginContextProviderImpl implements LoginContextProvider {
++    // Login context information is bound to a ThreadLocal variable.
++    private static ThreadLocal<Map<String, String>> m_properties = new 
ThreadLocal<Map<String, String>>();
++
++    // Service dependencies injected by the dependency manager
++    private volatile TokenProvider m_tokenProvider;
++    private volatile LogService m_logService;
++
++    public String getId() {
++        return LoginContextProvider.ID;
++    }
++
++    public String getValue(String propertyName) {
++        if (m_properties.get()  != null) {
++            return m_properties.get().get(propertyName);
++        } else {
++            return null;
++        }
++    }
++
++    private void setValue(String propertyName, String value) {
++        if (m_properties.get() == null) {
++            m_properties.set(new HashMap<String, String>());
++        }
++        if (value != null) {
++            m_properties.get().put(propertyName, value);
++        } else if ( m_properties.get().containsKey(propertyName)){
++            m_properties.get().remove(propertyName);
++        }
++    }
++
++    void setUsername(String username) {
++        setValue(LoginContextProvider.USERNAME, username);
++    }
++
++    void setToken(String token) {
++        setValue(LoginContextProvider.USER_TOKEN, token);
++    }
++
++    public void reset() {
++        m_properties = new ThreadLocal<Map<String, String>>();
++    }
++
++    // Resolve a map of arbitrary context resolve properties to this context.
++    public void resolve(Map<String, Object> properties) {
++        // Check if the HTTP request is one of the context resolver 
properties, in which case we can resolve the
++        // login context from the amdatu token (if available).
++        if (properties.containsKey(ContextProvider.PROPERTY_HTTP_REQUEST)) {
++            HttpServletRequest request = (HttpServletRequest) 
properties.get(ContextProvider.PROPERTY_HTTP_REQUEST);
++            String amdatuToken = getAmdatuTokenFromRequest(request);
++            if (amdatuToken != null) {
++                setToken(amdatuToken);
++                try {
++                    SortedMap<String, String> tokenProperties = 
m_tokenProvider.verifyToken(amdatuToken);
++                    if (tokenProperties != null) {
++                        if 
(tokenProperties.containsKey(TokenProvider.USERNAME)) {
++                            
setUsername(tokenProperties.get(TokenProvider.USERNAME));
++                        }
++                    }
++                }
++                catch (TokenProviderException e) {
++                    m_logService.log(LogService.LOG_ERROR, "An error occured 
while verifying token '" + amdatuToken + "'", e);
++                }
++                catch (InvalidTokenException e) {
++                    // Invalid token, log nothing
++                }
++            }
++        }
++    }
++
++    private String getAmdatuTokenFromRequest(HttpServletRequest request) {
++        // Use case 1: The token is send along in a cookie with the request. 
The cookie is send
++        // automatically when a request is send directly from the end users 
browser to the Amdatu server.
++        if (request.getCookies() != null) {
++            for (Cookie cookie : request.getCookies()) {
++                if (TokenProvider.TOKEN_COOKIE_NAME.equals(cookie.getName())) 
{
++                    return cookie.getValue();
++                }
++            }
++        }
++
++        // Use case 2: When requests are not send from a browser (for example 
calls to gadgets.ui.makeRequest
++        // proxied via an openSocial container) the token can be send in the 
Authorization header (like Basic
++        // and Digest HTTP authentication).
++        String authHeader = request.getHeader("Authorization");
++        if (authHeader != null && !authHeader.isEmpty()) {
++            if 
(authHeader.startsWith(TokenProvider.TOKEN_AUTHORIZATION_HEADER + " ")) {
++                return authHeader.substring(authHeader.indexOf(" ") + 1);
++            }
++        }
++        return null;
++    }
++}
+Index: 
amdatu-authorization/login-service/src/main/java/org/amdatu/authorization/login/service/service/LoginRESTServiceImpl.java
+===================================================================
+--- 
amdatu-authorization/login-service/src/main/java/org/amdatu/authorization/login/service/service/LoginRESTServiceImpl.java
  (revision 548)
++++ 
amdatu-authorization/login-service/src/main/java/org/amdatu/authorization/login/service/service/LoginRESTServiceImpl.java
  (working copy)
+@@ -17,10 +17,10 @@
+ package org.amdatu.authorization.login.service.service;
+ 
+ import java.net.URL;
+-import java.util.Map;
+ import java.util.SortedMap;
+ import java.util.TreeMap;
+ 
++import javax.security.auth.login.LoginException;
+ import javax.servlet.http.HttpServletRequest;
+ import javax.servlet.http.HttpServletResponse;
+ import javax.ws.rs.Consumes;
+@@ -37,9 +37,8 @@
+ import javax.ws.rs.core.Response;
+ import javax.ws.rs.core.Response.ResponseBuilder;
+ 
+-import org.amdatu.authentication.tokenprovider.InvalidTokenException;
+ import org.amdatu.authentication.tokenprovider.TokenProvider;
+-import org.amdatu.authentication.tokenprovider.TokenProviderException;
++import org.amdatu.authorization.login.service.LoginContextProvider;
+ import org.amdatu.authorization.login.service.LoginService;
+ import org.amdatu.authorization.login.service.osgi.Activator;
+ import org.amdatu.web.httpcontext.HttpContextServiceFactory;
+@@ -49,10 +48,6 @@
+ import org.json.JSONObject;
+ import org.osgi.framework.BundleContext;
+ import org.osgi.service.log.LogService;
+-import org.osgi.service.useradmin.Group;
+-import org.osgi.service.useradmin.Role;
+-import org.osgi.service.useradmin.User;
+-import org.osgi.service.useradmin.UserAdmin;
+ 
+ /**
+  * This service is responsible for authorization handling, based on the 
UserAdmin OSGi service.
+@@ -60,18 +55,13 @@
+  * @author ivol
+  */
+ @Path("authorization")
+-public class LoginServiceImpl implements ResourceProvider, LoginService {
+-    // Default Administrator user credentials
+-    private static final String DEFAULT_USERNAME = "Administrator";
+-    private static final String DEFAULT_PASSWORD = "Administrator";
+-    private static final String DEFAULT_ADMIN_GROUP = "Administrators";
+-
++public class LoginRESTServiceImpl implements ResourceProvider {
+     // Service dependencies, injected by the Felix dependency manager
+     private volatile LogService m_logService;
+     private volatile BundleContext m_bundleContext;
+     private volatile HttpContextServiceFactory m_httpContextServiceFactory;
+-    private volatile UserAdmin m_userAdmin;
+-    private volatile TokenProvider m_tokenProvider;
++    private volatile LoginService m_loginService;
++    private volatile LoginContextProvider m_loginContext;
+ 
+     // The private HTTP context service for this bundle
+     private Component m_httpContextComponent;
+@@ -90,26 +80,11 @@
+         // Create our own http context service which registers static 
resources and JSPs automatically
+         m_httpContextComponent = 
m_httpContextServiceFactory.create(m_bundleContext, this);
+ 
++        // Register our LoginContext provider
++
+         m_logService.log(LogService.LOG_INFO, getClass().getName() + " 
service initialized");
+     }
+ 
+-    @SuppressWarnings("unchecked")
+-    public void start() {
+-        // If we don't have a user named 'Administrator', we create one now.
+-        if (m_userAdmin.getRole(DEFAULT_USERNAME) == null) {
+-            User adminUser = (User) m_userAdmin.createRole(DEFAULT_USERNAME, 
Role.USER);
+-            if (adminUser != null) {
+-                adminUser.getCredentials().put(PASSWORD_CREDENTIAL_KEY, 
DEFAULT_PASSWORD);
+-                adminUser.getProperties().put(USER_NAME_CREDENTIAL_KEY, 
DEFAULT_USERNAME);
+-                Group adminGroup = (Group) 
m_userAdmin.createRole(DEFAULT_ADMIN_GROUP, Role.GROUP);
+-                adminGroup.addMember(adminUser);
+-            }
+-            else {
+-                m_logService.log(LogService.LOG_ERROR, "Failed to create 
initial user " + DEFAULT_USERNAME);
+-            }
+-        }
+-    }
+-
+     // The destroy() method is automatically invoked by the Felix dependency 
manager
+     public void destroy() {
+         // Stop the HTTP context service we created ourselves
+@@ -135,28 +110,18 @@
+     @Path("status")
+     @Produces( { MediaType.APPLICATION_JSON })
+     public Response getLoginStatus(@Context final HttpServletRequest request) 
{
+-        // TODO: here we have the authorization of this user, but to which 
context should we bind
+-        // it? And what about oAuth? For now we just bind it to the http 
session and use the
+-        // session info in the container. Note that we use our own http 
session implementation
+-        // because of issue AMDATU-67.
+         JSONObject jsonObject = new JSONObject();
+         try {
+-            String userName = getUserName(request);
++            String userName = 
m_loginContext.getValue(LoginContextProvider.USERNAME);
+             if (userName != null) {
+                 jsonObject.append("username", userName);
+                 return Response.ok(jsonObject.toString(), 
MediaType.APPLICATION_JSON_TYPE).cacheControl(m_cacheControl)
+-                    .build();
++                .build();
+             }
+         }
+         catch (JSONException e) {
+             m_logService.log(LogService.LOG_ERROR, "Could not retrieve 
current login status", e);
+         }
+-        catch (TokenProviderException e) {
+-         // If the token is invalid, the user is not logged in anymore, 
ignore this error
+-        }
+-        catch (InvalidTokenException e) {
+-            // If the token is invalid, the user is not logged in anymore, 
ignore this error
+-        }
+         return Response.ok(jsonObject.toString(), 
MediaType.APPLICATION_JSON_TYPE).cacheControl(m_cacheControl).build();
+     }
+ 
+@@ -175,28 +140,22 @@
+         JSONObject jsonObject = new JSONObject();
+         NewCookie cookie = null;
+         try {
+-            Role userRole = m_userAdmin.getRole(username);
+-            if (userRole != null && userRole.getType() == Role.USER) {
+-                User user = (User) userRole;
+-                if (user.hasCredential(PASSWORD_CREDENTIAL_KEY, password)) {
+-                    // Now generate a token for this user and write it to a 
Set-Cookie header
+-                    String token = generateToken(request, user);
+-                    cookie = new NewCookie(TokenProvider.TOKEN_COOKIE_NAME, 
token, "/", null, "Amdatu session", -1, false);
++            try {
++                // Login with specified username and password. If login 
fails, an exception is thrown.
++                // Add the IP address of this request to the login context
++                SortedMap<String, String> attributes = new TreeMap<String, 
String>();
++                attributes.put("ip", request.getRemoteAddr());
++                m_loginService.login(username, password, attributes);
+ 
+-                    m_logService.log(LogService.LOG_INFO, "User '" + username 
+ "' logged in successfully");
+-                    jsonObject.append("result", "ok");
+-                    jsonObject.append("username", username);
+-                    jsonObject.append("msg", "User '" + username + "' logged 
in successfully");
+-
+-                }
+-                else {
+-                    m_logService.log(LogService.LOG_INFO, "Incorrect password 
provided for user '" + username + "'");
+-                    jsonObject.append("result", "failed");
+-                    jsonObject.append("msg", "Password is incorrect");
+-                }
++                // Now write the login token to a Set-Cookie header
++                String token = 
m_loginContext.getValue(LoginContextProvider.USER_TOKEN);
++                cookie = new NewCookie(TokenProvider.TOKEN_COOKIE_NAME, 
token, "/", null, "Amdatu session", -1, false);
++                jsonObject.append("result", "ok");
++                jsonObject.append("username", username);
++                jsonObject.append("msg", "User '" + username + "' logged in 
successfully");
+             }
+-            else {
+-                m_logService.log(LogService.LOG_INFO, "Username '" + username 
+ "' unknown");
++            catch (LoginException e) {
++                m_logService.log(LogService.LOG_INFO, "Username '" + username 
+ "' unknown and/or password invalid");
+                 jsonObject.append("result", "failed");
+                 jsonObject.append("msg", "Username is unknown");
+             }
+@@ -205,11 +164,6 @@
+             m_logService.log(LogService.LOG_ERROR, "Could not retrieve 
current login status", e);
+             throw new WebApplicationException(e, 
HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
+         }
+-        catch (TokenProviderException e) {
+-            m_logService.log(LogService.LOG_ERROR, "Could not retrieve 
current login status", e);
+-            throw new WebApplicationException(e, 
HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
+-        }
+-
+         ResponseBuilder builder = Response.ok(jsonObject.toString(), 
MediaType.APPLICATION_JSON_TYPE);
+         builder.cacheControl(m_cacheControl);
+         if (cookie != null) {
+@@ -227,27 +181,14 @@
+     @Path("logout")
+     @Produces( { MediaType.APPLICATION_JSON })
+     public Response logout(@Context final HttpServletRequest request) {
+-        // TODO: here we have the authorization of this user, but to which 
context should we bind
+-        // it? And what about oAuth? For now we just bind it to the http 
session and use the
+-        // session info in the container. Note that we use our own http 
session implementation
+-        // because of issue AMDATU-67.
+         JSONObject jsonObject = new JSONObject();
+-        String userName = null;
+         try {
+-            userName = getUserName(request);
+-            invalidateToken(request);
+-            m_logService.log(LogService.LOG_INFO, "User '" + userName + "' 
logged out successfully");
++            m_loginService.logout();
+             jsonObject.append("result", "ok");
+         }
+         catch (JSONException e) {
+             m_logService.log(LogService.LOG_ERROR, "Could not retrieve 
current login status", e);
+         }
+-        catch (TokenProviderException e) {
+-            m_logService.log(LogService.LOG_INFO, "User '" + userName + "' 
could not be logged out");
+-        }
+-        catch (InvalidTokenException e) {
+-            m_logService.log(LogService.LOG_INFO, "User '" + userName + "' 
not logged out, token was already invalid");
+-        }
+         return Response.ok(jsonObject.toString(), 
MediaType.APPLICATION_JSON_TYPE).cacheControl(m_cacheControl).build();
+     }
+ 
+@@ -258,28 +199,4 @@
+     public String getResourceId() {
+         return Activator.RESOURCE_ID;
+     }
+-
+-    private String generateToken(HttpServletRequest request, User user) 
throws TokenProviderException {
+-        SortedMap<String, String> attributes = new TreeMap<String, String>();
+-        attributes.put("ip", request.getRemoteAddr());
+-        attributes.put(TokenProvider.USERNAME, user.getName());
+-        return m_tokenProvider.generateToken(attributes);
+-    }
+-
+-    private String getUserName(HttpServletRequest request) throws 
TokenProviderException, InvalidTokenException {
+-        String token = m_tokenProvider.getTokenFromRequest(request);
+-        if (token != null) {
+-            // Now decrypt to get the username and signature
+-            Map<String, String> attributes = 
m_tokenProvider.verifyToken(token);
+-            if (attributes != null) {
+-                return attributes.get(TokenProvider.USERNAME);
+-            }
+-        }
+-
+-        return null;
+-    }
+-
+-    private void invalidateToken(HttpServletRequest request) {
+-        
m_tokenProvider.invalidateToken(m_tokenProvider.getTokenFromRequest(request));
+-    }
+ }
+Index: 
amdatu-authorization/login-service/src/main/java/org/amdatu/authorization/login/service/service/LoginServiceImpl.java
+===================================================================
+--- 
amdatu-authorization/login-service/src/main/java/org/amdatu/authorization/login/service/service/LoginServiceImpl.java
      (revision 564)
++++ 
amdatu-authorization/login-service/src/main/java/org/amdatu/authorization/login/service/service/LoginServiceImpl.java
      (working copy)
+@@ -16,51 +16,24 @@
+  */
+ package org.amdatu.authorization.login.service.service;
+ 
+-import java.net.URL;
+-import java.util.Map;
+ import java.util.SortedMap;
+ import java.util.TreeMap;
+ 
+-import javax.servlet.http.HttpServletRequest;
+-import javax.servlet.http.HttpServletResponse;
+-import javax.ws.rs.Consumes;
+-import javax.ws.rs.FormParam;
+-import javax.ws.rs.GET;
+-import javax.ws.rs.POST;
+-import javax.ws.rs.Path;
+-import javax.ws.rs.Produces;
+-import javax.ws.rs.WebApplicationException;
+-import javax.ws.rs.core.CacheControl;
+-import javax.ws.rs.core.Context;
+-import javax.ws.rs.core.MediaType;
+-import javax.ws.rs.core.NewCookie;
+-import javax.ws.rs.core.Response;
+-import javax.ws.rs.core.Response.ResponseBuilder;
++import javax.security.auth.login.LoginException;
+ 
+-import org.amdatu.authentication.tokenprovider.InvalidTokenException;
++import org.amdatu.authentication.contextmanager.ContextProvider;
+ import org.amdatu.authentication.tokenprovider.TokenProvider;
+ import org.amdatu.authentication.tokenprovider.TokenProviderException;
++import org.amdatu.authorization.login.service.LoginContextProvider;
+ import org.amdatu.authorization.login.service.LoginService;
+-import org.amdatu.authorization.login.service.osgi.Activator;
+-import org.amdatu.web.httpcontext.HttpContextServiceFactory;
+-import org.amdatu.web.httpcontext.ResourceProvider;
+-import org.apache.felix.dm.Component;
+-import org.json.JSONException;
+-import org.json.JSONObject;
+-import org.osgi.framework.BundleContext;
++import org.apache.felix.dm.DependencyManager;
+ import org.osgi.service.log.LogService;
+ import org.osgi.service.useradmin.Group;
+ import org.osgi.service.useradmin.Role;
+ import org.osgi.service.useradmin.User;
+ import org.osgi.service.useradmin.UserAdmin;
+ 
+-/**
+- * This service is responsible for authorization handling, based on the 
UserAdmin OSGi service.
+- * 
+- * @author ivol
+- */
+- at Path("authorization")
+-public class LoginServiceImpl implements ResourceProvider, LoginService {
++public class LoginServiceImpl implements LoginService {
+     // Default Administrator user credentials
+     private static final String DEFAULT_USERNAME = "Administrator";
+     private static final String DEFAULT_PASSWORD = "Administrator";
+@@ -68,27 +41,23 @@
+ 
+     // Service dependencies, injected by the Felix dependency manager
+     private volatile LogService m_logService;
+-    private volatile BundleContext m_bundleContext;
+-    private volatile HttpContextServiceFactory m_httpContextServiceFactory;
+     private volatile UserAdmin m_userAdmin;
+     private volatile TokenProvider m_tokenProvider;
++    private volatile DependencyManager m_dependencyManager;
+ 
+-    // The private HTTP context service for this bundle
+-    private Component m_httpContextComponent;
++    private LoginContextProviderImpl m_loginContext = new 
LoginContextProviderImpl();
+ 
+-    // Disable HTTP caching in this REST interface
+-    private static CacheControl m_cacheControl;
+-    static {
+-        m_cacheControl = new CacheControl();
+-        m_cacheControl.setNoCache(true);
+-    }
+-
+     /**
+      * The init() method is invoked by the Felix dependency manager.
+      */
+     public void init() {
+-        // Create our own http context service which registers static 
resources and JSPs automatically
+-        m_httpContextComponent = 
m_httpContextServiceFactory.create(m_bundleContext, this);
++        // Register our LoginContext provider
++        m_dependencyManager.add(
++            m_dependencyManager.createComponent()
++            .setImplementation(m_loginContext)
++            .setInterface(new String[] {ContextProvider.class.getName(), 
LoginContextProvider.class.getName()}, null)
++            
.add(m_dependencyManager.createServiceDependency().setService(TokenProvider.class).setRequired(true))
++            
.add(m_dependencyManager.createServiceDependency().setService(LogService.class).setRequired(true)));
+ 
+         m_logService.log(LogService.LOG_INFO, getClass().getName() + " 
service initialized");
+     }
+@@ -110,176 +79,57 @@
+         }
+     }
+ 
+-    // The destroy() method is automatically invoked by the Felix dependency 
manager
+-    public void destroy() {
+-        // Stop the HTTP context service we created ourselves
+-        m_httpContextComponent.stop();
++    public void login(String username, String password) throws LoginException 
{
++        login(username, password, null);
+     }
+ 
+-    /**
+-     * This method can be used to check the availability of the Login Service.
+-     * 
+-     * @return The text "Login service online"
+-     */
+-    @GET
+-    @Produces( { MediaType.TEXT_PLAIN })
+-    public String status() {
+-        return "Login service online";
+-    }
+-
+-    /**
+-     * This REST service returns the current login status. Returns the 
username of the current user is logged in or an
+-     * empty string if the user is not logged in.
+-     */
+-    @GET
+-    @Path("status")
+-    @Produces( { MediaType.APPLICATION_JSON })
+-    public Response getLoginStatus(@Context final HttpServletRequest request) 
{
+-        // TODO: here we have the authorization of this user, but to which 
context should we bind
+-        // it? And what about oAuth? For now we just bind it to the http 
session and use the
+-        // session info in the container. Note that we use our own http 
session implementation
+-        // because of issue AMDATU-67.
+-        JSONObject jsonObject = new JSONObject();
++    public void login(String username, String password, SortedMap<String, 
String> attributes) throws LoginException {
+         try {
+-            String userName = getUserName(request);
+-            if (userName != null) {
+-                jsonObject.append("username", userName);
+-                return Response.ok(jsonObject.toString(), 
MediaType.APPLICATION_JSON_TYPE).cacheControl(m_cacheControl)
+-                    .build();
+-            }
+-        }
+-        catch (JSONException e) {
+-            m_logService.log(LogService.LOG_ERROR, "Could not retrieve 
current login status", e);
+-        }
+-        catch (TokenProviderException e) {
+-         // If the token is invalid, the user is not logged in anymore, 
ignore this error
+-        }
+-        catch (InvalidTokenException e) {
+-            // If the token is invalid, the user is not logged in anymore, 
ignore this error
+-        }
+-        return Response.ok(jsonObject.toString(), 
MediaType.APPLICATION_JSON_TYPE).cacheControl(m_cacheControl).build();
+-    }
+-
+-    /**
+-     * REST based login service with username/password.
+-     */
+-    @POST
+-    @Path("login")
+-    @Consumes("application/x-www-form-urlencoded")
+-    @Produces( { MediaType.APPLICATION_JSON })
+-    public Response login(@FormParam("username") final String username, 
@FormParam("password") final String password,
+-        @Context final HttpServletRequest request) {
+-        m_logService.log(LogService.LOG_INFO, "Login requested for user: " + 
username);
+-
+-        // First retrieve the user with this username
+-        JSONObject jsonObject = new JSONObject();
+-        NewCookie cookie = null;
+-        try {
++            // First validate username and password
+             Role userRole = m_userAdmin.getRole(username);
+             if (userRole != null && userRole.getType() == Role.USER) {
+                 User user = (User) userRole;
+-                if (user.hasCredential(PASSWORD_CREDENTIAL_KEY, password)) {
+-                    // Now generate a token for this user and write it to a 
Set-Cookie header
+-                    String token = generateToken(request, user);
+-                    cookie = new NewCookie(TokenProvider.TOKEN_COOKIE_NAME, 
token, "/", null, "Amdatu session", -1, false);
++                if (user.hasCredential(LoginService.PASSWORD_CREDENTIAL_KEY, 
password)) {
++                    // Now generate a token for this user
++                    String token = generateToken(user, attributes);
+ 
++                    // Finally, write the info to the current login context
++                    m_loginContext.setUsername(username);
++                    m_loginContext.setToken(token);
+                     m_logService.log(LogService.LOG_INFO, "User '" + username 
+ "' logged in successfully");
+-                    jsonObject.append("result", "ok");
+-                    jsonObject.append("username", username);
+-                    jsonObject.append("msg", "User '" + username + "' logged 
in successfully");
+-
++                    return;
+                 }
+-                else {
+-                    m_logService.log(LogService.LOG_INFO, "Incorrect password 
provided for user '" + username + "'");
+-                    jsonObject.append("result", "failed");
+-                    jsonObject.append("msg", "Password is incorrect");
+-                }
+             }
+-            else {
+-                m_logService.log(LogService.LOG_INFO, "Username '" + username 
+ "' unknown");
+-                jsonObject.append("result", "failed");
+-                jsonObject.append("msg", "Username is unknown");
+-            }
++            throw new LoginException("Username and/or password invalid");
++        } catch (TokenProviderException e) {
++            throw new LoginException(e.toString());
+         }
+-        catch (JSONException e) {
+-            m_logService.log(LogService.LOG_ERROR, "Could not retrieve 
current login status", e);
+-            throw new WebApplicationException(e, 
HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
+-        }
+-        catch (TokenProviderException e) {
+-            m_logService.log(LogService.LOG_ERROR, "Could not retrieve 
current login status", e);
+-            throw new WebApplicationException(e, 
HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
+-        }
+-
+-        ResponseBuilder builder = Response.ok(jsonObject.toString(), 
MediaType.APPLICATION_JSON_TYPE);
+-        builder.cacheControl(m_cacheControl);
+-        if (cookie != null) {
+-            builder.cookie(cookie);
+-        }
+-        return builder.build();
+     }
+ 
+-    /**
+-     * REST based logout service with username/password.
+-     * 
+-     * @return The result of the SPARQL query.
+-     */
+-    @POST
+-    @Path("logout")
+-    @Produces( { MediaType.APPLICATION_JSON })
+-    public Response logout(@Context final HttpServletRequest request) {
+-        // TODO: here we have the authorization of this user, but to which 
context should we bind
+-        // it? And what about oAuth? For now we just bind it to the http 
session and use the
+-        // session info in the container. Note that we use our own http 
session implementation
+-        // because of issue AMDATU-67.
+-        JSONObject jsonObject = new JSONObject();
+-        String userName = null;
+-        try {
+-            userName = getUserName(request);
+-            invalidateToken(request);
++    public void logout() {
++        String userName = 
m_loginContext.getValue(LoginContextProvider.USERNAME);
++        if (userName != null) {
++            invalidateToken();
++            (m_loginContext).setUsername(null);
+             m_logService.log(LogService.LOG_INFO, "User '" + userName + "' 
logged out successfully");
+-            jsonObject.append("result", "ok");
++        } else {
++            m_logService.log(LogService.LOG_INFO, "No user was logged in in 
the current context, unable to logout");
+         }
+-        catch (JSONException e) {
+-            m_logService.log(LogService.LOG_ERROR, "Could not retrieve 
current login status", e);
+-        }
+-        catch (TokenProviderException e) {
+-            m_logService.log(LogService.LOG_INFO, "User '" + userName + "' 
could not be logged out");
+-        }
+-        catch (InvalidTokenException e) {
+-            m_logService.log(LogService.LOG_INFO, "User '" + userName + "' 
not logged out, token was already invalid");
+-        }
+-        return Response.ok(jsonObject.toString(), 
MediaType.APPLICATION_JSON_TYPE).cacheControl(m_cacheControl).build();
+     }
+ 
+-    public URL getResource(String name) {
+-        return null;
+-    }
+-
+-    public String getResourceId() {
+-        return Activator.RESOURCE_ID;
+-    }
+-
+-    private String generateToken(HttpServletRequest request, User user) 
throws TokenProviderException {
++    private String generateToken(User user, SortedMap<String, String> 
additionAttrs) throws TokenProviderException {
+         SortedMap<String, String> attributes = new TreeMap<String, String>();
+-        attributes.put("ip", request.getRemoteAddr());
+         attributes.put(TokenProvider.USERNAME, user.getName());
+-        return m_tokenProvider.generateToken(attributes);
+-    }
+-
+-    private String getUserName(HttpServletRequest request) throws 
TokenProviderException, InvalidTokenException {
+-        String token = m_tokenProvider.getTokenFromRequest(request);
+-        if (token != null) {
+-            // Now decrypt to get the username and signature
+-            Map<String, String> attributes = 
m_tokenProvider.verifyToken(token);
+-            if (attributes != null) {
+-                return attributes.get(TokenProvider.USERNAME);
++        if (additionAttrs != null) {
++            for (String key : additionAttrs.keySet()) {
++                String value = additionAttrs.get(key);
++                attributes.put(key, value);
+             }
+         }
+-
+-        return null;
++        return m_tokenProvider.generateToken(attributes);
+     }
+ 
+-    private void invalidateToken(HttpServletRequest request) {
+-        
m_tokenProvider.invalidateToken(m_tokenProvider.getTokenFromRequest(request));
++    private void invalidateToken() {
++        
m_tokenProvider.invalidateToken(m_loginContext.getValue(LoginContextProvider.USER_TOKEN));
+     }
+ }
+Index: amdatu-authorization/useradmin-rest/pom.xml
+===================================================================
+--- amdatu-authorization/useradmin-rest/pom.xml        (revision 564)
++++ amdatu-authorization/useradmin-rest/pom.xml        (working copy)
+@@ -12,8 +12,8 @@
+   <packaging>bundle</packaging>
+   <name>Amdatu Authorization - User Admin REST API</name>
+   <description>Provides a REST API on UserAdmin</description>
+-  
+-  <dependencies>  
++
++  <dependencies>
+     <dependency>
+       <groupId>org.amdatu.web</groupId>
+       <artifactId>httpcontext</artifactId>
+@@ -45,8 +45,29 @@
+       <version>${platform.version}</version>
+       <scope>provided</scope>
+     </dependency>
++    <dependency>
++      <groupId>org.amdatu.authentication</groupId>
++      <artifactId>contextmanager</artifactId>
++      <version>${platform.version}</version>
++      <scope>provided</scope>
++      <type>bundle</type>
++    </dependency>
++    <dependency>
++      <groupId>org.amdatu.authorization.login</groupId>
++      <artifactId>service</artifactId>
++      <version>${platform.version}</version>
++      <scope>provided</scope>
++      <type>bundle</type>
++    </dependency>
++    <dependency>
++      <groupId>org.amdatu.core</groupId>
++      <artifactId>tenant</artifactId>
++      <version>${platform.version}</version>
++      <scope>provided</scope>
++      <type>bundle</type>
++    </dependency>
+   </dependencies>
+-  
++
+   <build>
+     <plugins>
+       <plugin>
+@@ -59,7 +80,7 @@
+             <Embed-Dependency>*;scope=compile</Embed-Dependency>
+           </instructions>
+         </configuration>
+-      </plugin>   
+-    </plugins>        
+-  </build> 
++      </plugin>
++    </plugins>
++  </build>
+ </project>
+Index: 
amdatu-authorization/useradmin-rest/src/main/java/org/amdatu/authorization/useradmin/rest/osgi/Activator.java
+===================================================================
+--- 
amdatu-authorization/useradmin-rest/src/main/java/org/amdatu/authorization/useradmin/rest/osgi/Activator.java
      (revision 564)
++++ 
amdatu-authorization/useradmin-rest/src/main/java/org/amdatu/authorization/useradmin/rest/osgi/Activator.java
      (working copy)
+@@ -16,6 +16,7 @@
+  */
+ package org.amdatu.authorization.useradmin.rest.osgi;
+ 
++import org.amdatu.authentication.contextmanager.ContextManager;
+ import org.amdatu.authentication.tokenprovider.TokenProvider;
+ import org.amdatu.authorization.useradmin.rest.service.GroupsResource;
+ import org.amdatu.authorization.useradmin.rest.service.RolesResource;
+@@ -26,7 +27,6 @@
+ import org.apache.felix.dm.DependencyManager;
+ import org.osgi.framework.BundleContext;
+ import org.osgi.service.log.LogService;
+-import org.osgi.service.useradmin.UserAdmin;
+ 
+ /**
+  * This is the activator for the UserAdmin REST API bundle
+@@ -45,25 +45,25 @@
+         manager.add(createComponent()
+             .setInterface(RESTService.class.getName(), null)
+             .setImplementation(UsersResource.class)
++            
.add(createServiceDependency().setService(ContextManager.class).setRequired(true))
+             
.add(createServiceDependency().setService(LogService.class).setRequired(true))
+-            
.add(createServiceDependency().setService(TokenProvider.class).setRequired(true))
+-            
.add(createServiceDependency().setService(UserAdmin.class).setRequired(true))); 
  
++            
.add(createServiceDependency().setService(TokenProvider.class).setRequired(true)));
+ 
+         // Create the groups resource service and register it as REST service
+         manager.add(createComponent()
+             .setInterface(RESTService.class.getName(), null)
+             .setImplementation(GroupsResource.class)
++            
.add(createServiceDependency().setService(ContextManager.class).setRequired(true))
+             
.add(createServiceDependency().setService(LogService.class).setRequired(true))
+-            
.add(createServiceDependency().setService(TokenProvider.class).setRequired(true))
+-            
.add(createServiceDependency().setService(UserAdmin.class).setRequired(true)));
+-        
++            
.add(createServiceDependency().setService(TokenProvider.class).setRequired(true)));
++
+         // Create the groups resource service and register it as REST service
+         manager.add(createComponent()
+             .setInterface(RESTService.class.getName(), null)
+             .setImplementation(RolesResource.class)
++            
.add(createServiceDependency().setService(ContextManager.class).setRequired(true))
+             
.add(createServiceDependency().setService(LogService.class).setRequired(true))
+-            
.add(createServiceDependency().setService(TokenProvider.class).setRequired(true))
+-            
.add(createServiceDependency().setService(UserAdmin.class).setRequired(true))); 
       
++            
.add(createServiceDependency().setService(TokenProvider.class).setRequired(true)));
+     }
+ 
+     @Override
+Index: 
amdatu-authorization/useradmin-rest/src/main/java/org/amdatu/authorization/useradmin/rest/service/GroupsResource.java
+===================================================================
+--- 
amdatu-authorization/useradmin-rest/src/main/java/org/amdatu/authorization/useradmin/rest/service/GroupsResource.java
      (revision 564)
++++ 
amdatu-authorization/useradmin-rest/src/main/java/org/amdatu/authorization/useradmin/rest/service/GroupsResource.java
      (working copy)
+@@ -95,7 +95,7 @@
+         @DefaultValue("1") @QueryParam("startIndex") final int startIndex,
+         @DefaultValue("50") @QueryParam("maxResults") final int maxResults,
+         @Context final HttpServletRequest request) {
+-        if (!isAuthorized(request)) {
++        if (!isAuthorized()) {
+             return Response.status(Response.Status.UNAUTHORIZED).build();
+         }
+         return super.getRoles(filter, sortOrder, startIndex, maxResults, 
Role.GROUP);
+@@ -121,7 +121,7 @@
+     @Path("{name}")
+     @Produces({MediaType.APPLICATION_JSON})
+     public Response getGroup(@PathParam("name") final String name, @Context 
final HttpServletRequest request) {
+-        if (!isAuthorized(request)) {
++        if (!isAuthorized()) {
+             return Response.status(Response.Status.UNAUTHORIZED).build();
+         }
+         return super.getRole(name, Role.GROUP);
+@@ -141,7 +141,7 @@
+     @Path("{name}")
+     @Produces({MediaType.APPLICATION_JSON})
+     public Response createGroup(@PathParam("name") final String name, 
@Context final HttpServletRequest request) {
+-        if (!isAuthorized(request)) {
++        if (!isAuthorized()) {
+             return Response.status(Response.Status.UNAUTHORIZED).build();
+         }
+         return super.createRole(name, Role.GROUP);
+@@ -163,7 +163,7 @@
+     @Produces({MediaType.APPLICATION_JSON})
+     public Response setCredential(@PathParam("name") final String name,
+         @PathParam("key") final String key, @QueryParam("value") final String 
value, @Context final HttpServletRequest request) {
+-        if (!isAuthorized(request)) {
++        if (!isAuthorized()) {
+             return Response.status(Response.Status.UNAUTHORIZED).build();
+         }
+         return setCredential(name, key, value, Role.GROUP);
+@@ -185,7 +185,7 @@
+     @Produces({MediaType.APPLICATION_JSON})
+     public Response setProperty(@PathParam("name") final String name,
+         @PathParam("key") final String key, @QueryParam("value") final String 
value, @Context final HttpServletRequest request) {
+-        if (!isAuthorized(request)) {
++        if (!isAuthorized()) {
+             return Response.status(Response.Status.UNAUTHORIZED).build();
+         }
+         return setProperty(name, key, value, Role.USER);
+@@ -207,7 +207,7 @@
+     @Produces({MediaType.APPLICATION_JSON})
+     public Response addBasicMember(@PathParam("name") final String name,
+         @PathParam("memberName") final String memberName, @Context final 
HttpServletRequest request) {
+-        if (!isAuthorized(request)) {
++        if (!isAuthorized()) {
+             return Response.status(Response.Status.UNAUTHORIZED).build();
+         }
+         return addMember(name, memberName, false);
+@@ -229,7 +229,7 @@
+     @Produces({MediaType.APPLICATION_JSON})
+     public Response addRequiredMember(@PathParam("name") final String name,
+         @PathParam("memberName") final String memberName, @Context final 
HttpServletRequest request) {
+-        if (!isAuthorized(request)) {
++        if (!isAuthorized()) {
+             return Response.status(Response.Status.UNAUTHORIZED).build();
+         }
+         return addMember(name, memberName, true);
+@@ -248,7 +248,7 @@
+     @Path("{name}")
+     @Produces({MediaType.APPLICATION_JSON})
+     public Response removeGroup(@PathParam("name") final String name, 
@Context final HttpServletRequest request) {
+-        if (!isAuthorized(request)) {
++        if (!isAuthorized()) {
+             return Response.status(Response.Status.UNAUTHORIZED).build();
+         }
+         return super.removeRole(name, Role.GROUP);
+@@ -269,11 +269,11 @@
+     @Produces({MediaType.APPLICATION_JSON})
+     public Response removeMember(@PathParam("name") final String name, 
@PathParam("memberName") final String memberName,
+         @Context final HttpServletRequest request) {
+-        if (!isAuthorized(request)) {
++        if (!isAuthorized()) {
+             return Response.status(Response.Status.UNAUTHORIZED).build();
+         }
+-        Role role = m_userAdmin.getRole(name);
+-        Role member = m_userAdmin.getRole(memberName);
++        Role role = getUserAdmin().getRole(name);
++        Role member = getUserAdmin().getRole(memberName);
+         if (role != null && role.getType() == Role.GROUP && member != null) {
+             if (((Group) role).removeMember(member)) {
+                 return buildOK();
+@@ -286,8 +286,8 @@
+     }
+ 
+     private Response addMember(String name, String memberName, boolean 
required) {
+-        Role role = m_userAdmin.getRole(name);
+-        Role member = m_userAdmin.getRole(memberName);
++        Role role = getUserAdmin().getRole(name);
++        Role member = getUserAdmin().getRole(memberName);
+         if (role != null && role.getType() == Role.GROUP && member != null) {
+             if (!required && ((Group) role).addMember(member)) {
+                 return buildOK();
+Index: 
amdatu-authorization/useradmin-rest/src/main/java/org/amdatu/authorization/useradmin/rest/service/ResourceBase.java
+===================================================================
+--- 
amdatu-authorization/useradmin-rest/src/main/java/org/amdatu/authorization/useradmin/rest/service/ResourceBase.java
        (revision 564)
++++ 
amdatu-authorization/useradmin-rest/src/main/java/org/amdatu/authorization/useradmin/rest/service/ResourceBase.java
        (working copy)
+@@ -21,25 +21,26 @@
+ import java.util.Collections;
+ import java.util.Comparator;
+ import java.util.List;
+-import java.util.Map;
+ 
+-import javax.servlet.http.HttpServletRequest;
+ import javax.ws.rs.WebApplicationException;
+ import javax.ws.rs.core.CacheControl;
+ import javax.ws.rs.core.MediaType;
+ import javax.ws.rs.core.Response;
+ 
+-import org.amdatu.authentication.tokenprovider.InvalidTokenException;
++import org.amdatu.authentication.contextmanager.ContextManager;
++import org.amdatu.authentication.contextmanager.UnknownProviderException;
+ import org.amdatu.authentication.tokenprovider.TokenProvider;
+-import org.amdatu.authentication.tokenprovider.TokenProviderException;
++import org.amdatu.authorization.login.service.LoginContextProvider;
+ import org.amdatu.authorization.useradmin.rest.bean.RoleBean;
+ import org.amdatu.authorization.useradmin.rest.bean.SearchResultBean;
++import org.amdatu.core.tenant.TenantContextProvider;
+ import org.amdatu.libraries.utilities.rest.AtomSyndicationLink;
+ import org.amdatu.web.rest.jaxrs.RESTService;
+ import org.json.JSONObject;
++import org.osgi.framework.BundleContext;
+ import org.osgi.framework.InvalidSyntaxException;
++import org.osgi.framework.ServiceReference;
+ import org.osgi.service.log.LogService;
+-import org.osgi.service.useradmin.Group;
+ import org.osgi.service.useradmin.Role;
+ import org.osgi.service.useradmin.User;
+ import org.osgi.service.useradmin.UserAdmin;
+@@ -47,11 +48,13 @@
+ abstract class ResourceBase implements RESTService {
+     // FIXME: Temporary fix for AMDATU-81
+     private static final String DEFAULT_ADMIN_GROUP = "Administrators";
+-    
++
+     // Service dependencies injected by the depedency manager
+     protected volatile LogService m_logService;
+-    protected volatile UserAdmin m_userAdmin;
++    //protected volatile UserAdmin m_userAdmin;
+     protected volatile TokenProvider m_tokenProvider;
++    private volatile ContextManager m_contextManager;
++    private volatile BundleContext m_bundleContext;
+ 
+     // Disable HTTP caching in this REST interface
+     private static CacheControl m_cacheControl;
+@@ -62,7 +65,7 @@
+ 
+     /**
+      * Returns the roles (users or groups) for the specified filter options.
+-     * 
++     *
+      * @param filter the filter to pass to UserAdmin
+      * @param sortOrder The sort order ('ascending' or 'descending')
+      * @param startIndex The startindex
+@@ -80,7 +83,7 @@
+             }
+ 
+             // First retrieve all roles with the specified filter
+-            Role[] roles = m_userAdmin.getRoles(null);
++            Role[] roles = getUserAdmin().getRoles(null);
+             final boolean descending = "desc".equalsIgnoreCase(sortOrder) || 
"descending".equalsIgnoreCase(sortOrder);
+ 
+             // Now filter out the user or groups (we should only return roles 
of type roleType)
+@@ -119,7 +122,7 @@
+             }
+ 
+             SearchResultBean result = new SearchResultBean();
+-            result.addRoles(roleRange, m_userAdmin);
++            result.addRoles(roleRange, getUserAdmin());
+ 
+             // Calculate paging
+             Paging paging = new Paging();
+@@ -140,7 +143,7 @@
+                 getBaseUrl() + "?startIndex=" + paging.pageStartIndex + 
"&endIndex=" + paging.pageEndIndex
+                 + "&maxResults=" + maxResults;
+             result.addLink(new 
AtomSyndicationLink().setHref(url).setRel("Alternate").setType("application/json"));
+-            
++
+             // Start
+             url =
+                 getBaseUrl() + "?startIndex=" + paging.firstStartIndex + 
"&endIndex=" + paging.firstEndIndex
+@@ -185,10 +188,10 @@
+     }
+ 
+     protected Response getRole(String name, int roleType) {
+-        Role role = m_userAdmin.getRole(name);
++        Role role = getUserAdmin().getRole(name);
+         if (role != null && role.getType() == roleType) {
+             try {
+-                RoleBean user = RoleBean.fromRole(role, m_userAdmin);
++                RoleBean user = RoleBean.fromRole(role, getUserAdmin());
+                 return Response.ok(user).cacheControl(m_cacheControl).build();
+             }
+             catch (URISyntaxException e) {
+@@ -202,7 +205,7 @@
+     }
+ 
+     protected Response createRole(String name, int roleType) {
+-        Role role = m_userAdmin.createRole(name, roleType);
++        Role role = getUserAdmin().createRole(name, roleType);
+         if (role != null) {
+             return buildOK();
+         }
+@@ -213,7 +216,7 @@
+ 
+     @SuppressWarnings("unchecked")
+     protected Response setCredential(String name, String key, String value, 
int roleType) {
+-        Role role = m_userAdmin.getRole(name);
++        Role role = getUserAdmin().getRole(name);
+         if (role != null && role.getType() == roleType) {
+             ((User) role).getCredentials().put(key, value);
+             return buildOK();
+@@ -225,7 +228,7 @@
+ 
+     @SuppressWarnings("unchecked")
+     protected Response setProperty(String name, String key, String value, int 
roleType) {
+-        Role role = m_userAdmin.getRole(name);
++        Role role = getUserAdmin().getRole(name);
+         if (role != null && role.getType() == roleType) {
+             role.getProperties().put(key, value);
+             return buildOK();
+@@ -236,9 +239,9 @@
+     }
+ 
+     protected Response removeRole(String name, int roleType) {
+-        Role role = m_userAdmin.getRole(name);
++        Role role = getUserAdmin().getRole(name);
+         if (role != null && role.getType() == roleType) {
+-            if (m_userAdmin.removeRole(name)) {
++            if (getUserAdmin().removeRole(name)) {
+                 return buildOK();
+             }
+             else {
+@@ -288,7 +291,7 @@
+ 
+         /**
+          * Calculate paging
+-         * 
++         *
+          * @param currentStartIndex The requested start index to display
+          * @param pageResults The amount of results in the current selection
+          * @param maxResults The maximum amount of results displayed on one 
page
+@@ -341,39 +344,46 @@
+     }
+ 
+     protected abstract String getBaseUrl();
+-    
++
+     // FIXME: Temporary fix for AMDATU-81. Until AMDATU-230 has been fixed we 
need to make a
+     // quick fix, not having any form of authorization is simply not 
acceptable. For now
+-    // we check if the user is logged in and in the "Administrators" role. 
This role is 
++    // we check if the user is logged in and in the "Administrators" role. 
This role is
+     // hard coded.
+-    protected boolean isAuthorized(HttpServletRequest request) {
+-        String token = m_tokenProvider.getTokenFromRequest(request);
+-        if (token != null) {
++    protected boolean isAuthorized() {
++        try {
++            String userName = 
m_contextManager.getValue(LoginContextProvider.ID, 
LoginContextProvider.USERNAME);
++            if (userName != null && !userName.isEmpty()) {
++                User user = (User) getUserAdmin().getRole(userName);
++                if (user != null) {
++                    return 
getUserAdmin().getAuthorization(user).hasRole(DEFAULT_ADMIN_GROUP);
++                }
++            }
++        }
++        catch (UnknownProviderException e) {
++            m_logService.log(LogService.LOG_ERROR, "Login context 
unavailable", e);
++        }
++        return false;
++    }
++
++    protected UserAdmin getUserAdmin() {
++        try {
+             try {
+-                Map<String, String> attributes = 
m_tokenProvider.verifyToken(token);
+-                if (attributes.containsKey(TokenProvider.USERNAME)) {
+-                    String userName = attributes.get(TokenProvider.USERNAME);
+-                    if (userName != null && !userName.isEmpty()) {
+-                        User user = (User) m_userAdmin.getRole(userName);
+-                        if (user != null) {
+-                            return 
m_userAdmin.getAuthorization(user).hasRole(DEFAULT_ADMIN_GROUP);
+-                        }
++                String tenantId = 
m_contextManager.getValue(TenantContextProvider.ID, 
TenantContextProvider.TENANT_ID);
++                if (tenantId != null && !tenantId.isEmpty()) {
++                    String filter = 
"(org.ops4j.pax.useradmin.storageprovider.type=Cassandra_" + tenantId + ")";
++                    ServiceReference[] servRefs = 
m_bundleContext.getAllServiceReferences(UserAdmin.class.getName(), filter);
++                    if (servRefs != null && servRefs.length > 0) {
++                        return (UserAdmin) 
m_bundleContext.getService(servRefs[0]);
+                     }
+-                }               
++                }
++            } catch (UnknownProviderException e) {
++                m_logService.log(LogService.LOG_ERROR, "Could not find tenant 
context provider", e);
+             }
+-            catch (TokenProviderException e) {
+-                // Ignore invalid tokens
+-            }
+-            catch (InvalidTokenException e) {
+-                // Ignore invalid tokens
+-            }
++            ServiceReference[] servRefs = 
m_bundleContext.getAllServiceReferences(UserAdmin.class.getName(), null);
++            return (UserAdmin) m_bundleContext.getService(servRefs[0]);
++        } catch (InvalidSyntaxException e) {
++            m_logService.log(LogService.LOG_ERROR, "Could not find useradmin 
service", e);
+         }
+-        return false;
++        return null;
+     }
+-    
+-    public void fix() {
+-        Role role = m_userAdmin.getRole("Administrator");
+-        Group group = (Group) m_userAdmin.getRole(DEFAULT_ADMIN_GROUP);
+-        group.addMember(role);
+-    }
+ }
+Index: 
amdatu-authorization/useradmin-rest/src/main/java/org/amdatu/authorization/useradmin/rest/service/RolesResource.java
+===================================================================
+--- 
amdatu-authorization/useradmin-rest/src/main/java/org/amdatu/authorization/useradmin/rest/service/RolesResource.java
       (revision 564)
++++ 
amdatu-authorization/useradmin-rest/src/main/java/org/amdatu/authorization/useradmin/rest/service/RolesResource.java
       (working copy)
+@@ -77,7 +77,7 @@
+         @DefaultValue("1") @QueryParam("startIndex") final int startIndex,
+         @DefaultValue("50") @QueryParam("maxResults") final int maxResults,
+         @Context final HttpServletRequest request) {
+-        if (!isAuthorized(request)) {
++        if (!isAuthorized()) {
+             return Response.status(Response.Status.UNAUTHORIZED).build();
+         }
+         return super.getRoles(filter, sortOrder, startIndex, maxResults, 
Role.ROLE);
+Index: 
amdatu-authorization/useradmin-rest/src/main/java/org/amdatu/authorization/useradmin/rest/service/UsersResource.java
+===================================================================
+--- 
amdatu-authorization/useradmin-rest/src/main/java/org/amdatu/authorization/useradmin/rest/service/UsersResource.java
       (revision 564)
++++ 
amdatu-authorization/useradmin-rest/src/main/java/org/amdatu/authorization/useradmin/rest/service/UsersResource.java
       (working copy)
+@@ -92,7 +92,7 @@
+         @DefaultValue("1") @QueryParam("startIndex") final int startIndex,
+         @DefaultValue("50") @QueryParam("maxResults") final int maxResults,
+         @Context final HttpServletRequest request) {
+-        if (!isAuthorized(request)) {
++        if (!isAuthorized()) {
+             return Response.status(Response.Status.UNAUTHORIZED).build();
+         }
+         return super.getRoles(filter, sortOrder, startIndex, maxResults, 
Role.USER);
+@@ -116,7 +116,7 @@
+     @Path("{name}")
+     @Produces({MediaType.APPLICATION_JSON})
+     public Response getUser(@PathParam("name") final String name, @Context 
final HttpServletRequest request) {
+-        if (!isAuthorized(request)) {
++        if (!isAuthorized()) {
+             return Response.status(Response.Status.UNAUTHORIZED).build();
+         }
+         return super.getRole(name, Role.USER);
+@@ -136,7 +136,7 @@
+     @Path("{name}")
+     @Produces({MediaType.APPLICATION_JSON})
+     public Response createUser(@PathParam("name") final String name, @Context 
final HttpServletRequest request) {
+-        if (!isAuthorized(request)) {
++        if (!isAuthorized()) {
+             return Response.status(Response.Status.UNAUTHORIZED).build();
+         }
+         return super.createRole(name, Role.USER);
+@@ -158,7 +158,7 @@
+     @Produces({MediaType.APPLICATION_JSON})
+     public Response setCredential(@PathParam("name") final String name,
+         @PathParam("key") final String key, @FormParam("value") final String 
value, @Context final HttpServletRequest request) {
+-        if (!isAuthorized(request)) {
++        if (!isAuthorized()) {
+             return Response.status(Response.Status.UNAUTHORIZED).build();
+         }
+         return setCredential(name, key, value, Role.USER);
+@@ -180,7 +180,7 @@
+     @Produces({MediaType.APPLICATION_JSON})
+     public Response setProperty(@PathParam("name") final String name,
+         @PathParam("key") final String key, @FormParam("value") final String 
value, @Context final HttpServletRequest request) {
+-        if (!isAuthorized(request)) {
++        if (!isAuthorized()) {
+             return Response.status(Response.Status.UNAUTHORIZED).build();
+         }
+         return setProperty(name, key, value, Role.USER);
+@@ -199,7 +199,7 @@
+     @Path("{name}")
+     @Produces({MediaType.APPLICATION_JSON})
+     public Response removeUser(@PathParam("name") final String name, @Context 
final HttpServletRequest request) {
+-        if (!isAuthorized(request)) {
++        if (!isAuthorized()) {
+             return Response.status(Response.Status.UNAUTHORIZED).build();
+         }
+         return super.removeRole(name, Role.USER);
+Index: amdatu-cassandra/cassandra-useradminstore/pom.xml
+===================================================================
+--- amdatu-cassandra/cassandra-useradminstore/pom.xml  (revision 564)
++++ amdatu-cassandra/cassandra-useradminstore/pom.xml  (working copy)
+@@ -12,31 +12,31 @@
+   <packaging>bundle</packaging>
+   <name>Amdatu Cassandra - User Admin Cassandra Store</name>
+   <description>Provides an implementation of the Pax UserAdmin 
store</description>
+-  
+-  <dependencies>  
++
++  <dependencies>
+     <dependency>
+       <groupId>org.ops4j.pax.useradmin</groupId>
+       <artifactId>pax-useradmin-service</artifactId>
+       <scope>provided</scope>
+-    </dependency>     
++    </dependency>
+     <dependency>
+       <groupId>org.amdatu.cassandra</groupId>
+       <artifactId>listener</artifactId>
+       <scope>provided</scope>
+       <type>bundle</type>
+-    </dependency>   
++    </dependency>
+     <dependency>
+       <groupId>org.amdatu.cassandra</groupId>
+       <artifactId>application</artifactId>
+       <scope>provided</scope>
+       <type>bundle</type>
+-    </dependency>     
++    </dependency>
+     <dependency>
+       <groupId>org.amdatu.cassandra</groupId>
+       <artifactId>persistencemanager</artifactId>
+       <scope>provided</scope>
+       <type>bundle</type>
+-    </dependency>        
++    </dependency>
+     <dependency>
+       <groupId>com.google.code.gson</groupId>
+       <artifactId>gson</artifactId>
+@@ -53,15 +53,22 @@
+     <dependency>
+       <groupId>org.amdatu.web</groupId>
+       <artifactId>httpcontext</artifactId>
+-      <scope>provided</scope> 
++      <scope>provided</scope>
+       <type>bundle</type>
+     </dependency>
+     <dependency>
++      <groupId>org.amdatu.core</groupId>
++      <artifactId>tenant</artifactId>
++      <version>${platform.version}</version>
++      <scope>provided</scope>
++      <type>bundle</type>
++    </dependency>
++    <dependency>
+       <groupId>org.json</groupId>
+       <artifactId>json</artifactId>
+       <version>20090211</version>
+       <scope>compile</scope>
+-    </dependency>   
++    </dependency>
+   </dependencies>
+ 
+   <build>
+@@ -80,5 +87,5 @@
+         </configuration>
+       </plugin>
+     </plugins>
+-  </build> 
++  </build>
+ </project>
+Index: 
amdatu-cassandra/cassandra-useradminstore/src/main/java/org/amdatu/cassandra/useradminstore/osgi/Activator.java
+===================================================================
+--- 
amdatu-cassandra/cassandra-useradminstore/src/main/java/org/amdatu/cassandra/useradminstore/osgi/Activator.java
    (revision 564)
++++ 
amdatu-cassandra/cassandra-useradminstore/src/main/java/org/amdatu/cassandra/useradminstore/osgi/Activator.java
    (working copy)
+@@ -16,21 +16,16 @@
+  */
+ package org.amdatu.cassandra.useradminstore.osgi;
+ 
+-import java.util.Hashtable;
+-
+ import org.amdatu.cassandra.application.CassandraDaemonService;
+-import org.amdatu.cassandra.listener.ColumnFamilyAvailable;
+ import org.amdatu.cassandra.listener.ColumnFamilyProvider;
+-import org.amdatu.cassandra.persistencemanager.CassandraPersistenceManager;
+ import 
org.amdatu.cassandra.useradminstore.rest.HttpContextRegistrationServiceImpl;
+-import org.amdatu.cassandra.useradminstore.service.CassandraStorageProvider;
++import 
org.amdatu.cassandra.useradminstore.service.CassandraStorageProviderRegistrationServiceImpl;
+ import org.amdatu.cassandra.useradminstore.service.RoleColumnFamilyProvider;
++import org.amdatu.core.tenant.Tenant;
+ import org.amdatu.web.httpcontext.HttpContextServiceFactory;
+ import org.amdatu.web.httpcontext.ResourceProvider;
+ import org.apache.felix.dm.DependencyActivatorBase;
+ import org.apache.felix.dm.DependencyManager;
+-import org.ops4j.pax.useradmin.service.UserAdminConstants;
+-import org.ops4j.pax.useradmin.service.spi.StorageProvider;
+ import org.osgi.framework.BundleContext;
+ import org.osgi.service.http.HttpService;
+ import org.osgi.service.log.LogService;
+@@ -42,42 +37,28 @@
+     // The resource identifier for this bundle. Resources are only considered 
to be 'ours' when
+     // it is prefixed with this id
+     public final static String RESOURCE_ID = "useradmin";
+-    
++
+     @Override
+     public void init(BundleContext context, DependencyManager manager) throws 
Exception {
+         // First define a service that provides the Role ColumnFamily we need
+         manager.add(createComponent()
+-                .setInterface(new 
String[]{ColumnFamilyProvider.class.getName()}, null)
+-                .setImplementation(RoleColumnFamilyProvider.class));
+-        
+-        // This filter is used to define a service dependency on the 
ColumnFamilyAvailable service
+-        // for the Role ColumnFamily. As a result, our service will depend on 
the availability
+-        // of this ColumnFamily.
+-        String roleFilter = "(" + ColumnFamilyAvailable.FILTER_NAME + "=" + 
CassandraStorageProvider.CF_ROLE + ")";
+-        String keyspaceFilter =
+-            "(" + CassandraPersistenceManager.KEYSPACE_AWARE_KEY + "="
+-                    + CassandraPersistenceManager.DEFAULT_KEYSPACE + ")";
+-        roleFilter = "(&" + roleFilter + keyspaceFilter + ")";
+-        
+-        // Create and register the CassandraStorageProvider service.
+-        Hashtable<String, String> properties = new Hashtable<String, 
String>();
+-        properties.put(UserAdminConstants.STORAGEPROVIDER_TYPE, "Cassandra");
+-        properties.put("service.ranking", "10");
+-        manager.add(createComponent()
+-                .setInterface(new String[]{StorageProvider.class.getName()}, 
properties)
+-                .setImplementation(CassandraStorageProvider.class)
+-                
.add(createServiceDependency().setService(LogService.class).setRequired(true))
+-                
.add(createServiceDependency().setService(CassandraPersistenceManager.class, 
keyspaceFilter).setRequired(true))
+-                
.add(createServiceDependency().setService(ColumnFamilyAvailable.class, 
roleFilter).setRequired(true))
+-                
.add(createServiceDependency().setService(CassandraDaemonService.class).setRequired(true)));
+-        
++            .setInterface(new String[]{ColumnFamilyProvider.class.getName()}, 
null)
++            .setImplementation(RoleColumnFamilyProvider.class));
++
++        // Create and register the tenant storage provider registration 
service, this service is responsible
++        // for launching a storage provider for each available tenant
++        manager.add(createAdapterService(Tenant.class, null)
++            
.setImplementation(CassandraStorageProviderRegistrationServiceImpl.class)
++            
.add(createServiceDependency().setService(CassandraDaemonService.class).setRequired(true))
++            
.add(createServiceDependency().setService(LogService.class).setRequired(true)));
++
+         // Create and register the http context registration service
+         manager.add(createComponent()
+-                .setInterface(ResourceProvider.class.getName(), null)
+-                .setImplementation(HttpContextRegistrationServiceImpl.class)
+-                
.add(createServiceDependency().setService(LogService.class).setRequired(true))
+-                
.add(createServiceDependency().setService(HttpContextServiceFactory.class).setRequired(true))
+-                
.add(createServiceDependency().setService(HttpService.class).setRequired(true)));
            
++            .setInterface(ResourceProvider.class.getName(), null)
++            .setImplementation(HttpContextRegistrationServiceImpl.class)
++            
.add(createServiceDependency().setService(LogService.class).setRequired(true))
++            
.add(createServiceDependency().setService(HttpContextServiceFactory.class).setRequired(true))
++            
.add(createServiceDependency().setService(HttpService.class).setRequired(true)));
+     }
+ 
+     @Override
+Index: 
amdatu-cassandra/cassandra-useradminstore/src/main/java/org/amdatu/cassandra/useradminstore/service/CassandraStorageProviderRegistrationServiceImpl.java
+===================================================================
+--- 
amdatu-cassandra/cassandra-useradminstore/src/main/java/org/amdatu/cassandra/useradminstore/service/CassandraStorageProviderRegistrationServiceImpl.java
   (revision 0)
++++ 
amdatu-cassandra/cassandra-useradminstore/src/main/java/org/amdatu/cassandra/useradminstore/service/CassandraStorageProviderRegistrationServiceImpl.java
   (revision 0)
+@@ -0,0 +1,58 @@
++package org.amdatu.cassandra.useradminstore.service;
++
++import java.util.Hashtable;
++
++import org.amdatu.cassandra.application.CassandraDaemonService;
++import org.amdatu.cassandra.listener.ColumnFamilyAvailable;
++import org.amdatu.cassandra.persistencemanager.CassandraPersistenceManager;
++import org.amdatu.core.tenant.Tenant;
++import org.apache.cassandra.thrift.InvalidRequestException;
++import org.apache.felix.dm.DependencyManager;
++import org.apache.thrift.TException;
++import org.ops4j.pax.useradmin.service.UserAdminConstants;
++import org.ops4j.pax.useradmin.service.spi.StorageProvider;
++import org.osgi.service.log.LogService;
++
++public class CassandraStorageProviderRegistrationServiceImpl {
++    // Service dependencies injected by the depedency manager
++    private volatile DependencyManager m_dependencyManager;
++    private volatile Tenant m_tenant;
++    private volatile CassandraDaemonService m_daemonService;
++    private volatile LogService m_logService;
++
++    public void start() {
++        try {
++            // We will create a storage provider that stores users for this 
tenant in a keyspace that equals the
++            // tenant id. We therefore first verify if that keyspace exists 
and if not, we create it.
++            if (!m_daemonService.getKeyspaces().contains(m_tenant.getId())) {
++                m_daemonService.addKeyspace(m_tenant.getId());
++            }
++
++            // This filter is used to define a service dependency on the 
ColumnFamilyAvailable service
++            // for the Role ColumnFamily. As a result, our service will 
depend on the availability
++            // of this ColumnFamily.
++            String roleFilter = "(" + ColumnFamilyAvailable.FILTER_NAME + "=" 
+ CassandraStorageProvider.CF_ROLE + ")";
++            String keyspaceFilter = "(" + 
CassandraPersistenceManager.KEYSPACE_AWARE_KEY + "=" + m_tenant.getId() + ")";
++            roleFilter = "(&" + roleFilter + keyspaceFilter + ")";
++
++            // Create and register the CassandraStorageProvider service.
++            Hashtable<String, String> properties = new Hashtable<String, 
String>();
++            properties.put(UserAdminConstants.STORAGEPROVIDER_TYPE, 
"Cassandra_" + m_tenant.getId());
++            properties.put("service.ranking", "10");
++            properties.put(Tenant.SERVICE_PREFIX + "id", m_tenant.getId());
++            m_dependencyManager.add(m_dependencyManager.createComponent()
++                .setInterface(new String[]{StorageProvider.class.getName()}, 
properties)
++                .setImplementation(CassandraStorageProvider.class)
++                
.add(m_dependencyManager.createServiceDependency().setService(LogService.class).setRequired(true))
++                
.add(m_dependencyManager.createServiceDependency().setService(CassandraPersistenceManager.class,
 keyspaceFilter).setRequired(true))
++                
.add(m_dependencyManager.createServiceDependency().setService(ColumnFamilyAvailable.class,
 roleFilter).setRequired(true))
++                
.add(m_dependencyManager.createServiceDependency().setService(CassandraDaemonService.class).setRequired(true)));
++
++            m_logService.log(LogService.LOG_INFO, "Cassandra useradmin 
storage provided started successfully for tenant  '" + m_tenant.getId() + "'");
++        } catch (TException e) {
++            m_logService.log(LogService.LOG_ERROR, "Could not start cassandra 
useradmin storage provider for tenant '" + m_tenant.getId() + "'", e);
++        } catch (InvalidRequestException e) {
++            m_logService.log(LogService.LOG_ERROR, "Could not start cassandra 
useradmin storage provider for tenant '" + m_tenant.getId() + "'", e);
++        }
++    }
++}
+Index: 
amdatu-cassandra/cassandra-useradminstore/src/main/java/org/amdatu/cassandra/useradminstore/service/RoleColumnFamilyProvider.java
+===================================================================
+--- 
amdatu-cassandra/cassandra-useradminstore/src/main/java/org/amdatu/cassandra/useradminstore/service/RoleColumnFamilyProvider.java
  (revision 564)
++++ 
amdatu-cassandra/cassandra-useradminstore/src/main/java/org/amdatu/cassandra/useradminstore/service/RoleColumnFamilyProvider.java
  (working copy)
+@@ -20,12 +20,11 @@
+ import org.amdatu.cassandra.listener.ColumnFamilyProvider;
+ import org.amdatu.cassandra.listener.ColumnFamilyDefinition.ColumnType;
+ import org.amdatu.cassandra.listener.ColumnFamilyDefinition.CompareType;
+-import org.amdatu.cassandra.persistencemanager.CassandraPersistenceManager;
+ 
+ /**
+  * This service only provides the Role Column Family. Note that the 
CassandraStorageProvider has
+  * a required dependency on the availability of this ColumnFamily (using 
ColumnFamilyAvailable
+- * with filter columnfamily=Role). So the CassandraStorageProvider doesn't 
start until this 
++ * with filter columnfamily=Role). So the CassandraStorageProvider doesn't 
start until this
+  * ColumnFamily is available in Cassandra (i.e. present in the last read 
storage config of Cassandra).
+  * The UserAdmin has a required dependency on the store, so the UserAdmin 
will not be available until
+  * the store is.
+@@ -34,11 +33,11 @@
+ public class RoleColumnFamilyProvider implements ColumnFamilyProvider {
+     public ColumnFamilyDefinition[] getColumnFamilies() {
+         return new ColumnFamilyDefinition[]{
+-                new ColumnFamilyDefinition(
+-                        CassandraStorageProvider.CF_ROLE, 
+-                        new 
String[]{CassandraPersistenceManager.DEFAULT_KEYSPACE},
+-                        ColumnType.SUPER, 
+-                        CompareType.BYTESTYPE, 
+-                        CompareType.BYTESTYPE)};
++            new ColumnFamilyDefinition(
++                CassandraStorageProvider.CF_ROLE,
++                null,
++                ColumnType.SUPER,
++                CompareType.BYTESTYPE,
++                CompareType.BYTESTYPE)};
+     }
+ }
+Index: amdatu-core/config-filebased/pom.xml
+===================================================================
+--- amdatu-core/config-filebased/pom.xml       (revision 564)
++++ amdatu-core/config-filebased/pom.xml       (working copy)
+@@ -15,7 +15,7 @@
+     <description>This bundle contains the configuration files of all Amdatu 
bundles and is repsonsible for registration of these configs in 
ConfigAdmin.</description>
+     
+     <build>
+-        <finalName>${groupId}.${artifactId}-${platform.version}</finalName>
++        
<finalName>${project.groupId}.${project.artifactId}-${platform.version}</finalName>
+         <resources>
+             <resource>
+                 <directory>src/main/resources</directory>
+Index: amdatu-core/tenant/pom.xml
+===================================================================
+--- amdatu-core/tenant/pom.xml (revision 564)
++++ amdatu-core/tenant/pom.xml (working copy)
+@@ -13,16 +13,23 @@
+   <name>Amdatu Core - Tenant Service</name>
+   <description>This bundle provides a tenant management service with tenant 
CRUD operations</description>
+ 
+-  <dependencies> 
++  <dependencies>
+     <dependency>
+       <groupId>org.amdatu.libraries</groupId>
+       <artifactId>utilities</artifactId>
+       <version>${platform.version}</version>
+       <scope>compile</scope>
+       <type>jar</type>
+-    </dependency>    
++    </dependency>
++    <dependency>
++      <groupId>org.amdatu.authentication</groupId>
++      <artifactId>contextmanager</artifactId>
++      <version>${platform.version}</version>
++      <scope>provided</scope>
++      <type>bundle</type>
++    </dependency>
+   </dependencies>
+-  
++
+   <build>
+     <plugins>
+       <plugin>
+@@ -38,7 +45,7 @@
+           </instructions>
+         </configuration>
+       </plugin>
+-      
++
+     </plugins>
+-  </build> 
++  </build>
+ </project>
+Index: 
amdatu-core/tenant/src/main/java/org/amdatu/core/tenant/osgi/Activator.java
+===================================================================
+--- 
amdatu-core/tenant/src/main/java/org/amdatu/core/tenant/osgi/Activator.java     
   (revision 564)
++++ 
amdatu-core/tenant/src/main/java/org/amdatu/core/tenant/osgi/Activator.java     
   (working copy)
+@@ -17,8 +17,11 @@
+  */
+ package org.amdatu.core.tenant.osgi;
+ 
++import org.amdatu.authentication.contextmanager.ContextProvider;
++import org.amdatu.core.tenant.TenantContextProvider;
+ import org.amdatu.core.tenant.TenantManagementService;
+ import org.amdatu.core.tenant.TenantStorageProvider;
++import org.amdatu.core.tenant.service.TenantContextProviderImpl;
+ import org.amdatu.core.tenant.service.TenantManagementServiceImpl;
+ import org.apache.felix.dm.DependencyActivatorBase;
+ import org.apache.felix.dm.DependencyManager;
+@@ -33,14 +36,21 @@
+ public class Activator extends DependencyActivatorBase {
+     @Override
+     public void init(BundleContext context, DependencyManager manager) throws 
Exception {
+-        
+         // Create and register the Tenant management service
+         manager.add(
+-                createComponent()
+-                .setImplementation(TenantManagementServiceImpl.class)
+-                .setInterface(TenantManagementService.class.getName(), null)
+-                
.add(createServiceDependency().setService(TenantStorageProvider.class).setRequired(true))
+-                
.add(createServiceDependency().setService(LogService.class).setRequired(true)));
++            createComponent()
++            .setImplementation(TenantManagementServiceImpl.class)
++            .setInterface(TenantManagementService.class.getName(), null)
++            
.add(createServiceDependency().setService(TenantStorageProvider.class).setRequired(true))
++            
.add(createServiceDependency().setService(LogService.class).setRequired(true)));
++
++        // Create and register the Tenant context provider
++        manager.add(
++            createComponent()
++            .setImplementation(TenantContextProviderImpl.class)
++            .setInterface(new String[]{TenantContextProvider.class.getName(), 
ContextProvider.class.getName()}, null)
++            
.add(createServiceDependency().setService(TenantManagementService.class).setRequired(true))
++            
.add(createServiceDependency().setService(LogService.class).setRequired(true)));
+     }
+ 
+     @Override
+Index: 
amdatu-core/tenant/src/main/java/org/amdatu/core/tenant/service/TenantContextProviderImpl.java
+===================================================================
+--- 
amdatu-core/tenant/src/main/java/org/amdatu/core/tenant/service/TenantContextProviderImpl.java
     (revision 0)
++++ 
amdatu-core/tenant/src/main/java/org/amdatu/core/tenant/service/TenantContextProviderImpl.java
     (revision 0)
+@@ -0,0 +1,131 @@
++/*
++    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.core.tenant.service;
++
++import java.util.ArrayList;
++import java.util.HashMap;
++import java.util.List;
++import java.util.Map;
++
++import javax.servlet.http.HttpServletRequest;
++
++import org.amdatu.authentication.contextmanager.ContextProvider;
++import org.amdatu.core.tenant.Tenant;
++import org.amdatu.core.tenant.TenantContextProvider;
++import org.amdatu.core.tenant.TenantEntity;
++import org.amdatu.core.tenant.TenantException;
++import org.amdatu.core.tenant.TenantManagementService;
++import org.osgi.service.log.LogService;
++
++/**
++ * Implementation of the tenant context provider.
++ * 
++ * @author ivol
++ */
++public class TenantContextProviderImpl implements TenantContextProvider {
++    // Tenant context information is bound to a ThreadLocal variable.
++    private static ThreadLocal<Map<String, String>> m_properties = new 
ThreadLocal<Map<String, String>>();
++
++    // Service dependencies injected by the dependency manager
++    private volatile TenantManagementService m_tenantManagementService;
++    private volatile LogService m_logService;
++
++    public String getId() {
++        return TenantContextProvider.ID;
++    }
++
++    public String getValue(String propertyName) {
++        if (m_properties.get() != null) {
++            return m_properties.get().get(propertyName);
++        } else {
++            return null;
++        }
++    }
++
++    private void setValue(String key, String value) {
++        if (m_properties.get() == null) {
++            m_properties.set(new HashMap<String, String>());
++        }
++        m_properties.get().put(key, value);
++    }
++
++    public void start()  {
++        try {
++            // TODO: this is test code, create test tenants!
++            if (m_tenantManagementService.getTenantById("tenant_a") == null) {
++                TenantEntity tenantA = 
m_tenantManagementService.createTenant("tenant_a", "Tenant A");
++                tenantA.putProperty(HOSTNAME, "localhost");
++                m_tenantManagementService.updateTenant(tenantA);
++            }
++            if (m_tenantManagementService.getTenantById("tenant_b") == null) {
++                TenantEntity tenantB = 
m_tenantManagementService.createTenant("tenant_b", "Tenant B");
++                tenantB.putProperty(HOSTNAME, "127.0.0.1");
++                m_tenantManagementService.updateTenant(tenantB);
++            }
++        } catch (TenantException e) {
++        }
++    }
++
++    public void resolve(Map<String, Object> properties) {
++        // Check if the context resolver properties contain a HTTP request, 
if so we are able to resolve
++        // this to a tenant context
++        String serverName = "";
++        if (properties.containsKey(ContextProvider.PROPERTY_HTTP_REQUEST)) {
++            try {
++                HttpServletRequest request = (HttpServletRequest) 
properties.get(ContextProvider.PROPERTY_HTTP_REQUEST);
++                serverName = request.getServerName();
++
++                // Start with a full list of tenants and remove tenants that 
do not match the hostname of the request.
++                List<TenantEntity> matchingTenants = new 
ArrayList<TenantEntity>();
++                for (TenantEntity tenant : 
m_tenantManagementService.getTenants()) {
++                    matchingTenants.add(tenant);
++                }
++                int size = matchingTenants.size();
++
++                // Loop over all available Tenants and determine the cross 
section
++                // of all matches. Note that if a tenant match returns 
UNKNOWN, this means that
++                // it is unable to resolve and so the result should be 
ignored.
++                for (int i=0; i<size;) {
++                    if (!match(matchingTenants.get(i), serverName)) {
++                        matchingTenants.remove(matchingTenants.get(i));
++                        size--;
++                    } else {
++                        i++;
++                    }
++                }
++                if (size == 1) {
++                    setValue(TENANT_ID, matchingTenants.get(0).getId());
++                }
++            } catch (TenantException e) {
++                m_logService.log(LogService.LOG_ERROR, "Could not resolve '" 
+ serverName + "' to a tenant", e);
++            }
++        }
++    }
++
++    private boolean match(Tenant tenant, String serverName) {
++        if 
(tenant.getProperties().containsKey(TenantContextProvider.HOSTNAME)) {
++            String tenantHostname = 
tenant.getProperties().get(TenantContextProvider.HOSTNAME);
++            if (!serverName.equals(tenantHostname)) {
++                return false;
++            }
++        }
++
++        // True means that either the hostname matches the tenant or the 
tenant didn't contain a hostname
++        // and could not be matched.
++        return true;
++    }
++}
+Index: 
amdatu-core/tenant/src/main/java/org/amdatu/core/tenant/service/TenantManagementServiceImpl.java
+===================================================================
+--- 
amdatu-core/tenant/src/main/java/org/amdatu/core/tenant/service/TenantManagementServiceImpl.java
   (revision 564)
++++ 
amdatu-core/tenant/src/main/java/org/amdatu/core/tenant/service/TenantManagementServiceImpl.java
   (working copy)
+@@ -16,9 +16,17 @@
+  */
+ package org.amdatu.core.tenant.service;
+ 
+-import java.util.*;
++import java.util.ArrayList;
++import java.util.HashMap;
++import java.util.List;
++import java.util.Map;
++import java.util.Properties;
+ 
+-import org.amdatu.core.tenant.*;
++import org.amdatu.core.tenant.Tenant;
++import org.amdatu.core.tenant.TenantEntity;
++import org.amdatu.core.tenant.TenantException;
++import org.amdatu.core.tenant.TenantManagementService;
++import org.amdatu.core.tenant.TenantStorageProvider;
+ import org.apache.felix.dm.Component;
+ import org.apache.felix.dm.DependencyManager;
+ 
+@@ -98,8 +106,8 @@
+ 
+     private void createTenantService(TenantEntity tenant) {
+         Component component = m_manager.createComponent()
+-                .setImplementation(tenant)
+-                .setInterface(Tenant.class.getName(), 
createServiceProperties(tenant));
++        .setImplementation(tenant)
++        .setInterface(Tenant.class.getName(), 
createServiceProperties(tenant));
+         m_manager.add(component);
+         m_tenantComponents.put(tenant, component);
+     }
+@@ -121,7 +129,7 @@
+         }
+         properties.put(Tenant.SERVICE_PREFIX + "id", tenant.getId());
+         properties.put(Tenant.SERVICE_PREFIX + "name", tenant.getName());
+-        
++
+         return properties;
+     }
+ }
+Index: 
amdatu-core/tenant/src/main/java/org/amdatu/core/tenant/TenantContextProvider.java
+===================================================================
+--- 
amdatu-core/tenant/src/main/java/org/amdatu/core/tenant/TenantContextProvider.java
 (revision 0)
++++ 
amdatu-core/tenant/src/main/java/org/amdatu/core/tenant/TenantContextProvider.java
 (revision 0)
+@@ -0,0 +1,37 @@
++/*
++/*
++    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.core.tenant;
++
++import org.amdatu.authentication.contextmanager.ContextProvider;
++
++public interface TenantContextProvider extends ContextProvider {
++    /**
++     * Id of the tenant context provider.
++     */
++    String ID = "org.amdatu.core.tenant.contextprovider";
++
++    /**
++     * Name of the hostname property in this context. The hostname is matched 
to one or more tenants.
++     */
++    String HOSTNAME = "hostname";
++
++    /**
++     * Name of the tenant property in this context.
++     */
++    String TENANT_ID = "tenantid";
++}
+Index: 
amdatu-core/tenant/src/main/java/org/amdatu/core/tenant/TenantEntity.java
+===================================================================
+--- amdatu-core/tenant/src/main/java/org/amdatu/core/tenant/TenantEntity.java  
(revision 564)
++++ amdatu-core/tenant/src/main/java/org/amdatu/core/tenant/TenantEntity.java  
(working copy)
+@@ -1,5 +1,4 @@
+ /*
+-/*
+     Copyright (C) 2010 Amdatu.org
+ 
+     This program is free software: you can redistribute it and/or modify
+@@ -55,7 +54,7 @@
+     public void setName(String name) {
+         m_name = name;
+     }
+-    
++
+     public Map<String, String> getProperties() {
+         return new HashMap<String, String>(m_properties);
+     }
+@@ -75,16 +74,19 @@
+ 
+     @Override
+     public boolean equals(Object obj) {
+-        if (this == obj)
++        if (this == obj) {
+             return true;
+-        if (obj == null)
++        }
++        if (obj == null) {
+             return false;
+-        if (getClass() != obj.getClass())
++        }
++        if (getClass() != obj.getClass()) {
+             return false;
++        }
+         TenantEntity other = (TenantEntity) obj;
+         return m_id == other.getId();
+     }
+-    
++
+     public boolean matches(Map<String, String> properties) {
+         for (String key : properties.keySet()) {
+             if (!m_properties.containsKey(key)) {
+Index: 
amdatu-core/tenant/src/main/java/org/amdatu/core/tenant/TenantManagementService.java
+===================================================================
+--- 
amdatu-core/tenant/src/main/java/org/amdatu/core/tenant/TenantManagementService.java
       (revision 564)
++++ 
amdatu-core/tenant/src/main/java/org/amdatu/core/tenant/TenantManagementService.java
       (working copy)
+@@ -1,5 +1,4 @@
+ /*
+-/*
+     Copyright (C) 2010 Amdatu.org
+ 
+     This program is free software: you can redistribute it and/or modify
+@@ -23,7 +22,7 @@
+ /**
+  * Interface of the tenant service. Responsible for managing tenants. Service 
adapters
+  * are used to create tenant aware services. The tenant service will provide 
tenants
+- * and the Felix dependency manager will automatically invoke a service 
instance for 
++ * and the Felix dependency manager will automatically invoke a service 
instance for
+  * each tenant aware service in which the tenant is injected.
+  */
+ public interface TenantManagementService {
+@@ -31,23 +30,23 @@
+      * Gets all tenants, or an empty list if there are none.
+      */
+     List<TenantEntity> getTenants() throws TenantException;
+-    
++
+     /**
+      * Gets the tenant with the given ID, or <code>null</code> if this 
doesn't exist.
+      */
+     TenantEntity getTenantById(String id) throws TenantException;
+-    
++
+     /**
+      * Gets all tenants that match the given properties, or an empty list if 
there are none.
+      */
+     List<TenantEntity> getTenants(Map<String, String> properties) throws 
TenantException;
+-        
++
+     /**
+      * Creates a new tenant with the specified id and name.
+      * @throws TenantException in case a tenant with the specified id already 
exists.
+      */
+     TenantEntity createTenant(String id, String name) throws TenantException;
+-    
++
+     void updateTenant(TenantEntity tenant) throws TenantException;
+ 
+     void deleteTenant(TenantEntity tenant) throws TenantException;
+Index: amdatu-opensocial/gadgetmanagement/pom.xml
+===================================================================
+--- amdatu-opensocial/gadgetmanagement/pom.xml (revision 564)
++++ amdatu-opensocial/gadgetmanagement/pom.xml (working copy)
+@@ -12,8 +12,8 @@
+   <packaging>bundle</packaging>
+   <name>Amdatu Open Social - Gadget Management</name>
+   <description>Provides a service to manage gadgets stored in the gadget 
store</description>
+-  
+-  <dependencies>  
++
++  <dependencies>
+     <dependency>
+       <groupId>org.amdatu.web</groupId>
+       <artifactId>httpcontext</artifactId>
+@@ -32,7 +32,7 @@
+       <version>${platform.version}</version>
+       <scope>provided</scope>
+       <type>bundle</type>
+-    </dependency>   
++    </dependency>
+     <dependency>
+       <groupId>org.amdatu.cassandra</groupId>
+       <artifactId>listener</artifactId>
+@@ -52,7 +52,7 @@
+       <artifactId>shindig</artifactId>
+       <scope>provided</scope>
+       <type>bundle</type>
+-    </dependency>   
++    </dependency>
+     <dependency>
+       <groupId>org.json</groupId>
+       <artifactId>json</artifactId>
+@@ -70,8 +70,15 @@
+       <version>${platform.version}</version>
+       <scope>provided</scope>
+     </dependency>
++    <dependency>
++      <groupId>org.amdatu.authentication</groupId>
++      <artifactId>contextmanager</artifactId>
++      <version>${platform.version}</version>
++      <scope>provided</scope>
++      <type>bundle</type>
++    </dependency>
+   </dependencies>
+-  
++
+   <build>
+     <plugins>
+       <plugin>
+@@ -80,12 +87,12 @@
+         <configuration>
+           <instructions>
+             
<Bundle-Activator>org.amdatu.opensocial.gadgetmanagement.osgi.Activator</Bundle-Activator>
+-            <Bundle-SymbolicName> 
org.amdatu.opensocial.gadgetmanagement</Bundle-SymbolicName>     
++            <Bundle-SymbolicName> 
org.amdatu.opensocial.gadgetmanagement</Bundle-SymbolicName>
+             <Embed-Dependency>*;scope=compile</Embed-Dependency>
+             <Embed-Transitive>true</Embed-Transitive>
+           </instructions>
+         </configuration>
+-      </plugin>   
+-    </plugins>        
+-  </build> 
++      </plugin>
++    </plugins>
++  </build>
+ </project>
+Index: 
amdatu-opensocial/gadgetmanagement/src/main/java/org/amdatu/opensocial/gadgetmanagement/osgi/Activator.java
+===================================================================
+--- 
amdatu-opensocial/gadgetmanagement/src/main/java/org/amdatu/opensocial/gadgetmanagement/osgi/Activator.java
        (revision 564)
++++ 
amdatu-opensocial/gadgetmanagement/src/main/java/org/amdatu/opensocial/gadgetmanagement/osgi/Activator.java
        (working copy)
+@@ -16,7 +16,7 @@
+  */
+ package org.amdatu.opensocial.gadgetmanagement.osgi;
+ 
+-import org.amdatu.authentication.tokenprovider.TokenProvider;
++import org.amdatu.authentication.contextmanager.ContextManager;
+ import org.amdatu.cassandra.listener.ColumnFamilyAvailable;
+ import org.amdatu.cassandra.persistencemanager.CassandraPersistenceManager;
+ import org.amdatu.libraries.utilities.osgi.ServiceDependentActivator;
+@@ -51,19 +51,19 @@
+         String gadgetFilter = "(" + ColumnFamilyAvailable.FILTER_NAME + "=" + 
GadgetStore.CF_GADGET + ")";
+         String keyspaceFilter =
+             "(" + CassandraPersistenceManager.KEYSPACE_AWARE_KEY + "="
+-                    + CassandraPersistenceManager.DEFAULT_KEYSPACE + ")";
++            + CassandraPersistenceManager.DEFAULT_KEYSPACE + ")";
+         gadgetFilter = "(&" + gadgetFilter + keyspaceFilter + ")";
+         manager.add(
+-                createComponent()
+-                .setInterface(new String[]{GadgetManagement.class.getName(), 
ResourceProvider.class.getName()}, null)
+-                .setImplementation(GadgetManagementServiceImpl.class)
+-                
.add(createServiceDependency().setService(LogService.class).setRequired(true))
+-                
.add(createServiceDependency().setService(UserAdmin.class).setRequired(true))
+-                
.add(createServiceDependency().setService(HttpContextServiceFactory.class).setRequired(true))
+-                
.add(createServiceDependency().setService(ColumnFamilyAvailable.class, 
gadgetFilter).setRequired(true))
+-                
.add(createServiceDependency().setService(GadgetStore.class).setRequired(true))
+-                
.add(createServiceDependency().setService(TokenProvider.class).setRequired(true))
+-                
.add(createServiceDependency().setService(CassandraPersistenceManager.class, 
keyspaceFilter).setRequired(true)));
++            createComponent()
++            .setInterface(new String[]{GadgetManagement.class.getName(), 
ResourceProvider.class.getName()}, null)
++            .setImplementation(GadgetManagementServiceImpl.class)
++            
.add(createServiceDependency().setService(LogService.class).setRequired(true))
++            
.add(createServiceDependency().setService(UserAdmin.class).setRequired(true))
++            
.add(createServiceDependency().setService(HttpContextServiceFactory.class).setRequired(true))
++            
.add(createServiceDependency().setService(ColumnFamilyAvailable.class, 
gadgetFilter).setRequired(true))
++            
.add(createServiceDependency().setService(GadgetStore.class).setRequired(true))
++            
.add(createServiceDependency().setService(ContextManager.class).setRequired(true))
++            
.add(createServiceDependency().setService(CassandraPersistenceManager.class, 
keyspaceFilter).setRequired(true)));
+     }
+ 
+     @Override
+Index: 
amdatu-opensocial/gadgetmanagement/src/main/java/org/amdatu/opensocial/gadgetmanagement/service/GadgetManagementServiceImpl.java
+===================================================================
+--- 
amdatu-opensocial/gadgetmanagement/src/main/java/org/amdatu/opensocial/gadgetmanagement/service/GadgetManagementServiceImpl.java
   (revision 564)
++++ 
amdatu-opensocial/gadgetmanagement/src/main/java/org/amdatu/opensocial/gadgetmanagement/service/GadgetManagementServiceImpl.java
   (working copy)
+@@ -48,9 +48,9 @@
+ import javax.ws.rs.core.MediaType;
+ import javax.ws.rs.core.Response;
+ 
+-import org.amdatu.authentication.tokenprovider.InvalidTokenException;
+-import org.amdatu.authentication.tokenprovider.TokenProvider;
+-import org.amdatu.authentication.tokenprovider.TokenProviderException;
++import org.amdatu.authentication.contextmanager.ContextManager;
++import org.amdatu.authentication.contextmanager.UnknownProviderException;
++import org.amdatu.authorization.login.service.LoginContextProvider;
+ import org.amdatu.authorization.login.service.LoginService;
+ import org.amdatu.cassandra.persistencemanager.CassandraException;
+ import org.amdatu.libraries.utilities.ConversionUtil;
+@@ -102,7 +102,7 @@
+     private volatile UserAdmin m_userAdmin;
+     private volatile HttpContextServiceFactory m_httpContextFactoryService;
+     private volatile GadgetStore m_gadgetStore;
+-    private volatile TokenProvider m_tokenProvider;
++    private volatile ContextManager m_contextManager;
+ 
+     private Component m_httpContextComponent;
+ 
+@@ -284,9 +284,10 @@
+     public Response getMyGadgets(@Context HttpHeaders headers, @Context 
HttpServletRequest request) {
+         JSONObject jsonObject = new JSONObject();
+         List<JSONObject> gadgets = new ArrayList<JSONObject>();
+-        String viewer = getUserNameFromRequest(request);
+-        String errorMsg = "An error occurred while retrieving gadgets for 
viewer '" + viewer + "'.";
++        String errorMsg = "";
+         try {
++            String viewer = 
m_contextManager.getValue(LoginContextProvider.ID, 
LoginContextProvider.USERNAME);
++            errorMsg = "An error occurred while retrieving gadgets for viewer 
'" + viewer + "'.";
+             User user = null;
+             String[] gadgetIds = null;
+             if (viewer != null && !"anonymous".equals(viewer)) {
+@@ -381,6 +382,9 @@
+         catch (IOException e) {
+             m_logService.log(LogService.LOG_ERROR, errorMsg, e);
+         }
++        catch (UnknownProviderException e) {
++            m_logService.log(LogService.LOG_ERROR, "Loging context 
unavailable", e);
++        }
+ 
+         return Response.ok(jsonObject.toString(), 
MediaType.APPLICATION_JSON_TYPE).cacheControl(m_noCacheControl).build();
+     }
+@@ -639,12 +643,17 @@
+         String viewerId = "anonymous";
+         String ownerId = "anonymous";
+ 
+-        // Verify if we have a valid authentication token holding a username, 
if so add the authenticated user as viewer
+-        String userName = getUserNameFromRequest(request);
+-        if (userName != null && !"".equals(userName)) {
+-            viewerId = userName;
+-            ownerId = userName;
++        try {
++            // Verify if we have a valid authentication token holding a 
username, if so add the authenticated user as viewer
++            String userName = 
m_contextManager.getValue(LoginContextProvider.ID, 
LoginContextProvider.USERNAME);
++            if (userName != null && !"".equals(userName)) {
++                viewerId = userName;
++                ownerId = userName;
++            }
+         }
++        catch (UnknownProviderException e) {
++            m_logService.log(LogService.LOG_WARNING, "Login context 
uinavailable, could not retrieve user", e);
++        }
+         st.setViewerId(viewerId);
+         st.setOwnerId(ownerId);
+ 
+@@ -691,25 +700,6 @@
+         return m_gadgetStore.getCategories();
+     }
+ 
+-    private String getUserNameFromRequest(HttpServletRequest request) {
+-        String token = m_tokenProvider.getTokenFromRequest(request);
+-        if (token != null) {
+-            try {
+-                Map<String, String> attributes = 
m_tokenProvider.verifyToken(token);
+-                if (attributes.containsKey(TokenProvider.USERNAME)) {
+-                    return attributes.get(TokenProvider.USERNAME);
+-                }
+-            }
+-            catch (TokenProviderException e) {
+-                // Ignore invalid tokens
+-            }
+-            catch (InvalidTokenException e) {
+-                // Ignore invalid tokens
+-            }
+-        }
+-        return null;
+-    }
+-
+     private String toAbsoluteUrl(String url, HttpServletRequest request) {
+         if (url.startsWith("/")) {
+             // This is a relative URL, convert to absolute URL
+Index: amdatu-release/pom.xml
+===================================================================
+--- amdatu-release/pom.xml     (revision 564)
++++ amdatu-release/pom.xml     (working copy)
+@@ -13,48 +13,55 @@
+   <dependencies>
+     <!-- Authentication bundles -->
+     <dependency>
++      <groupId>org.amdatu.authentication</groupId>
++      <artifactId>contextmanager</artifactId>
++      <version>${platform.version}</version>
++      <scope>compile</scope>
++      <type>bundle</type>
++    </dependency>
++    <dependency>
+       <groupId>org.amdatu.authentication.oauth</groupId>
+-      <artifactId>api</artifactId>    
++      <artifactId>api</artifactId>
+       <version>${platform.version}</version>
+       <scope>compile</scope>
+       <type>bundle</type>
+-    </dependency>    
++    </dependency>
+     <dependency>
+       <groupId>org.amdatu.authentication.oauth</groupId>
+-      <artifactId>server</artifactId>    
++      <artifactId>server</artifactId>
+       <version>${platform.version}</version>
+       <scope>compile</scope>
+       <type>bundle</type>
+     </dependency>
+     <dependency>
+       <groupId>org.amdatu.authentication.oauth</groupId>
+-      <artifactId>client</artifactId>    
++      <artifactId>client</artifactId>
+       <version>${platform.version}</version>
+       <scope>compile</scope>
+       <type>bundle</type>
+-    </dependency>    
++    </dependency>
+     <dependency>
+       <groupId>org.amdatu.authentication.oauth</groupId>
+-      <artifactId>consumerregistry-fs</artifactId>    
++      <artifactId>consumerregistry-fs</artifactId>
+       <version>${platform.version}</version>
+       <scope>compile</scope>
+       <type>bundle</type>
+-    </dependency>    
++    </dependency>
+     <dependency>
+       <groupId>org.amdatu.authentication</groupId>
+-      <artifactId>tokenprovider</artifactId>    
++      <artifactId>tokenprovider</artifactId>
+       <version>${platform.version}</version>
+       <scope>compile</scope>
+       <type>bundle</type>
+-    </dependency>    
++    </dependency>
+     <dependency>
+       <groupId>org.amdatu.authentication.tokenstore</groupId>
+-      <artifactId>mem</artifactId>    
++      <artifactId>mem</artifactId>
+       <version>${platform.version}</version>
+       <scope>compile</scope>
+       <type>bundle</type>
+-    </dependency>        
+-    
++    </dependency>
++
+     <!-- Authorization bundles -->
+     <dependency>
+       <groupId>org.amdatu.authorization.login</groupId>
+@@ -76,7 +83,7 @@
+       <version>${platform.version}</version>
+       <scope>compile</scope>
+       <type>bundle</type>
+-    </dependency>    
++    </dependency>
+     <dependency>
+       <groupId>org.amdatu.authorization.useradmin</groupId>
+       <artifactId>rest</artifactId>
+@@ -192,7 +199,7 @@
+       <version>${platform.version}</version>
+       <scope>compile</scope>
+       <type>bundle</type>
+-    </dependency>    
++    </dependency>
+ 
+     <!-- Open Social bundles -->
+     <dependency>
+@@ -238,7 +245,7 @@
+       <version>${platform.version}</version>
+       <scope>compile</scope>
+       <type>bundle</type>
+-    </dependency>  
++    </dependency>
+     <dependency>
+       <groupId>org.amdatu.semanticweb</groupId>
+       <artifactId>sesame</artifactId>
+Index: amdatu-web/httpcontext/pom.xml
+===================================================================
+--- amdatu-web/httpcontext/pom.xml     (revision 564)
++++ amdatu-web/httpcontext/pom.xml     (working copy)
+@@ -13,6 +13,22 @@
+   <name>Amdatu Web - HTTP Context</name>
+   <description>Provides a HTTPContext implementation</description>
+ 
++  <dependencies>
++    <dependency>
++      <groupId>org.amdatu.authentication</groupId>
++      <artifactId>tokenprovider</artifactId>
++      <version>${platform.version}</version>
++      <scope>provided</scope>
++    </dependency>
++    <dependency>
++      <groupId>org.amdatu.authentication</groupId>
++      <artifactId>contextmanager</artifactId>
++      <version>${platform.version}</version>
++      <scope>provided</scope>
++      <type>bundle</type>
++    </dependency>
++  </dependencies>
++
+   <build>
+     <plugins>
+       <plugin>
+Index: 
amdatu-web/httpcontext/src/main/java/org/amdatu/web/httpcontext/osgi/Activator.java
+===================================================================
+--- 
amdatu-web/httpcontext/src/main/java/org/amdatu/web/httpcontext/osgi/Activator.java
        (revision 564)
++++ 
amdatu-web/httpcontext/src/main/java/org/amdatu/web/httpcontext/osgi/Activator.java
        (working copy)
+@@ -16,8 +16,15 @@
+  */
+ package org.amdatu.web.httpcontext.osgi;
+ 
++import java.util.Dictionary;
++import java.util.Hashtable;
++
++import javax.servlet.Filter;
++
++import org.amdatu.authentication.contextmanager.ContextManager;
+ import org.amdatu.web.httpcontext.HttpContextServiceFactory;
+ import org.amdatu.web.httpcontext.service.HttpContextFactoryServiceImpl;
++import org.amdatu.web.httpcontext.service.HttpRequestContextResolver;
+ import org.apache.felix.dm.DependencyActivatorBase;
+ import org.apache.felix.dm.DependencyManager;
+ import org.osgi.framework.BundleContext;
+@@ -30,13 +37,26 @@
+  */
+ public class Activator extends DependencyActivatorBase {
+     @Override
+-    public void init(BundleContext context, DependencyManager manager) throws 
Exception {        
++    public void init(BundleContext context, DependencyManager manager) throws 
Exception {
+         manager.add(
+-                createComponent()
+-                .setImplementation(HttpContextFactoryServiceImpl.class)
+-                .setInterface(HttpContextServiceFactory.class.getName(), null)
+-                
.add(createServiceDependency().setService(HttpService.class).setRequired(true))
+-                
.add(createServiceDependency().setService(LogService.class).setRequired(true)));
++            createComponent()
++            .setImplementation(HttpContextFactoryServiceImpl.class)
++            .setInterface(HttpContextServiceFactory.class.getName(), null)
++            
.add(createServiceDependency().setService(HttpService.class).setRequired(true))
++            
.add(createServiceDependency().setService(LogService.class).setRequired(true)));
++
++        // Create and register a HttpSessionContext resolver filter. This 
filter is mapped on *
++        // and will set context information into SessionContext based on 
information send along
++        // with a HTTP context
++        Dictionary<String, String> filterProperties = new Hashtable<String, 
String>();
++        filterProperties.put("pattern", ".*");
++        filterProperties.put("service.ranking", "99999999"); // We definitely 
want to be the first!!!!
++        filterProperties.put("contextId", "sesioncontextfilter");
++        manager.add(
++            createComponent()
++            .setImplementation(HttpRequestContextResolver.class)
++            .setInterface(Filter.class.getName(), filterProperties)
++            
.add(createServiceDependency().setService(ContextManager.class).setRequired(true)));
+     }
+ 
+     @Override
+Index: 
amdatu-web/httpcontext/src/main/java/org/amdatu/web/httpcontext/service/HttpRequestContextResolver.java
+===================================================================
+--- 
amdatu-web/httpcontext/src/main/java/org/amdatu/web/httpcontext/service/HttpRequestContextResolver.java
    (revision 0)
++++ 
amdatu-web/httpcontext/src/main/java/org/amdatu/web/httpcontext/service/HttpRequestContextResolver.java
    (revision 0)
+@@ -0,0 +1,56 @@
++/*
++    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.web.httpcontext.service;
++
++import java.io.IOException;
++import java.util.HashMap;
++import java.util.Map;
++
++import javax.servlet.Filter;
++import javax.servlet.FilterChain;
++import javax.servlet.FilterConfig;
++import javax.servlet.ServletException;
++import javax.servlet.ServletRequest;
++import javax.servlet.ServletResponse;
++
++import org.amdatu.authentication.contextmanager.ContextManager;
++import org.amdatu.authentication.contextmanager.ContextProvider;
++
++/**
++ * This filter captures HTTP requests and invokes resolve() on the 
ContextManager. The ContextManager will delegate the
++ * resolving to all available Context Providers. Any provider that can 
resolve context information from a HTTP request
++ * can do so.
++ *
++ * @author ivol
++ */
++public class HttpRequestContextResolver implements Filter {
++    // Service dependencies, injected by the dependency manager
++    private volatile ContextManager m_contextManager;
++
++    public void init(FilterConfig filterConfig) throws ServletException {
++    }
++
++    public void doFilter(ServletRequest request, ServletResponse response, 
FilterChain chain) throws IOException, ServletException {
++        Map<String, Object> contextProperties = new HashMap<String, Object>();
++        contextProperties.put(ContextProvider.PROPERTY_HTTP_REQUEST, request);
++        m_contextManager.resolve(contextProperties);
++        chain.doFilter(request, response);
++    }
++
++    public void destroy() {
++    }
++}
+Index: src/main/resources/conf/felix-config.properties
+===================================================================
+--- src/main/resources/conf/felix-config.properties    (revision 564)
++++ src/main/resources/conf/felix-config.properties    (working copy)
+@@ -110,6 +110,7 @@
+           
reference:file:amdatu-application/org.amdatu.authorization.login.service-${platform.version}.jar
 \
+           
reference:file:amdatu-application/org.amdatu.authorization.useradmin.gadget-${platform.version}.jar
 \
+           
reference:file:amdatu-application/org.amdatu.authorization.useradmin.rest-${platform.version}.jar
 \
++          
reference:file:amdatu-application/org.amdatu.authentication.contextmanager-${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
 \

Reply via email to