Author: ivol37 at gmail.com
Date: Tue Nov 30 17:45:08 2010
New Revision: 455

Log:
[AMDATU-189] Replaced dependency on filebasedconfiguration bundle by explicitly 
setting the configs in the integration test themselves.
Also fixed a concurrency issue between onAdded/destroy in the 
ResourceProviderListener

Added:
   
trunk/integration-tests/src/test/java/org/amdatu/test/integration/base/ConfigProvider.java
Modified:
   
trunk/amdatu-authorization/login-gadget/src/main/resources/jsp/LoginGadget.jsp
   
trunk/amdatu-core/config-templates/src/main/java/org/amdatu/core/config/templates/ConfigTemplateManager.java
   
trunk/amdatu-core/config-templates/src/main/java/org/amdatu/core/config/templates/service/ConfigTemplateManagerImpl.java
   
trunk/amdatu-core/loghandler/src/main/java/org/amdatu/core/loghandler/service/ConsoleLogHandler.java
   
trunk/amdatu-core/tenant/src/main/java/org/amdatu/core/tenant/TenantStorageProvider.java
   
trunk/amdatu-core/tenantstore-fs/src/main/java/org/amdatu/core/tenantstore/fs/service/FSTenantStorageProvider.java
   
trunk/amdatu-opensocial/shindig/src/main/java/org/amdatu/opensocial/shindig/ShindigService.java
   
trunk/amdatu-opensocial/shindig/src/main/java/org/amdatu/opensocial/shindig/osgi/Activator.java
   
trunk/amdatu-web/jsp/src/main/java/org/amdatu/web/jsp/service/ResourceProviderJspServlet.java
   
trunk/amdatu-web/jsp/src/main/java/org/amdatu/web/jsp/service/ResourceProviderListener.java
   
trunk/integration-tests/src/test/java/org/amdatu/test/integration/base/IntegrationTestBase.java
   
trunk/integration-tests/src/test/java/org/amdatu/test/integration/tests/CassandraDaemonIntegrationTest.java
   
trunk/integration-tests/src/test/java/org/amdatu/test/integration/tests/CassandraPersistenceManagerTest.java
   
trunk/integration-tests/src/test/java/org/amdatu/test/integration/tests/FSTenantStorageProviderServiceTest.java
   
trunk/integration-tests/src/test/java/org/amdatu/test/integration/tests/GadgetManagementServiceTest.java
   
trunk/integration-tests/src/test/java/org/amdatu/test/integration/tests/HttpServiceTest.java
   
trunk/integration-tests/src/test/java/org/amdatu/test/integration/tests/TenantManagementServiceTest.java
   
trunk/integration-tests/src/test/java/org/amdatu/test/integration/tests/UserAdminStoreTest.java

Modified: 
trunk/amdatu-authorization/login-gadget/src/main/resources/jsp/LoginGadget.jsp
==============================================================================
--- 
trunk/amdatu-authorization/login-gadget/src/main/resources/jsp/LoginGadget.jsp  
    (original)
+++ 
trunk/amdatu-authorization/login-gadget/src/main/resources/jsp/LoginGadget.jsp  
    Tue Nov 30 17:45:08 2010
@@ -27,12 +27,12 @@
 
 <Module>
   <ModulePrefs 
-       title="Amdatu Login Gadget" 
-       description="Provides login/logout functionality for Amdatu users"
-       author="Ivo Ladage-van Doorn"
-       screenshot="${gadgetBaseUrl}/static/images/login.png"
-       icon="${gadgetBaseUrl}/static/images/login.png" 
-       height="400">
+    title="Amdatu Login Gadget" 
+    description="Provides login/logout functionality for Amdatu users"
+    author="Ivo Ladage-van Doorn"
+    screenshot="${gadgetBaseUrl}/static/images/login.png"
+    icon="${gadgetBaseUrl}/static/images/login.png" 
+    height="400">
     <Require feature="osapi"/>       
     <Require feature="dynamic-height"/>     
   </ModulePrefs>
@@ -41,140 +41,143 @@
     <link rel="stylesheet" href="/dashboard/static/css/dashboard.css">
     
     <script type="text/javascript" 
src="/dashboard/static/js/lib/jquery-1.4.2.min.js"></script>
-       <script type="text/javascript" 
src="/dashboard/static/js/lib/jquery-ui-1.8.2.custom.min.js"></script>
+    <script type="text/javascript" 
src="/dashboard/static/js/lib/jquery-ui-1.8.2.custom.min.js"></script>
   
+    <div id="login" style="display:none;visibility:hidden">
+      <p>
+        You are currently not logged in<br/><br/>
+
+        <table width="95%">
+          <tr>
+            <td>Username</td><td><input type="edit" id="username" 
value="Administrator" onKeyPress="return submitenter(this, event)"/></td>
+          </tr>
+          <tr>
+            <td>Password</td><td><input type="password" id="password" 
value="Administrator" onKeyPress="return submitenter(this, event)"/></td>
+          </tr>
+          <tr>
+            <td><input type="submit" value="Login" 
onclick="javascript:login()" /></td><td/>
+          </tr>
+          <tr><td colspan="2"><font color="red"><div 
id="result"></div></font></td></tr>
+        </table>
+      </p>
+    </div>
+    <div id="logout" style="display:none;visibility:hidden"></div>
+    
     <script type="text/javascript">
       function showLoginBox() {
-       document.getElementById("login").style.visibility = "";
-       document.getElementById("login").style.display = "";
-                               
document.getElementById("logout").style.visibility = "hidden";
-                               document.getElementById("logout").style.display 
= "none";
+      alert('show login');
+        document.getElementById("login").style.visibility = "";
+        document.getElementById("login").style.display = "";
+        document.getElementById("logout").style.visibility = "hidden";
+        document.getElementById("logout").style.display = "none";
       }
       
       function showLogoutBox(username) {
-       document.getElementById("login").style.visibility = "hidden";
-       document.getElementById("login").style.display = "none";
-                               
document.getElementById("logout").style.visibility = "";
-                               document.getElementById("logout").style.display 
= "";
-                               var userdiv = document.getElementById("logout");
-                               userdiv.innerHTML = "<p>You are currently 
logged in as " + username + "<br/><br/>" +
-                                       "<input type='submit' value='Logout' 
onclick='javascript:logout()' /></p>";
+      alert('show logout');
+        document.getElementById("login").style.visibility = "hidden";
+        document.getElementById("login").style.display = "none";
+        document.getElementById("logout").style.visibility = "";
+        document.getElementById("logout").style.display = "";
+        var userdiv = document.getElementById("logout");
+        userdiv.innerHTML = "<p>You are currently logged in as " + username + 
"<br/><br/>" +
+          "<input type='submit' value='Logout' onclick='javascript:logout()' 
/></p>";
       }
       
       function login() {
-                               var postdata = {
-                                       username : 
document.getElementById('username').value,
-                                       password : 
document.getElementById('password').value
+        var postdata = {
+          username : document.getElementById('username').value,
+          password : document.getElementById('password').value
         };
-                                                       
-                               var url = "${baseRestUrl}/login";
-                               jQuery.ajax({
-                                       url: url,
-                                       type: "POST",
-                                       data: postdata,
-                                       dataType: "json",
-                                       async:true,
-                                       success: function(response) {
-                                                       if (response.result != 
null && response.result == 'ok') {
-                                                               
showLogoutBox(response.username);
-                                                       } else {
-                                                               var errorMsg = 
"An unexpected error occurred";
-                                                               if 
(response.msg) {
-                                                                       
errorMsg = response.msg;
-                                                               }
-                                                               var resultDiv = 
document.getElementById("result");
-                                                               
resultDiv.innerHTML = errorMsg;
-                                                       }
-                                               }
-                                       }
-                               );                              
+              
+        var url = "${baseRestUrl}/login";
+        jQuery.ajax({
+          url: url,
+          type: "POST",
+          data: postdata,
+          dataType: "json",
+          async:true,
+          success: function(response) {
+              if (response.result != null && response.result == 'ok') {
+                showLogoutBox(response.username);
+              } else {
+                var errorMsg = "An unexpected error occurred";
+                if (response.msg) {
+                  errorMsg = response.msg;
+                }
+                var resultDiv = document.getElementById("result");
+                resultDiv.innerHTML = errorMsg;
+              }
+            }
+          }
+        );        
       }
       
       function logout() {
-                               var postdata = {
-                                       username : 
document.getElementById('username').value,
-                                       password : 
document.getElementById('password').value
+        var postdata = {
+          username : document.getElementById('username').value,
+          password : document.getElementById('password').value
         };
-                                                       
-                               var url = "${baseRestUrl}/logout";
-                               jQuery.ajax({
-                                       url: url,
-                                       type: "POST",
-                                       data: postdata,
-                                       dataType: "json",
-                                       async:true,
-                                       success: function(response) {
-                                                       if (response.result != 
null && response.result == 'ok') {
-                                                               showLoginBox();
-                                                       } else {
-                                                               var errorMsg = 
"An unexpected error occurred";
-                                                               var resultDiv = 
document.getElementById("result");
-                                                               
resultDiv.innerHTML = errorMsg;
-                                                       }
-                                               }
-                                       }
-                               );                                      
-      }
-      
-                       function getLoginStatus() {
-                               var url = "${baseRestUrl}/status";
-                               jQuery.ajax({
-                                       url: url,
-                                       type: "GET",
-                                       dataType: "json",
-                                       async:true,
-                                       success: function(response) {
-                                                       if (response.username 
!= null) {
-                                                               
showLogoutBox(response.username);
-                                                       } else {
-                                                               showLoginBox();
-                                                       }
-                                               }
-                                       }
-                               );      
-                       }
-                       
-                       function submitenter(field, e) {
-                               var keycode;
-                               if (window.event) {
-                                 keycode = window.event.keyCode;
-                               } else if (e) {
-                                 keycode = e.which;
-                               } else {
-                                 return true;
-                         }
-                         
-                               if (keycode == 13) {
-                               login();
-                               return false;
-                         } else {
-                           return true;
-                         }
-                       }
-                       
-                       getLoginStatus();
+              
+        var url = "${baseRestUrl}/logout";
+        jQuery.ajax({
+          url: url,
+          type: "POST",
+          data: postdata,
+          dataType: "json",
+          async:true,
+          success: function(response) {
+              if (response.result != null && response.result == 'ok') {
+                showLoginBox();
+              } else {
+                var errorMsg = "An unexpected error occurred";
+                var resultDiv = document.getElementById("result");
+                resultDiv.innerHTML = errorMsg;
+              }
+            }
+          }
+        );          
+      }
+      
+      function getLoginStatus() {
+        var url = "${baseRestUrl}/status";
+        jQuery.ajax({
+          url: url,
+          type: "GET",
+          dataType: "json",
+          async:true,
+          success: function(response) {
+              if (response.username != null) {
+                showLogoutBox(response.username);
+              } else {
+                showLoginBox();
+              }
+            }
+          }
+        );  
+      }
+      
+      function submitenter(field, e) {
+        var keycode;
+        if (window.event) {
+          keycode = window.event.keyCode;
+        } else if (e) {
+          keycode = e.which;
+        } else {
+          return true;
+        }
+        
+        if (keycode == 13) {
+          login();
+          return false;
+        } else {
+          return true;
+        }
+      }
+      
+      getLoginStatus();
     </script>
     
-    <div id="login" style="display:none;visibility:hidden">
-                       <p>
-                               You are currently not logged in<br/><br/>
-                               
-                               <table width="95%">
-                                       <tr>
-                                               <td>Username</td><td><input 
type="edit" id="username" value="Administrator" onKeyPress="return 
submitenter(this, event)"/></td>
-                                       </tr>
-                                       <tr>
-                                               <td>Password</td><td><input 
type="password" id="password" value="Administrator" onKeyPress="return 
submitenter(this, event)"/></td>
-                                       </tr>
-                                       <tr>
-                                               <td><input type="submit" 
value="Login" onclick="javascript:login()" /></td><td/>
-                                       </tr>
-                                       <tr><td colspan="2"><font 
color="red"><div id="result"></div></font></td></tr>
-                               </table>
-                       </p>
-               </div>
-               <div id="logout" style="display:none;visibility:hidden">
-               </div>
+
     ]]>
   </Content>
 </Module>

Modified: 
trunk/amdatu-core/config-templates/src/main/java/org/amdatu/core/config/templates/ConfigTemplateManager.java
==============================================================================
--- 
trunk/amdatu-core/config-templates/src/main/java/org/amdatu/core/config/templates/ConfigTemplateManager.java
        (original)
+++ 
trunk/amdatu-core/config-templates/src/main/java/org/amdatu/core/config/templates/ConfigTemplateManager.java
        Tue Nov 30 17:45:08 2010
@@ -32,6 +32,11 @@
  */
 public interface ConfigTemplateManager {
     /**
+     * The PID of the configuration of this bundle.
+     */
+    public final static String PID = 
ConfigTemplateManager.class.getPackage().getName();
+    
+    /**
      * Replaces all occurrences of configuration entries in the plain text 
file pointed to 
      * by the given URL with the value of these entries from the 
ConfigAdminService and returns
      * a new URL with the replacements.

Modified: 
trunk/amdatu-core/config-templates/src/main/java/org/amdatu/core/config/templates/service/ConfigTemplateManagerImpl.java
==============================================================================
--- 
trunk/amdatu-core/config-templates/src/main/java/org/amdatu/core/config/templates/service/ConfigTemplateManagerImpl.java
    (original)
+++ 
trunk/amdatu-core/config-templates/src/main/java/org/amdatu/core/config/templates/service/ConfigTemplateManagerImpl.java
    Tue Nov 30 17:45:08 2010
@@ -47,9 +47,6 @@
     // Regular expression to match configuration entries. Syntax: 
${[pid].[configentry]}
     private static final Pattern CONFIG_ENTRY_REGEX = 
Pattern.compile("\\$\\{([A-Za-z0-9\\.-])+/([A-Za-z0-9\\.-])+\\}");
 
-    // The PID of the configuration of this bundle
-    public final static String PID = 
ConfigTemplateManager.class.getPackage().getName();
-
     // Services injected by the Felix dependency manager
     private volatile LogService m_logService;
     private volatile ConfigurationAdmin m_configurationAdmin;

Modified: 
trunk/amdatu-core/loghandler/src/main/java/org/amdatu/core/loghandler/service/ConsoleLogHandler.java
==============================================================================
--- 
trunk/amdatu-core/loghandler/src/main/java/org/amdatu/core/loghandler/service/ConsoleLogHandler.java
        (original)
+++ 
trunk/amdatu-core/loghandler/src/main/java/org/amdatu/core/loghandler/service/ConsoleLogHandler.java
        Tue Nov 30 17:45:08 2010
@@ -32,7 +32,7 @@
  * @author ivol
  */
 public class ConsoleLogHandler implements LogListener, ManagedService {
-    private static int DEFAULT_LOG_LEVEL = LogService.LOG_INFO;
+    private static int DEFAULT_LOG_LEVEL = LogService.LOG_DEBUG;
     private int m_minLogLevel = DEFAULT_LOG_LEVEL;
 
     private static final Map<Integer, String> LOG_LEVELS;

Modified: 
trunk/amdatu-core/tenant/src/main/java/org/amdatu/core/tenant/TenantStorageProvider.java
==============================================================================
--- 
trunk/amdatu-core/tenant/src/main/java/org/amdatu/core/tenant/TenantStorageProvider.java
    (original)
+++ 
trunk/amdatu-core/tenant/src/main/java/org/amdatu/core/tenant/TenantStorageProvider.java
    Tue Nov 30 17:45:08 2010
@@ -27,6 +27,16 @@
  */
 public interface TenantStorageProvider {
     /**
+     * The PID of the configuration of this bundle.
+     */
+    public static final String CONFIGURATION_PID = 
"org.amdatu.core.tenantstore-fs";
+    
+    /**
+     * The configuration entry of this bundle that provides the storage 
directory.
+     */
+    public final static String DATA_DIRECTORY = "datadir";
+    
+    /**
      * Stores a tenant. If a tenant with this ID already exists, update it.
      */
     void store(TenantEntity tenant) throws TenantStorageException;

Modified: 
trunk/amdatu-core/tenantstore-fs/src/main/java/org/amdatu/core/tenantstore/fs/service/FSTenantStorageProvider.java
==============================================================================
--- 
trunk/amdatu-core/tenantstore-fs/src/main/java/org/amdatu/core/tenantstore/fs/service/FSTenantStorageProvider.java
  (original)
+++ 
trunk/amdatu-core/tenantstore-fs/src/main/java/org/amdatu/core/tenantstore/fs/service/FSTenantStorageProvider.java
  Tue Nov 30 17:45:08 2010
@@ -33,11 +33,6 @@
  * Filesystem backed implementation of the <code>TenantStorageProvider</code> 
service interface.
  */
 public class FSTenantStorageProvider implements TenantStorageProvider {
-
-    // The PID and configuration properties
-    public static final String CONFIGURATION_PID = 
"org.amdatu.core.tenantstore-fs";
-    public final static String DATA_DIRECTORY = "datadir";
-
     // File naming constants
     private static final String ENTITYLIST_FILENAME = "tenantIdList.ser";
     private static final String STORAGEFILE_PREFIX = "t_";

Modified: 
trunk/amdatu-opensocial/shindig/src/main/java/org/amdatu/opensocial/shindig/ShindigService.java
==============================================================================
--- 
trunk/amdatu-opensocial/shindig/src/main/java/org/amdatu/opensocial/shindig/ShindigService.java
     (original)
+++ 
trunk/amdatu-opensocial/shindig/src/main/java/org/amdatu/opensocial/shindig/ShindigService.java
     Tue Nov 30 17:45:08 2010
@@ -23,4 +23,8 @@
  * @author ivol
  */
 public interface ShindigService {
+    /**
+     * The PID for Shindig specific configuration properties.
+     */
+    public final static String SHINDIG_CONFIG_PID = 
"org.amdatu.opensocial.shindig";
 }

Modified: 
trunk/amdatu-opensocial/shindig/src/main/java/org/amdatu/opensocial/shindig/osgi/Activator.java
==============================================================================
--- 
trunk/amdatu-opensocial/shindig/src/main/java/org/amdatu/opensocial/shindig/osgi/Activator.java
     (original)
+++ 
trunk/amdatu-opensocial/shindig/src/main/java/org/amdatu/opensocial/shindig/osgi/Activator.java
     Tue Nov 30 17:45:08 2010
@@ -53,10 +53,7 @@
     // The resource identifier for this bundle. Resources are only considered 
to be 'ours' when
     // it is prefixed with this id. Do not not append "/" at the beginning or 
end of the identifier.
     public final static String RESOURCE_ID = "gadgets";
-    
-    // The PID for Shindig specific configuration properties
-    public final static String SHINDIG_CONFIG_PID = 
"org.amdatu.opensocial.shindig";
-    
+        
     @Override
     public void init(BundleContext context, DependencyManager manager) throws 
Exception {
         // First define a service that provides the Gadget ColumnFamily we need
@@ -113,7 +110,7 @@
                 createComponent()
                 .setInterface(ConfigurationAdminGuiceModule.class.getName(), 
null)
                 .setImplementation(ConfigurationAdminGuiceModule.class)
-                
.add(createConfigurationDependency().setPid(SHINDIG_CONFIG_PID).setPropagate(true)));
+                
.add(createConfigurationDependency().setPid(ShindigService.SHINDIG_CONFIG_PID).setPropagate(true)));
         
         // Create the Guice injector servlet
         manager.add(
@@ -123,7 +120,7 @@
                 
.add(createServiceDependency().setService(LogService.class).setRequired(true))
                 
.add(createServiceDependency().setService(SocialApiModule.class).setRequired(true))
                 
.add(createServiceDependency().setService(OAuthModule.class).setRequired(true))
-                
.add(createServiceDependency().setService(ConfigurationAdminGuiceModule.class, 
"("+ Constants.SERVICE_PID + "=" + SHINDIG_CONFIG_PID + ")")
+                
.add(createServiceDependency().setService(ConfigurationAdminGuiceModule.class, 
"("+ Constants.SERVICE_PID + "=" + ShindigService.SHINDIG_CONFIG_PID + ")")
                         .setRequired(true)));
         
         // Register the Shindig registration service
@@ -136,7 +133,7 @@
                 
.add(createServiceDependency().setService(SocialApiModule.class).setRequired(true))
                 
.add(createServiceDependency().setService(OAuthModule.class).setRequired(true))
                 .add(createServiceDependency()
-                        .setService(ConfigurationAdminGuiceModule.class, "("+ 
Constants.SERVICE_PID + "=" + SHINDIG_CONFIG_PID + ")")
+                        .setService(ConfigurationAdminGuiceModule.class, "("+ 
Constants.SERVICE_PID + "=" + ShindigService.SHINDIG_CONFIG_PID + ")")
                         .setRequired(true))
                 
.add(createServiceDependency().setService(HttpContextServiceFactory.class).setRequired(true))
                 
.add(createServiceDependency().setService(HttpService.class).setRequired(true)));

Modified: 
trunk/amdatu-web/jsp/src/main/java/org/amdatu/web/jsp/service/ResourceProviderJspServlet.java
==============================================================================
--- 
trunk/amdatu-web/jsp/src/main/java/org/amdatu/web/jsp/service/ResourceProviderJspServlet.java
       (original)
+++ 
trunk/amdatu-web/jsp/src/main/java/org/amdatu/web/jsp/service/ResourceProviderJspServlet.java
       Tue Nov 30 17:45:08 2010
@@ -183,6 +183,7 @@
                 new Callable<Void>() {
                 public Void call() throws Exception {
                     m_jasperServlet.destroy();
+                    m_logService.log(LogService.LOG_ERROR, "JSP servlet for " 
+ getResourceProvider().getResourceId() + " destroyed");
                     return null;
                 }
             }

Modified: 
trunk/amdatu-web/jsp/src/main/java/org/amdatu/web/jsp/service/ResourceProviderListener.java
==============================================================================
--- 
trunk/amdatu-web/jsp/src/main/java/org/amdatu/web/jsp/service/ResourceProviderListener.java
 (original)
+++ 
trunk/amdatu-web/jsp/src/main/java/org/amdatu/web/jsp/service/ResourceProviderListener.java
 Tue Nov 30 17:45:08 2010
@@ -23,6 +23,8 @@
 import java.util.Hashtable;
 import java.util.List;
 import java.util.Map;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
+import java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock;
 
 import javax.servlet.ServletException;
 
@@ -31,6 +33,7 @@
 import org.amdatu.web.jsp.osgi.Activator;
 import org.apache.felix.dm.Component;
 import org.apache.felix.dm.DependencyManager;
+import org.osgi.framework.Bundle;
 import org.osgi.framework.BundleContext;
 import org.osgi.service.http.HttpContext;
 import org.osgi.service.http.HttpService;
@@ -44,16 +47,16 @@
  * @author ivol
  */
 public class ResourceProviderListener implements ResourceProvider {
-    //The serial version UID of this servlet.
+    // The serial version UID of this servlet.
     private static final long serialVersionUID = 7506277600212824000L;
-    
+
     // The file name extensions that are assumed to be JSPs
     private final static List<String> JSP_EXTENSIONS = new ArrayList<String>();
     static {
         JSP_EXTENSIONS.add(".jsp");
         JSP_EXTENSIONS.add(".jspf");
     }
-    
+
     // This path is appended to the ResourceProvider's resourceId defines the 
servlet alias
     // used to register the JSP servlet.
     private final static String JSP_SERVLET_PATH = "jsp";
@@ -72,6 +75,10 @@
     List<ResourceProvider> m_resourceProviders = new 
ArrayList<ResourceProvider>();
     Map<String, Component> m_components = new HashMap<String, Component>();
 
+    // This lock prevents concurrency issues caused by onAdded callback method 
being invoked during service destruction
+    // (so onAdded and destroy are invoked concurrently).
+    ReentrantReadWriteLock m_destructionLock = new ReentrantReadWriteLock();
+
     public void init() {
         // Create our own http context and register resources
         m_httpContextComponent = 
m_httpContextFactoryService.create(m_bundleContext, this);
@@ -79,55 +86,80 @@
     }
 
     public void destroy() {
-        m_httpContextComponent.stop();
+        // When this service itself is stopped for any reason, onRemoved will 
not be invoked on the providers
+        // and the corresponding JSP servlet would not be unregistered, 
resulting in a 'alias already in use'
+        // error upon starting this service. Therefore we explicitly invoke 
onRemoved on all available
+        // resource providers ourselves here
+        // First retrieve a write destruction lock, to prevent new resource 
providers to be registered during destruction.
+        WriteLock destructionLock = m_destructionLock.writeLock();
+        destructionLock.lock();
+        try {
+            while (m_resourceProviders.size() > 0) {
+                onRemoved(m_resourceProviders.get(0));
+            }
+            m_httpContextComponent.stop();
+        } finally {
+            destructionLock.unlock();
+        }
     }
 
     // This callback is invoked for each ResourceProvider that comes available
     public void onAdded(ResourceProvider provider) {
-        Dictionary<String, String> initParams = new Hashtable<String, 
String>();
-        String servletAlias = getServletAlias(provider);
-
-        // Instantiate new ResourceProviderJspServlet service
-        ResourceProviderJspServlet jspServlet = new 
ResourceProviderJspServlet(provider);
-        Component component = m_dependencyManager.createComponent();
-        component.setImplementation(jspServlet);
-
-        // Add service dependencies
-        
component.add(m_dependencyManager.createServiceDependency().setService(LogService.class).setRequired(true));
-
-        // Add the component to the dependency manager
-        m_components.put(normalizeResourceId(provider), component);
-        m_dependencyManager.add(component);
-
+        WriteLock destructionLock = m_destructionLock.writeLock();
+        destructionLock.lock();
         try {
-            m_httpService.registerServlet(servletAlias, jspServlet, 
initParams, m_httpContext);
-            m_logService.log(LogService.LOG_DEBUG, "JSP servlet registered for 
resource provider " + provider);
-        }
-        catch (ServletException e) {
-            m_logService.log(LogService.LOG_ERROR, "Could not register JSP 
servlet for resource provider " + provider,
-                e);
-            return;
-        }
-        catch (NamespaceException e) {
-            m_logService.log(LogService.LOG_ERROR, "Could not register JSP 
servlet for resource provider " + provider,
-                e);
-            return;
+            // After retrieving the destruction lock, be sure the bundle is 
not being stopped (we might have been waiting for 
+            // the destruction lock to be released by the destroy() method)
+            if (m_bundleContext.getBundle().getState() == Bundle.ACTIVE) {
+                Dictionary<String, String> initParams = new Hashtable<String, 
String>();
+                String servletAlias = getServletAlias(provider);
+
+                // Instantiate new ResourceProviderJspServlet service
+                ResourceProviderJspServlet jspServlet = new 
ResourceProviderJspServlet(provider);
+                Component component = m_dependencyManager.createComponent();
+                component.setImplementation(jspServlet);
+
+                // Add service dependencies
+                
component.add(m_dependencyManager.createServiceDependency().setService(LogService.class).setRequired(true));
+
+                // Add the component to the dependency manager
+                m_components.put(normalizeResourceId(provider), component);
+                m_dependencyManager.add(component);
+
+                try {
+                    m_httpService.registerServlet(servletAlias, jspServlet, 
initParams, m_httpContext);
+                    m_resourceProviders.add(provider);
+
+                }
+                catch (ServletException e) {
+                    m_logService.log(LogService.LOG_ERROR, "Could not register 
JSP servlet on alias '" + servletAlias
+                        + "' for resource provider " + provider, e);
+                    return;
+                }
+                catch (NamespaceException e) {
+                    m_logService.log(LogService.LOG_ERROR, "Could not register 
JSP servlet on alias '" + servletAlias
+                        + "' for resource provider " + 
provider.getResourceId(), e);
+                    return;
+                }
+            }
+        } finally {
+            destructionLock.unlock();
         }
-        m_resourceProviders.add(provider);
     }
 
     // This callback is invoked for each ResourceProvider that becomes 
unavailable
     public void onRemoved(ResourceProvider provider) {
         try {
-            m_httpService.unregister(getServletAlias(provider));
+            String alias = getServletAlias(provider);
+            m_httpService.unregister(alias);
             
m_dependencyManager.remove(m_components.get(normalizeResourceId(provider)));
-            m_logService.log(LogService.LOG_DEBUG, "JSP servlet unregistered 
for resource provider " + provider);
         }
         finally {
             m_resourceProviders.remove(provider);
         }
+        m_logService.log(LogService.LOG_DEBUG, "JSP servlet removed for 
resource provider " + provider.getResourceId());
     }
-    
+
     // Returns the resource Id trimming leading and ending slashes
     private String normalizeResourceId(ResourceProvider provider) {
         String resId = provider.getResourceId();
@@ -135,7 +167,7 @@
             resId = resId.substring(1);
         }
         if (resId.endsWith("/")) {
-            resId = resId.substring(0, provider.getResourceId().length()-1);
+            resId = resId.substring(0, provider.getResourceId().length() - 1);
         }
         return resId;
     }
@@ -157,7 +189,8 @@
                 String resource;
                 if (name.startsWith("/")) {
                     resource = name.substring(("/" + prefix + "/").length());
-                } else {
+                }
+                else {
                     resource = name.substring((prefix + "/").length());
                 }
                 URL url = provider.getResource(resource);
@@ -173,7 +206,7 @@
     public String getResourceId() {
         return Activator.RESOURCE_ID;
     }
-    
+
     private boolean isJsp(String name) {
         for (String extension : JSP_EXTENSIONS) {
             if (name.endsWith(extension)) {
@@ -182,7 +215,7 @@
         }
         return false;
     }
-    
+
     private String getJspServletPath(String name) {
         // Retrieves the Jsp servlet path from a full URL
         int endIndex = name.indexOf("/" + JSP_SERVLET_PATH + "/");

Added: 
trunk/integration-tests/src/test/java/org/amdatu/test/integration/base/ConfigProvider.java
==============================================================================
--- (empty file)
+++ 
trunk/integration-tests/src/test/java/org/amdatu/test/integration/base/ConfigProvider.java
  Tue Nov 30 17:45:08 2010
@@ -0,0 +1,172 @@
+/*
+ Copyright (C) 2010 Amdatu.org
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+package org.amdatu.test.integration.base;
+
+import java.io.IOException;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.util.Properties;
+
+import org.amdatu.cassandra.application.CassandraConfigurationService;
+import org.amdatu.core.config.templates.ConfigTemplateManager;
+import org.amdatu.core.tenant.TenantStorageProvider;
+import org.amdatu.opensocial.shindig.ShindigService;
+import org.osgi.service.cm.Configuration;
+import org.osgi.service.cm.ConfigurationAdmin;
+
+/**
+ * This class provides the configurations for the bundles under test.
+ * 
+ * @author ivol
+ */
+public class ConfigProvider {
+    public final static String HOSTNAME = "localhost";
+    public final static String PORTNR = "3737";
+    public final static String SECURE_PORTNR = "3738";
+
+    public void addCassandraConfig(ConfigurationAdmin configAdmin) throws 
IOException {
+        Configuration config = 
configAdmin.getConfiguration(CassandraConfigurationService.PID, null);
+        Properties properties = new Properties();
+        properties.put("workdir", "cassandra");
+        properties.put("commitlogdir", "work/cassandra/commitlog");
+        properties.put("datafiledir", "work/cassandra/data");
+        properties.put("savedcachesdir", "work/cassandra/saved_caches");
+        config.update(properties);
+    }
+
+    public void addTemplateConfig(ConfigurationAdmin configAdmin) throws 
IOException {
+        Configuration config = 
configAdmin.getConfiguration(ConfigTemplateManager.PID, null);
+        Properties properties = new Properties();
+        properties.put("workdir", "config-template-manager");
+        properties.put("hostname", "localhost");
+        properties.put("port", 3737);
+        config.update(properties);
+    }
+
+    public void addFSTenantStoreConfig(ConfigurationAdmin configAdmin) throws 
IOException {
+        Configuration config = 
configAdmin.getConfiguration(TenantStorageProvider.CONFIGURATION_PID, null);
+        Properties properties = new Properties();
+        properties.put(TenantStorageProvider.DATA_DIRECTORY, 
"work/tenantstore");
+        config.update(properties);
+    }
+
+    public void addShindigConfig(ConfigurationAdmin configAdmin) throws 
IOException {
+        Configuration config = 
configAdmin.getConfiguration(ShindigService.SHINDIG_CONFIG_PID, null);
+        Properties properties = new Properties();
+        properties.put("shindig.features.default", 
"res://features/features.txt");
+        properties.put("shindig.containers.default", 
"res://conf/container.js");
+        properties.put("shindig.blacklist.file", "");
+        properties.put("shindig.oauth.base-url", "/oauth/");
+        properties.put("shindig.oauth.authorize-action", 
"/dashboard/authorize.jsp");
+        properties.put("shindig.signing.state-key", "");
+        properties.put("shindig.signing.key-name", "amdatu_public_key");
+        properties.put("shindig.signing.global-callback-url", "http://"; + 
HOSTNAME + ":" + PORTNR
+            + "/gadgets/oauthcallback");
+        properties.put("shindig.signing.enable-signed-callbacks", "true");
+        properties.put("shindig.signing.viewer-access-tokens-enabled", 
"false");
+        properties.put("shindig.locked-domain.enabled", "false");
+        properties.put("shindig.content-rewrite.only-allow-excludes", "false");
+        properties.put("shindig.content-rewrite.include-urls", ".*");
+        properties.put("shindig.content-rewrite.exclude-urls", "");
+        properties.put("shindig.content-rewrite.include-tags", 
"body,embed,img,input,link,script,style");
+        properties.put("shindig.content-rewrite.expires", "86400");
+        properties.put("shindig.content-rewrite.proxy-url", 
"/gadgets/proxy?container=default&url=");
+        properties.put("shindig.content-rewrite.concat-url", 
"/gadgets/concat?container=default&");
+        properties.put("shindig.content-rewrite.enable-split-js-concat", 
"true");
+        properties.put("shindig.gadget-rewrite.default-forced-libs", 
"core:rpc");
+        properties.put("shindig.gadget-rewrite.externalize-feature-libs", 
"false");
+        properties.put("shindig.image-rewrite.max-inmem-bytes", "1048576");
+        properties.put("shindig.image-rewrite.max-palette-size", "256");
+        properties.put("shindig.image-rewrite.allow-jpeg-conversion", "true");
+        properties.put("shindig.image-rewrite.jpeg-compression", "0.75");
+        properties.put("shindig.image-rewrite.min-threshold-bytes", "200");
+        properties.put("shindig.flash.min-version", "9.0.115");
+        properties.put("shindig.template-rewrite.extension-tag-namespace", 
"http://ns.opensocial.org/2009/extensions";);
+        properties.put("shindig.cache.http.defaultTtl", "0");
+        properties.put("shindig.cache.http.negativeCacheTtl", "0");
+        properties.put("shindig.cache.xml.refreshInterval", "1");
+        properties.put("shindig.cache.lru.default.capacity", "1000");
+        properties.put("shindig.cache.lru.expressions.capacity", "1000");
+        properties.put("shindig.cache.lru.gadgetSpecs.capacity", "1000");
+        properties.put("shindig.cache.lru.messageBundles.capacity", "1000");
+        properties.put("shindig.cache.lru.httpResponses.capacity", "10000");
+        properties.put("shindig.cache.ehcache.config",
+            "res://org/apache/shindig/common/cache/ehcache/ehcacheConfig.xml");
+        properties.put("shindig.cache.ehcache.jmx.enabled", "true");
+        properties.put("shindig.cache.ehcache.jmx.stats", "true");
+        properties.put("shindig.http.fast-encoding-detection", "true");
+        properties.put("shindig.http.client.connection-timeout-ms", "15000");
+        properties.put("shindig.http.client.max-object-size-bytes", "0");
+        properties.put("shindig.uri.proxy.use-strict-parsing", "false");
+        properties.put("shindig.uri.concat.use-strict-parsing", "false");
+        
properties.put("org.apache.shindig.gadgets.http.basicHttpFetcherProxy", "");
+        properties.put("org.apache.shindig.serviceExpirationDurationMinutes", 
"60");
+        properties.put("shindig.json-rpc.result-field", "result");
+        properties.put("shindig.accelerate.remapInternalServerError", "true");
+        properties.put("shindig.host", HOSTNAME);
+        properties.put("shindig.port", PORTNR);
+        properties.put("shindig.proxy.remapInternalServerError", "false");
+        config.update(properties);
+    }
+
+    public void addHttpServiceConfig(ConfigurationAdmin configAdmin) throws 
IOException {
+        Configuration config = 
configAdmin.getConfiguration("org.apache.felix.http", null);
+        Properties properties = new Properties();
+        properties.put("org.osgi.service.http.hostname", HOSTNAME);
+        properties.put("org.osgi.service.http.port", PORTNR);
+        properties.put("org.osgi.service.http.port.secure", SECURE_PORTNR);
+        properties.put("org.apache.felix.http.debug", "true");
+        properties.put("org.apache.felix.log.storeDebug", "true");
+        config.update(properties);
+    }
+    
+    public void addUserAdminConfig(ConfigurationAdmin configAdmin) throws 
IOException {
+        Configuration config = 
configAdmin.getConfiguration("org.amdatu.core.useradminstore-fs", null);
+        Properties properties = new Properties();
+        properties.put(TenantStorageProvider.DATA_DIRECTORY, 
"work/useradminstore");
+        config.update(properties);
+    }
+
+    /**
+     * Wait until the service at the specified URL returns the specified 
response code with a timeout as specified.
+     */
+    public static boolean waitForURL(URL url, int responseCode, int timeout) {
+        long deadline = System.currentTimeMillis() + timeout;
+        while (System.currentTimeMillis() < deadline) {
+            try {
+                HttpURLConnection connection = (HttpURLConnection) 
url.openConnection();
+                connection.connect();
+                if (connection.getResponseCode() == responseCode) {
+                    return true;
+                }
+            }
+            catch (ClassCastException cce) {
+                throw new IllegalArgumentException("Expected url to be an HTTP 
url, not: " + url.toString(), cce);
+            }
+            catch (IOException ioe) {
+                // retry
+            }
+            try {
+                Thread.sleep(100);
+            }
+            catch (InterruptedException ie) {
+                return false;
+            }
+        }
+        return false;
+    }
+}

Modified: 
trunk/integration-tests/src/test/java/org/amdatu/test/integration/base/IntegrationTestBase.java
==============================================================================
--- 
trunk/integration-tests/src/test/java/org/amdatu/test/integration/base/IntegrationTestBase.java
     (original)
+++ 
trunk/integration-tests/src/test/java/org/amdatu/test/integration/base/IntegrationTestBase.java
     Tue Nov 30 17:45:08 2010
@@ -82,7 +82,7 @@
 
                 new VMOption("-Xmx1g"),
                 // Enable this line to allow a remote debugger to attach to 
the VM in which Pax Exam runs
-                // new 
VMOption("-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=5005"),
+                //new 
VMOption("-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=5005"),
 
                 // Install bundles we need to execute our test
                 provision(
@@ -96,8 +96,6 @@
                     // repository prior to running this integration test. With 
'mvn integration-test' however, artifacts will
                     // not be deployed and so this will only work when 
artifacts have been deployed to the maven repository
                     // before, possibly using outdated artifacts.
-                    fileBasedConfiguration(),
-                    amdatuConfigTemplateManager(),
                     amdatuLogHandler(),
 
                     // And finally deploy ourselves

Modified: 
trunk/integration-tests/src/test/java/org/amdatu/test/integration/tests/CassandraDaemonIntegrationTest.java
==============================================================================
--- 
trunk/integration-tests/src/test/java/org/amdatu/test/integration/tests/CassandraDaemonIntegrationTest.java
 (original)
+++ 
trunk/integration-tests/src/test/java/org/amdatu/test/integration/tests/CassandraDaemonIntegrationTest.java
 Tue Nov 30 17:45:08 2010
@@ -18,6 +18,7 @@
 
 import static org.ops4j.pax.exam.CoreOptions.provision;
 
+import java.io.IOException;
 import java.util.List;
 
 import junit.framework.Assert;
@@ -26,17 +27,21 @@
 import org.amdatu.cassandra.listener.ColumnFamilyDefinition.ColumnType;
 import org.amdatu.cassandra.listener.ColumnFamilyDefinition.CompareType;
 import org.amdatu.cassandra.persistencemanager.CassandraPersistenceManager;
+import org.amdatu.test.integration.base.ConfigProvider;
 import org.amdatu.test.integration.base.IntegrationTestBase;
 import org.apache.cassandra.db.Table;
 import org.apache.cassandra.thrift.InvalidRequestException;
 import org.apache.felix.dm.Component;
 import org.apache.felix.dm.DependencyManager;
 import org.junit.After;
+import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.ops4j.pax.exam.Option;
 import org.ops4j.pax.exam.junit.Configuration;
 import org.ops4j.pax.exam.junit.JUnit4TestRunner;
+import org.osgi.framework.BundleException;
+import org.osgi.service.cm.ConfigurationAdmin;
 
 /**
  * This class provides an integration test for the Cassandra Daemon service.
@@ -49,6 +54,7 @@
     private final static String COLUMNFAMILY = "IntegrationTestColumnFamily";
 
     private volatile CassandraDaemonService m_daemonService;
+    private volatile ConfigurationAdmin m_configAdmin;
 
     @Configuration
     public Option[] configure() {
@@ -59,6 +65,7 @@
         // Deploy bundles needed by cassandra daemon integration test
         return provision(
                javaxServlet(), // Required if the httpservice is not deployed
+               amdatuConfigTemplateManager(), // Required for placeholders in 
cassandra.yaml
             amdatuCassandraApplication(),
             amdatuCassandraListener(),
             amdatuCassandraPersistenceManager());
@@ -74,6 +81,7 @@
         return new Component[] { manager.createComponent()
             .setImplementation(this)
             
.add(manager.createServiceDependency().setService(CassandraDaemonService.class).setRequired(true))
+            
.add(manager.createServiceDependency().setService(ConfigurationAdmin.class).setRequired(true))
             
.add(manager.createServiceDependency().setService(CassandraPersistenceManager.class,
 filter).setRequired(true)) };
     }
 
@@ -92,11 +100,21 @@
             }
         }
     }
+    
+    @Before 
+    public void initConfig() throws IOException, BundleException {
+       m_configAdmin = getService(ConfigurationAdmin.class);
+       
+       // Add cassandra and templates configs
+       ConfigProvider configProvider = new ConfigProvider();
+       configProvider.addCassandraConfig(m_configAdmin);
+       configProvider.addTemplateConfig(m_configAdmin);
+    }
 
     @Test
     public void testCassandraDaemonService() throws Exception {
-        m_daemonService = getService(CassandraDaemonService.class);
-
+       m_daemonService = getService(CassandraDaemonService.class);
+       
         // -1- Test adding/updating/removing keyspaces
         int beforeCount = m_daemonService.getKeyspaces().size();
         m_daemonService.addKeyspace(KEYSPACE);

Modified: 
trunk/integration-tests/src/test/java/org/amdatu/test/integration/tests/CassandraPersistenceManagerTest.java
==============================================================================
--- 
trunk/integration-tests/src/test/java/org/amdatu/test/integration/tests/CassandraPersistenceManagerTest.java
        (original)
+++ 
trunk/integration-tests/src/test/java/org/amdatu/test/integration/tests/CassandraPersistenceManagerTest.java
        Tue Nov 30 17:45:08 2010
@@ -18,6 +18,7 @@
 
 import static org.ops4j.pax.exam.CoreOptions.provision;
 
+import java.io.IOException;
 import java.io.UnsupportedEncodingException;
 import java.util.Arrays;
 
@@ -29,16 +30,20 @@
 import org.amdatu.cassandra.persistencemanager.CassandraException;
 import org.amdatu.cassandra.persistencemanager.CassandraPersistenceManager;
 import 
org.amdatu.cassandra.persistencemanager.CassandraPersistenceManagerFactory;
+import org.amdatu.test.integration.base.ConfigProvider;
 import org.amdatu.test.integration.base.IntegrationTestBase;
 import org.apache.cassandra.db.Table;
 import org.apache.felix.dm.Component;
 import org.apache.felix.dm.DependencyManager;
 import org.junit.After;
+import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.ops4j.pax.exam.Option;
 import org.ops4j.pax.exam.junit.Configuration;
 import org.ops4j.pax.exam.junit.JUnit4TestRunner;
+import org.osgi.framework.BundleException;
+import org.osgi.service.cm.ConfigurationAdmin;
 
 /**
  * This class provides an integration test for the Cassandra Persistence 
Manager.
@@ -53,10 +58,11 @@
     private final static String DEFAULT_CHARSET = "UTF-8";
 
     // Services under test
-    private CassandraDaemonService m_daemonService;
-    private CassandraPersistenceManagerFactory m_pmFactory;
-    private CassandraPersistenceManager m_pm;
-
+    private volatile CassandraDaemonService m_daemonService;
+    private volatile CassandraPersistenceManagerFactory m_pmFactory;
+    private volatile CassandraPersistenceManager m_pm;
+    private volatile ConfigurationAdmin m_configAdmin;
+    
     @Configuration
     public Option[] configure() {
         return super.configure();
@@ -66,6 +72,7 @@
         // Deploy bundles needed by cassandra daemon integration test
         return provision(
                javaxServlet(), // Required if the httpservice is not deployed
+               amdatuConfigTemplateManager(), // Required for placeholders in 
cassandra.yaml
             amdatuCassandraApplication(),
             amdatuCassandraListener(),
             amdatuCassandraPersistenceManager());
@@ -81,8 +88,19 @@
         return new Component[] { manager.createComponent()
             .setImplementation(this)
             
.add(manager.createServiceDependency().setService(CassandraDaemonService.class).setRequired(true))
+            
.add(manager.createServiceDependency().setService(ConfigurationAdmin.class).setRequired(true))
             
.add(manager.createServiceDependency().setService(CassandraPersistenceManager.class,
 filter).setRequired(true)) };
     }
+    
+    @Before 
+    public void initConfig() throws IOException, BundleException {
+       m_configAdmin = getService(ConfigurationAdmin.class);
+       
+       // Add cassandra and templates configs
+       ConfigProvider configProvider = new ConfigProvider();
+       configProvider.addCassandraConfig(m_configAdmin);
+       configProvider.addTemplateConfig(m_configAdmin);
+    }
    
     public void setUp() throws Exception {
         m_daemonService = getService(CassandraDaemonService.class);

Modified: 
trunk/integration-tests/src/test/java/org/amdatu/test/integration/tests/FSTenantStorageProviderServiceTest.java
==============================================================================
--- 
trunk/integration-tests/src/test/java/org/amdatu/test/integration/tests/FSTenantStorageProviderServiceTest.java
     (original)
+++ 
trunk/integration-tests/src/test/java/org/amdatu/test/integration/tests/FSTenantStorageProviderServiceTest.java
     Tue Nov 30 17:45:08 2010
@@ -17,20 +17,27 @@
 package org.amdatu.test.integration.tests;
 
 import static org.ops4j.pax.exam.CoreOptions.provision;
+
+import java.io.IOException;
+
 import junit.framework.Assert;
 
 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.amdatu.test.integration.base.ConfigProvider;
 import org.amdatu.test.integration.base.IntegrationTestBase;
 import org.apache.felix.dm.Component;
 import org.apache.felix.dm.DependencyManager;
+import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.ops4j.pax.exam.Option;
 import org.ops4j.pax.exam.junit.Configuration;
 import org.ops4j.pax.exam.junit.JUnit4TestRunner;
+import org.osgi.framework.BundleException;
+import org.osgi.service.cm.ConfigurationAdmin;
 
 /**
  * This class provides an integration test for testing the Tenant FS storage
@@ -43,7 +50,8 @@
 
     private volatile TenantManagementService m_tenantManagementService;
     private volatile TenantStorageProvider m_tenantStorageProvider;
-
+    private volatile ConfigurationAdmin m_configAdmin;
+    
     @Configuration
     public Option[] configure() {
         return super.configure();
@@ -63,11 +71,23 @@
                 .setService(TenantManagementService.class)
                 .setRequired(true))
             .add(manager.createServiceDependency()
+               .setService(ConfigurationAdmin.class)
+               .setRequired(true))
+            .add(manager.createServiceDependency()
                 .setService(TenantStorageProvider.class)
                 .setRequired(true));
 
         return new Component[] { testComponent };
     }
+    
+    @Before 
+    public void initConfig() throws IOException, BundleException {
+       m_configAdmin = getService(ConfigurationAdmin.class);
+       
+       // Add cassandra and templates configs
+       ConfigProvider configProvider = new ConfigProvider();
+       configProvider.addFSTenantStoreConfig(m_configAdmin);
+    }
 
     @Test
     public void testBasicCRUDIntegration() throws TenantException, 
InterruptedException {

Modified: 
trunk/integration-tests/src/test/java/org/amdatu/test/integration/tests/GadgetManagementServiceTest.java
==============================================================================
--- 
trunk/integration-tests/src/test/java/org/amdatu/test/integration/tests/GadgetManagementServiceTest.java
    (original)
+++ 
trunk/integration-tests/src/test/java/org/amdatu/test/integration/tests/GadgetManagementServiceTest.java
    Tue Nov 30 17:45:08 2010
@@ -18,19 +18,25 @@
 
 import static org.ops4j.pax.exam.CoreOptions.provision;
 
+import java.io.IOException;
+
 import org.amdatu.opensocial.gadgetmanagement.GadgetManagement;
 import org.amdatu.opensocial.shindig.GadgetCategory;
 import org.amdatu.opensocial.shindig.GadgetDefinition;
 import org.amdatu.opensocial.shindig.ShindigService;
+import org.amdatu.test.integration.base.ConfigProvider;
 import org.amdatu.test.integration.base.IntegrationTestBase;
 import org.apache.felix.dm.Component;
 import org.apache.felix.dm.DependencyManager;
 import org.junit.Assert;
+import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.ops4j.pax.exam.Option;
 import org.ops4j.pax.exam.junit.Configuration;
 import org.ops4j.pax.exam.junit.JUnit4TestRunner;
+import org.osgi.framework.BundleException;
+import org.osgi.service.cm.ConfigurationAdmin;
 
 /**
  * This class provides an integration test for testing the User Admin store.
@@ -40,8 +46,9 @@
 @RunWith(JUnit4TestRunner.class)
 public class GadgetManagementServiceTest extends IntegrationTestBase {
  
-    private GadgetManagement m_gadgetManagementService;
-
+    private volatile GadgetManagement m_gadgetManagementService;
+    private volatile ConfigurationAdmin m_configAdmin;
+    
     @Configuration
     public Option[] configure() {
         return super.configure();
@@ -54,11 +61,13 @@
             // before this service finished initialization (since the 
integration test does not have a 
             // direct dependency on it) which would result in a failure upon 
shutdown (IllegalStateException).
             
.add(manager.createServiceDependency().setService(ShindigService.class).setRequired(true))
+            
.add(manager.createServiceDependency().setService(ConfigurationAdmin.class))
             
.add(manager.createServiceDependency().setService(GadgetManagement.class).setRequired(true))};
     }
     
     protected Option provisionBundles() {
         return provision(
+               amdatuConfigTemplateManager(), // Required for placeholders in 
cassandra.yaml
             amdatuCassandraApplication(),
             amdatuCassandraListener(),
             amdatuCassandraPersistenceManager(),
@@ -74,6 +83,17 @@
             amdatuGadgetManagement()
         );
     }
+    
+    @Before 
+    public void initConfig() throws IOException, BundleException {
+       m_configAdmin = getService(ConfigurationAdmin.class);
+       
+       // Add cassandra and templates configs
+       ConfigProvider configProvider = new ConfigProvider();
+       configProvider.addCassandraConfig(m_configAdmin);
+       configProvider.addTemplateConfig(m_configAdmin);
+       configProvider.addShindigConfig(m_configAdmin);
+    }
 
     @Test
     public void testCRUD() throws Exception {

Modified: 
trunk/integration-tests/src/test/java/org/amdatu/test/integration/tests/HttpServiceTest.java
==============================================================================
--- 
trunk/integration-tests/src/test/java/org/amdatu/test/integration/tests/HttpServiceTest.java
        (original)
+++ 
trunk/integration-tests/src/test/java/org/amdatu/test/integration/tests/HttpServiceTest.java
        Tue Nov 30 17:45:08 2010
@@ -35,6 +35,7 @@
 import javax.servlet.ServletResponse;
 import javax.servlet.http.HttpServletResponse;
 
+import org.amdatu.test.integration.base.ConfigProvider;
 import org.amdatu.test.integration.base.IntegrationTestBase;
 import org.amdatu.web.httpcontext.HttpContextServiceFactory;
 import org.amdatu.web.httpcontext.ResourceProvider;
@@ -46,13 +47,14 @@
 import org.apache.felix.dm.Component;
 import org.apache.felix.dm.DependencyManager;
 import org.junit.After;
+import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.ops4j.pax.exam.Option;
 import org.ops4j.pax.exam.junit.Configuration;
 import org.ops4j.pax.exam.junit.JUnit4TestRunner;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.ServiceReference;
+import org.osgi.framework.BundleException;
+import org.osgi.service.cm.ConfigurationAdmin;
 import org.osgi.service.http.HttpService;
 import org.osgi.service.log.LogService;
 
@@ -69,7 +71,7 @@
 
     private volatile LogService m_logService;
     private volatile HttpContextServiceFactory m_httpContextFactoryService;
-    private volatile BundleContext m_context;
+    private volatile ConfigurationAdmin m_configAdmin;
 
     private Component m_httpContextComponent;
     private String m_baseUrl;
@@ -123,11 +125,21 @@
                 
.add(manager.createServiceDependency().setService(TestFilterInterface.class).setRequired(true))
                 
.add(manager.createServiceDependency().setService(TestServletInterface.class).setRequired(true))
                 
.add(manager.createServiceDependency().setService(LogService.class).setRequired(true))
+                
.add(manager.createServiceDependency().setService(ConfigurationAdmin.class))
                 
.add(manager.createServiceDependency().setService(HttpContextServiceFactory.class).setRequired(true))
                 
.add(manager.createServiceDependency().setService(HttpService.class).setRequired(true));
 
         return new Component[] { filterComponent, servletComponent, 
testComponent };
     }
+    
+    @Before 
+    public void initConfig() throws IOException, BundleException {
+       m_configAdmin = getService(ConfigurationAdmin.class);
+       
+       // Add cassandra and templates configs
+       ConfigProvider configProvider = new ConfigProvider();
+       configProvider.addHttpServiceConfig(m_configAdmin);
+    }
 
     @After
     public void tearDown() throws Exception {
@@ -135,7 +147,7 @@
     }
 
     private void initialize() throws Exception {
-       m_baseUrl = "http://localhost:"; + getHttpPortNr();
+       m_baseUrl = "http://"; + ConfigProvider.HOSTNAME + ":" + 
ConfigProvider.PORTNR;
 
        // Initialize the HTTP Context in which the filter, servlet and JSP 
under test are registered
         m_httpContextComponent = 
m_httpContextFactoryService.create(m_bundleContext, m_testServlet);
@@ -144,6 +156,11 @@
     @Test
     public void testFilter() throws Exception {
        initialize();
+       
+       // Wait until the http service is available, for a maximum of 5 seconds
+        if (!ConfigProvider.waitForURL(new URL(m_baseUrl), 
HttpStatus.SC_NOT_FOUND, 5000)) {
+            throw new IllegalArgumentException("URL " + m_baseUrl + " is 
unreachable");
+        }
 
        // Wait for two seconds such that the Felix whiteboard service has the 
time to receive the filter added
        // callback and register it. See 
http://jira.amdatu.org/jira/browse/AMDATU-189
@@ -188,6 +205,11 @@
     public void testJsp() throws Exception {
        initialize();
 
+        // Wait until the http service is available, for a maximum of 5 seconds
+        if (!ConfigProvider.waitForURL(new URL(m_baseUrl), 
HttpStatus.SC_NOT_FOUND, 5000)) {
+            throw new IllegalArgumentException("URL " + m_baseUrl + " is 
unreachable");
+        }
+        
        // Wait for two seconds such that the Felix whiteboard service has the 
time to receive the filter added
        // callback and register it. See 
http://jira.amdatu.org/jira/browse/AMDATU-189
        Thread.sleep(2000);
@@ -215,19 +237,6 @@
         }
     }
 
-    public String getHttpPortNr() throws InterruptedException {
-        ServiceReference reference = 
m_context.getServiceReference(HttpService.class.getName());
-        int wait = 0;
-        while (reference.getProperty("org.osgi.service.http.port") == null && 
wait++ < 20) {
-            // We might be trying to get our references before the 
configuration is set; just wait
-            // around for a while.
-            Thread.sleep(100);
-        }
-        String portnr = (String) 
reference.getProperty("org.osgi.service.http.port");
-        m_logService.log(LogService.LOG_DEBUG, "Integration test is executed 
against port " + portnr);
-        return portnr;
-    }
-
     /**
      * A simple TestFilter that sets a header testFilterBefore to 'true' 
before executing the rest of
      * the filter chain and sets testFilterAfter to 'true' afterwards.

Modified: 
trunk/integration-tests/src/test/java/org/amdatu/test/integration/tests/TenantManagementServiceTest.java
==============================================================================
--- 
trunk/integration-tests/src/test/java/org/amdatu/test/integration/tests/TenantManagementServiceTest.java
    (original)
+++ 
trunk/integration-tests/src/test/java/org/amdatu/test/integration/tests/TenantManagementServiceTest.java
    Tue Nov 30 17:45:08 2010
@@ -20,29 +20,36 @@
 import static junit.framework.Assert.assertNull;
 import static org.ops4j.pax.exam.CoreOptions.provision;
 
+import java.io.IOException;
 import java.util.Properties;
 import java.util.concurrent.Semaphore;
 import java.util.concurrent.TimeUnit;
 
 import junit.framework.Assert;
 
+import org.amdatu.cassandra.persistencemanager.CassandraPersistenceManager;
 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.amdatu.test.integration.base.ConfigProvider;
 import org.amdatu.test.integration.base.IntegrationTestBase;
 import org.amdatu.test.integration.mock.InMemoryTenantStorageProvider;
 import org.apache.felix.dm.Component;
 import org.apache.felix.dm.DependencyManager;
+import org.junit.After;
+import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.ops4j.pax.exam.Option;
 import org.ops4j.pax.exam.junit.Configuration;
 import org.ops4j.pax.exam.junit.JUnit4TestRunner;
+import org.osgi.framework.BundleException;
 import org.osgi.framework.Constants;
 import org.osgi.framework.InvalidSyntaxException;
 import org.osgi.framework.ServiceReference;
+import org.osgi.service.cm.ConfigurationAdmin;
 
 /**
  * This class provides an integration test for testing the Tenant Management 
Service. We
@@ -55,7 +62,8 @@
 public class TenantManagementServiceTest extends IntegrationTestBase {
 
     private volatile TenantManagementService m_tenantManagementService;
-
+    private volatile ConfigurationAdmin m_configAdmin;
+    
     @Configuration
     public Option[] configure() {
         return super.configure();
@@ -64,6 +72,7 @@
     protected Option provisionBundles() {
         return provision(
                javaxServlet(), // Required if the httpservice is not deployed
+               amdatuConfigTemplateManager(), // Required for placeholders in 
cassandra.yaml
             amdatuCassandraApplication(),
             amdatuCassandraListener(),
             amdatuCassandraPersistenceManager(),
@@ -77,6 +86,13 @@
                 .setService(TenantManagementService.class)
                 .setRequired(true))
             .add(manager.createServiceDependency()
+                .setService(ConfigurationAdmin.class)
+                .setRequired(true))
+            // this dependency is necessary to prevent a shutdown before all 
bundles are started
+            .add(manager.createServiceDependency()
+                .setService(CassandraPersistenceManager.class)
+                .setRequired(true))
+            .add(manager.createServiceDependency()
                 .setService(Tenant.class)
                 .setCallbacks("tenantAdded", "tenantRemoved"));
 
@@ -92,6 +108,22 @@
     private final Semaphore m_tenant1Added = new Semaphore(0);
     private final Semaphore m_tenant1Removed = new Semaphore(0);
 
+    @Before 
+    public void initConfig() throws IOException, BundleException {
+        m_configAdmin = getService(ConfigurationAdmin.class);
+        
+        // Add cassandra and templates configs
+        ConfigProvider configProvider = new ConfigProvider();
+        configProvider.addCassandraConfig(m_configAdmin);
+        configProvider.addTemplateConfig(m_configAdmin);
+    }
+    
+    @After
+    public void after() throws InterruptedException {
+        // Give the framework 2 seconds time to be able to finalize startup 
before shutting down.
+        Thread.sleep(2000);
+    }
+    
     public void tenantAdded(ServiceReference reference) {
         if (reference.getProperty(Tenant.SERVICE_PREFIX + 
"id").equals("tenant1")) {
             m_tenant1Added.release();

Modified: 
trunk/integration-tests/src/test/java/org/amdatu/test/integration/tests/UserAdminStoreTest.java
==============================================================================
--- 
trunk/integration-tests/src/test/java/org/amdatu/test/integration/tests/UserAdminStoreTest.java
     (original)
+++ 
trunk/integration-tests/src/test/java/org/amdatu/test/integration/tests/UserAdminStoreTest.java
     Tue Nov 30 17:45:08 2010
@@ -19,7 +19,10 @@
 import static org.ops4j.pax.exam.CoreOptions.provision;
 import junit.framework.Assert;
 
+import org.amdatu.test.integration.base.ConfigProvider;
 import org.amdatu.test.integration.base.IntegrationTestBase;
+import org.apache.felix.dm.Component;
+import org.apache.felix.dm.DependencyManager;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -27,7 +30,7 @@
 import org.ops4j.pax.exam.Option;
 import org.ops4j.pax.exam.junit.Configuration;
 import org.ops4j.pax.exam.junit.JUnit4TestRunner;
-import org.osgi.framework.BundleContext;
+import org.osgi.service.cm.ConfigurationAdmin;
 import org.osgi.service.useradmin.Group;
 import org.osgi.service.useradmin.Role;
 import org.osgi.service.useradmin.User;
@@ -45,9 +48,8 @@
     private static int WAIT = 20;
 
     @Inject
-    protected BundleContext m_bundleContext;
-
-    private UserAdmin m_userAdmin;
+    private volatile ConfigurationAdmin m_configAdmin;
+    private volatile UserAdmin m_userAdmin;
 
     @Configuration
     public Option[] configure() {
@@ -56,15 +58,23 @@
 
     protected Option provisionBundles() {
         return provision(
-               javaxServlet(), // Required if the httpservice is not deployed
+            javaxServlet(), // Required if the httpservice is not deployed
+            amdatuConfigTemplateManager(), // Required for placeholders in 
cassandra.yaml
             amdatuHttpContext(), // needed by cassandra useradmin store
             amdatuJaxRs(), // needed by cassandra useradmin store
             amdatuCassandraApplication(),
             amdatuCassandraListener(),
             amdatuCassandraPersistenceManager(),
             paxUserAdmin(),
-            amdatuUserAdminCassandraStore()
-        );
+            amdatuUserAdminCassandraStore());
+    }
+
+    public Component[] getDependencies(DependencyManager manager) {
+        return new Component[] {
+            manager.createComponent().setImplementation(this)
+            
.add(manager.createServiceDependency().setService(ConfigurationAdmin.class).setRequired(true))
+            
.add(manager.createServiceDependency().setService(UserAdmin.class)) 
+        };
     }
 
     private void sleep() throws InterruptedException {
@@ -74,6 +84,13 @@
 
     @Before
     public void setUp() throws Exception {
+        m_configAdmin = getService(ConfigurationAdmin.class);
+
+        // Add cassandra and templates configs
+        ConfigProvider configProvider = new ConfigProvider();
+        configProvider.addCassandraConfig(m_configAdmin);
+        configProvider.addTemplateConfig(m_configAdmin);
+        
         m_userAdmin = getService(UserAdmin.class);
     }
 
@@ -111,7 +128,7 @@
         // Now see if we can find these users from credentials
         sleep();
         Assert
-            .assertTrue("TestAdmin user could not be found", 
m_userAdmin.getUser("name", "TestAdministrator") != null);
+        .assertTrue("TestAdmin user could not be found", 
m_userAdmin.getUser("name", "TestAdministrator") != null);
         Assert.assertTrue("TestEditor user could not be found", 
m_userAdmin.getUser("name", "TestEditor") != null);
         Assert.assertTrue("TestGuest user could not be found", 
m_userAdmin.getUser("name", "TestGuest") != null);
 
@@ -130,7 +147,7 @@
         adminUser.getProperties().remove("lastName");
         sleep();
         Assert.assertTrue("lastName not properly removed from property set", 
m_userAdmin.getUser("name",
-            "TestAdministrator").getProperties().get("lastName") == null);
+        "TestAdministrator").getProperties().get("lastName") == null);
 
         // Now create "Administrator", "Editor" and "Guest" group and do some 
assignments
         Group adminGroup = (Group) m_userAdmin.createRole("TestAdminUsers", 
Role.GROUP);
@@ -201,26 +218,26 @@
         Assert.assertTrue("Group '" + group + "' is unknown by UserAdmin", 
m_userAdmin.getRole(group) != null);
         int count =
             ((Group) m_userAdmin.getRole(group)).getMembers() != null ? 
((Group) m_userAdmin.getRole(group))
-            .getMembers().length : 0;
-        if (count != expected) {
-            Role[] members = ((Group) m_userAdmin.getRole(group)).getMembers();
-            String sMembers = toString(members);
-            Assert.assertTrue("Group '" + group + "' has " + count + " basic 
members. Expected: " + expected
-                + ". Members found: " + sMembers, false);
-        }
+                .getMembers().length : 0;
+                if (count != expected) {
+                    Role[] members = ((Group) 
m_userAdmin.getRole(group)).getMembers();
+                    String sMembers = toString(members);
+                    Assert.assertTrue("Group '" + group + "' has " + count + " 
basic members. Expected: " + expected
+                        + ". Members found: " + sMembers, false);
+                }
     }
 
     private void assertRequiredMemberCount(String group, int expected) {
         Assert.assertTrue("Group '" + group + "' is unknown by UserAdmin", 
m_userAdmin.getRole(group) != null);
         int count =
             ((Group) m_userAdmin.getRole(group)).getRequiredMembers() != null 
? ((Group) m_userAdmin.getRole(group))
-            .getRequiredMembers().length : 0;
-        if (count != expected) {
-            Role[] members = ((Group) 
m_userAdmin.getRole(group)).getRequiredMembers();
-            String sMembers = toString(members);
-            Assert.assertTrue("Group '" + group + "' has " + count + " 
required members. Expected: " + expected
-                + ". Members found: " + sMembers, false);
-        }
+                .getRequiredMembers().length : 0;
+                if (count != expected) {
+                    Role[] members = ((Group) 
m_userAdmin.getRole(group)).getRequiredMembers();
+                    String sMembers = toString(members);
+                    Assert.assertTrue("Group '" + group + "' has " + count + " 
required members. Expected: " + expected
+                        + ". Members found: " + sMembers, false);
+                }
     }
 
     private String toString(Role[] members) {

Reply via email to