Author: ivol37 at gmail.com
Date: Thu Nov  4 16:06:52 2010
New Revision: 248

Log:
[AMDATU-151] Implemented whiteboard style registration of filters. Also the 
infamous 'Thread.sleep' to wait for the availability of the Guice injector has 
been replaced by service dependency mechanism. Also shindig dependency is no 
longer needed during integration tests.

Added:
   
trunk/platform-bundles/shindig-application/src/main/java/org/amdatu/platform/shindig/application/service/GuiceInjectorService.java
   
trunk/platform-bundles/shindig-application/src/main/java/org/amdatu/platform/shindig/application/service/GuiceInjectorServiceImpl.java
   
trunk/platform-bundles/shindig-application/src/main/java/org/amdatu/platform/shindig/application/service/GuiceInjectorServlet.java
Modified:
   trunk/integration-tests/pom.xml
   
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/platform-bundles/httpcontext/pom.xml
   
trunk/platform-bundles/httpcontext/src/main/java/org/amdatu/platform/httpcontext/service/HttpContextFactoryServiceImpl.java
   
trunk/platform-bundles/shindig-application/src/main/java/org/amdatu/platform/shindig/application/osgi/Activator.java
   
trunk/platform-bundles/shindig-application/src/main/java/org/amdatu/platform/shindig/application/service/ShindigRegistrationServiceImpl.java
   trunk/src/main/resources/conf/felix-config.properties

Modified: trunk/integration-tests/pom.xml
==============================================================================
--- trunk/integration-tests/pom.xml     (original)
+++ trunk/integration-tests/pom.xml     Thu Nov  4 16:06:52 2010
@@ -128,7 +128,14 @@
       <version>${org.apache.felix.http.version}</version>
       <scope>test</scope>
       <type>bundle</type>
-    </dependency>    
+    </dependency>
+    <dependency>
+      <groupId>commons-httpclient</groupId>
+      <artifactId>commons-httpclient</artifactId>
+      <version>3.1</version>
+      <scope>compile</scope>
+    </dependency>
+    
   </dependencies>
   
   <build>

Modified: 
trunk/integration-tests/src/test/java/org/amdatu/test/integration/base/IntegrationTestBase.java
==============================================================================
--- 
trunk/integration-tests/src/test/java/org/amdatu/test/integration/base/IntegrationTestBase.java
     (original)
+++ 
trunk/integration-tests/src/test/java/org/amdatu/test/integration/base/IntegrationTestBase.java
     Thu Nov  4 16:06:52 2010
@@ -16,16 +16,20 @@
  */
 package org.amdatu.test.integration.base;
 
-import static org.ops4j.pax.exam.CoreOptions.*;
+import static org.ops4j.pax.exam.CoreOptions.bundle;
+import static org.ops4j.pax.exam.CoreOptions.felix;
+import static org.ops4j.pax.exam.CoreOptions.frameworks;
+import static org.ops4j.pax.exam.CoreOptions.mavenBundle;
+import static org.ops4j.pax.exam.CoreOptions.mavenConfiguration;
+import static org.ops4j.pax.exam.CoreOptions.options;
+import static org.ops4j.pax.exam.CoreOptions.provision;
+import static org.ops4j.pax.exam.CoreOptions.systemProperty;
 
 import java.io.File;
 import java.io.FileFilter;
 import java.util.concurrent.Semaphore;
 import java.util.concurrent.TimeUnit;
 
-import org.amdatu.platform.cassandra.application.CassandraConfigurationService;
-import org.amdatu.platform.configtemplatemanager.ConfigTemplateManager;
-import org.amdatu.platform.httpcontext.HttpContextServiceFactory;
 import org.apache.felix.dm.Component;
 import org.apache.felix.dm.ComponentStateListener;
 import org.apache.felix.dm.DependencyManager;
@@ -40,8 +44,6 @@
 import org.osgi.framework.Constants;
 import org.osgi.framework.InvalidSyntaxException;
 import org.osgi.framework.ServiceReference;
-import org.osgi.service.cm.ConfigurationAdmin;
-import org.osgi.service.log.LogService;
 
 /**
  * This class works as a base for all our integration tests. The notable 
components,
@@ -55,6 +57,9 @@
 public abstract class IntegrationTestBase {
     public final static String TEST_PREFIX = ">  TESTING:  ";
     public final static int SERVICE_TIMEOUT = 30;
+    
+    public final static String HOST_NAME = "localhost";
+    public final static int PORT_NR = 3738; 
 
     @Inject
     protected BundleContext m_bundleContext;
@@ -76,6 +81,9 @@
             
             // Set System property to enable Jetty for the Felix http bundle
             systemProperty("org.apache.felix.http.jettyEnabled").value("true"),
+            
systemProperty("org.apache.felix.http.whiteboardEnabled").value("true"),
+            systemProperty("org.osgi.service.http.hostname").value(HOST_NAME),
+            systemProperty("org.osgi.service.http.port").value(new 
Integer(PORT_NR).toString()),
             
             new VMOption("-Xmx1g"),
             // Enable this line to allow a remote debugger to attach to the VM 
in which Pax Exam runs
@@ -104,7 +112,6 @@
                     amdatuHttpContext(),
                     amdatuConfigTemplateManager(),
                     amdatuCassandraApplication(),
-                    amdatuShindigApplication(),
                     amdatuCassandraListener(),
                     amdatuCassandraPersistenceManager(),
                     amdatuTenantService(),
@@ -272,10 +279,6 @@
         return 
mavenBundle().groupId("org.amdatu.platform").artifactId("cassandra-listener").versionAsInProject();
     }
 
-    protected static MavenArtifactProvisionOption amdatuShindigApplication() {
-        return 
mavenBundle().groupId("org.amdatu.platform").artifactId("shindig-application").versionAsInProject();
-    }
-
     protected static MavenArtifactProvisionOption amdatuCassandraApplication() 
{
         return 
mavenBundle().groupId("org.amdatu.platform").artifactId("cassandra-application").versionAsInProject();
     }

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
 Thu Nov  4 16:06:52 2010
@@ -74,15 +74,6 @@
 
     @Before
     public void setUp() throws Exception {
-        System.out.println("AVAILABLE: " + getService(LogService.class));
-        System.out.println("AVAILABLE: " + 
getService(ConfigurationAdmin.class));
-        System.out.println("AVAILABLE: " + getService(HttpService.class));
-        
-        System.out.println("AVAILABLE: " + 
getService(HttpContextServiceFactory.class));
-        
-        System.out.println("AVAILABLE: " + 
getService(ConfigTemplateManager.class));
-        System.out.println("AVAILABLE: " + 
getService(CassandraConfigurationService.class));
-        
         m_daemonService = getService(CassandraDaemonService.class);
     }
 

Modified: trunk/platform-bundles/httpcontext/pom.xml
==============================================================================
--- trunk/platform-bundles/httpcontext/pom.xml  (original)
+++ trunk/platform-bundles/httpcontext/pom.xml  Thu Nov  4 16:06:52 2010
@@ -47,15 +47,9 @@
             
<Embed-Dependency>*;scope=compile;groupId=!org.apache.felix|org.osgi</Embed-Dependency>
             <Import-Package>
               *;resolution:=optional,
-              org.apache.shindig.auth,
-              org.apache.shindig.common,
-              org.apache.shindig.common.crypto,
-              org.apache.shindig.common.util,
-              org.apache.shindig.social.opensocial.oauth,
-              net.oauth,
               org.osgi.service.useradmin,
               org.amdatu.platform.httpcontext
-            </Import-Package> 
+            </Import-Package>             
             <_exportcontents>
               org.amdatu.platform.httpcontext
             </_exportcontents>

Modified: 
trunk/platform-bundles/httpcontext/src/main/java/org/amdatu/platform/httpcontext/service/HttpContextFactoryServiceImpl.java
==============================================================================
--- 
trunk/platform-bundles/httpcontext/src/main/java/org/amdatu/platform/httpcontext/service/HttpContextFactoryServiceImpl.java
 (original)
+++ 
trunk/platform-bundles/httpcontext/src/main/java/org/amdatu/platform/httpcontext/service/HttpContextFactoryServiceImpl.java
 Thu Nov  4 16:06:52 2010
@@ -41,9 +41,6 @@
     private volatile HttpService m_httpService;
     private volatile LogService m_logService;
 
-    // Injected by Felix
-    private DependencyManager m_manager;
-
     /**
      * Creates a new http context.
      * @param bundleContext The bundle context
@@ -54,21 +51,25 @@
         Dictionary<String, Object> properties = new Hashtable<String, 
Object>();
         properties.put(HttpContextImpl.BUNDLECONTEXT_PROP, bundleContext);
         properties.put(HttpContextImpl.BUNDLEID_PROP, 
bundleContext.getBundle().getBundleId());
+        properties.put("contextId", resourceProvider.getResourceId());
         if (resourceProvider != null) {
             properties.put(HttpContextImpl.RESOURCEPROVIDER_PROP, 
resourceProvider);
             if (resourceProvider.getResourceId() != null) {
                 properties.put(HttpContextImpl.RESOURCEID_PROP, 
resourceProvider.getResourceId());
             }
         }
-        Component component = m_manager.createComponent();
-        m_manager.add(
+        
+        // Create a new dependency manager such that we have a dependency 
manager for the proper bundle context
+        DependencyManager manager = new DependencyManager(bundleContext);
+        Component component = manager.createComponent();
+        manager.add(
                 component
                 .setImplementation(HttpContextImpl.class)
                 .setInterface(HttpContext.class.getName(), properties)
-                
.add(m_manager.createServiceDependency().setService(HttpService.class).setRequired(true))
-                
.add(m_manager.createServiceDependency().setService(ConfigurationAdmin.class).setRequired(true))
-                
.add(m_manager.createServiceDependency().setService(MimeTypeService.class).setRequired(false))
-                
.add(m_manager.createServiceDependency().setService(LogService.class).setRequired(true)));
+                
.add(manager.createServiceDependency().setService(HttpService.class).setRequired(true))
+                
.add(manager.createServiceDependency().setService(ConfigurationAdmin.class).setRequired(true))
+                
.add(manager.createServiceDependency().setService(MimeTypeService.class).setRequired(false))
+                
.add(manager.createServiceDependency().setService(LogService.class).setRequired(true)));
         return component;
     }
 

Modified: 
trunk/platform-bundles/shindig-application/src/main/java/org/amdatu/platform/shindig/application/osgi/Activator.java
==============================================================================
--- 
trunk/platform-bundles/shindig-application/src/main/java/org/amdatu/platform/shindig/application/osgi/Activator.java
        (original)
+++ 
trunk/platform-bundles/shindig-application/src/main/java/org/amdatu/platform/shindig/application/osgi/Activator.java
        Thu Nov  4 16:06:52 2010
@@ -31,14 +31,16 @@
 import org.amdatu.platform.shindig.application.persistence.CassandraOAuthStore;
 import 
org.amdatu.platform.shindig.application.persistence.GadgetColumnFamilyProvider;
 import org.amdatu.platform.shindig.application.persistence.GadgetStoreImpl;
+import org.amdatu.platform.shindig.application.service.GuiceInjectorService;
+import 
org.amdatu.platform.shindig.application.service.GuiceInjectorServiceImpl;
 import 
org.amdatu.platform.shindig.application.service.ShindigRegistrationServiceImpl;
 import org.apache.felix.dm.DependencyActivatorBase;
 import org.apache.felix.dm.DependencyManager;
-import org.apache.felix.http.api.ExtHttpService;
 import org.apache.shindig.gadgets.oauth.OAuthStore;
 import org.apache.shindig.social.opensocial.spi.AppDataService;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.Constants;
+import org.osgi.service.http.HttpService;
 import org.osgi.service.log.LogService;
 import org.osgi.service.useradmin.UserAdmin;
 
@@ -112,30 +114,31 @@
                 .setImplementation(ConfigurationAdminGuiceModule.class)
                 
.add(createConfigurationDependency().setPid(SHINDIG_CONFIG_PID).setPropagate(true)));
         
+        // Create the Guice injector servlet
+        manager.add(
+                createComponent()
+                .setInterface(GuiceInjectorService.class.getName(), null)
+                .setImplementation(GuiceInjectorServiceImpl.class)
+                
.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 + ")")
+                        .setRequired(true)));
+        
         // Register the Shindig registration service
         manager.add( 
                 createComponent()
                 .setImplementation(ShindigRegistrationServiceImpl.class)
                 .setInterface(ResourceProvider.class.getName(), null)
                 
.add(createServiceDependency().setService(LogService.class).setRequired(true))
+                
.add(createServiceDependency().setService(GuiceInjectorService.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 + ")")
                         .setRequired(true))
                 
.add(createServiceDependency().setService(HttpContextServiceFactory.class).setRequired(true))
-                
.add(createServiceDependency().setService(ExtHttpService.class).setRequired(true)));
-        
-        //TODO: Register authentication filter as a service
-       /* 
-        Dictionary<String, String> props = new Hashtable<String, String>();
-        props.put("pattern ", "/*");
-        props.put("service.ranking", "0");
-        manager.add( 
-            createComponent()
-            .setImplementation(AuthenticationServletFilter.class)
-            .setInterface(Filter.class.getName(), props));
-        */
+                
.add(createServiceDependency().setService(HttpService.class).setRequired(true)));
     }
 
     @Override

Added: 
trunk/platform-bundles/shindig-application/src/main/java/org/amdatu/platform/shindig/application/service/GuiceInjectorService.java
==============================================================================
--- (empty file)
+++ 
trunk/platform-bundles/shindig-application/src/main/java/org/amdatu/platform/shindig/application/service/GuiceInjectorService.java
  Thu Nov  4 16:06:52 2010
@@ -0,0 +1,28 @@
+/*
+    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.platform.shindig.application.service;
+
+import javax.servlet.Servlet;
+
+/**
+ * Interface for the Guice injector service. The only purpose of this 
interface is to allow service
+ * dependencies to be created. For that reason, it holds no methods.
+ * 
+ * @author ivol
+ */
+public interface GuiceInjectorService extends Servlet {
+}

Added: 
trunk/platform-bundles/shindig-application/src/main/java/org/amdatu/platform/shindig/application/service/GuiceInjectorServiceImpl.java
==============================================================================
--- (empty file)
+++ 
trunk/platform-bundles/shindig-application/src/main/java/org/amdatu/platform/shindig/application/service/GuiceInjectorServiceImpl.java
      Thu Nov  4 16:06:52 2010
@@ -0,0 +1,177 @@
+/*
+    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.platform.shindig.application.service;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Dictionary;
+import java.util.Hashtable;
+import java.util.List;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletContext;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServlet;
+
+import org.amdatu.platform.shindig.application.OAuthModule;
+import org.amdatu.platform.shindig.application.SocialApiModule;
+import 
org.amdatu.platform.shindig.application.module.ConfigurationAdminGuiceModule;
+import org.apache.felix.dm.Component;
+import org.apache.felix.dm.DependencyManager;
+import org.apache.shindig.common.servlet.GuiceServletContextListener;
+import org.osgi.service.log.LogService;
+
+import com.google.inject.Guice;
+import com.google.inject.Injector;
+import com.google.inject.Module;
+import com.google.inject.Stage;
+import com.google.inject.tools.jmx.Manager;
+
+/**
+ * This class covers a rather complicated problem using Guice. Guice-based 
servlets require the "Guice injector" to
+ * be created before they are registered. The Guice injector should be 
associated with that same servlet context, so
+ * to make that so a servlet should be registered. Usually you do not have 
control when a servlet is 
+ * actually initialized.
+ * This service covers this tricky stuff. This is what will happen:
+ * -1- First this GuiceInjectorService is created, which contains some 
dependencies on Guice modules. The service is
+ * registered with the GuiceInjectorService interface, so it will not register 
any servlet yet.
+ * -2- The ShindigRegistrationService has a dependency on this 
GuiceInjectorService. In its init() method it will
+ * first create a http context.
+ * -3- The ShindigRegistrationService will now register the 
GuiceInjectorService as servlet, using the http context
+ * it just created
+ * -4- By registration of this service as Servlet, the init(ServletConfig) 
will be invoked which creates the Guice 
+ * injector and associates it with the servlet context.
+ * -5- When the Guice injector is registered, this service is registered as 
GuiceInjectorServlet service.
+ * -6- The ShindigRegistrationService continues to register filters and 
servlets (whiteboard style), but all with a
+ * service dependency on the GuiceInjectorServlet. This ensures that the Guice 
injector is initialized and bound to
+ * the servlet context before it is created.
+ * @author ivol
+ *
+ */
+public class GuiceInjectorServiceImpl implements GuiceInjectorService, 
GuiceInjectorServlet {
+    /**
+     * This a path to a fake servlet used to initialize the Guice context. 
This servlet is registered *before* all other
+     * servlets and it activates a common HttpContext in its {@link 
HttpServlet#init(javax.servlet.ServletConfig)}
+     * method. So all other servlets could find the Guice injector stored by 
this fake servlet.
+     */
+    public static final String SERVLET_ALIAS = 
"/this/is/the/guice/injector/servlet";
+
+    // Service dependencies
+    private volatile LogService m_logService;
+    private volatile SocialApiModule m_socialApiModule;
+    private volatile OAuthModule m_oAuthModule;
+    private volatile ConfigurationAdminGuiceModule 
m_shindigConfigurationModule;
+    private volatile DependencyManager m_dependencyManager;
+
+    // Instance variables
+    private boolean m_jmxInitialized;
+
+    public ServletConfig getServletConfig() {
+        return null;
+    }
+
+    public String getServletInfo() {
+        return null;
+    }
+
+    public void init(ServletConfig config) throws ServletException {
+        Injector injector = createGuiceInjector();
+        ServletContext context = config.getServletContext();
+        context.setAttribute(GuiceServletContextListener.INJECTOR_ATTRIBUTE, 
injector);
+        registerService();
+    }
+
+    private void registerService() {
+        // This registers ourselves as GuiceInjectorServlet. Note that the 
activator explicitly
+        // does not register the service with the GuiceInjectorServlet 
interface since we want
+        // postpone the availability of the service until the Guice injector 
is initialized.
+        Dictionary<String, String> serviceProps = new Hashtable<String, 
String>();
+        Component component = m_dependencyManager.createComponent();
+        component.setImplementation(this);
+        component.setInterface(GuiceInjectorServlet.class.getName(), 
serviceProps);
+        m_dependencyManager.add(component);
+    }
+
+    public void service(ServletRequest arg0, ServletResponse arg1) throws 
ServletException, IOException {
+    }
+    
+    public void destroy() {
+    }
+
+    /**
+     * @return a newly created Guice injector which is shared between all 
Shindig servlets using a common HttpContext
+     */
+    private Injector createGuiceInjector() {
+        String[] moduleNames = getGuiceModules();
+        List<Module> modules = new ArrayList<Module>();
+        if (moduleNames != null) {
+            // First add the properties module
+            modules.add(m_shindigConfigurationModule);
+
+            // Now add all Guice-injected modules
+            for (String moduleName : moduleNames) {
+                try {
+                    moduleName = moduleName.trim();
+                    if (moduleName.length() > 0) {
+                        ClassLoader cl = Module.class.getClassLoader();
+                        Module moduleInstance = (Module) 
cl.loadClass(moduleName).newInstance();
+                        modules.add(moduleInstance);
+                    }
+                }
+                catch (InstantiationException e) {
+                    m_logService.log(LogService.LOG_ERROR, "Could not create 
Guice module", e);
+                }
+                catch (ClassNotFoundException e) {
+                    m_logService.log(LogService.LOG_ERROR, "Could not create 
Guice module", e);
+                }
+                catch (IllegalAccessException e) {
+                    m_logService.log(LogService.LOG_ERROR, "Could not create 
Guice module", e);
+                }
+                catch (ClassCastException e) {
+                    m_logService.log(LogService.LOG_ERROR, "Could not create 
Guice module", e);
+                }
+            }
+
+            // Add our own oAuth module
+            modules.add(m_oAuthModule);
+
+            // Finally add our own social api module
+            modules.add(m_socialApiModule);
+        }
+        Injector injector = Guice.createInjector(Stage.PRODUCTION, modules);
+        injector.injectMembers(this);
+        try {
+            if (m_jmxInitialized == false) {
+                Manager.manage("ShindigGuiceContext", injector);
+                m_jmxInitialized = true;
+            }
+        }
+        catch (Exception e) {
+            // Ignore errors
+        }
+        return injector;
+    }
+
+    private String[] getGuiceModules() {
+        return new String[] {
+            "org.apache.shindig.gadgets.DefaultGuiceModule",
+            "org.apache.shindig.extras.ShindigExtrasGuiceModule",
+            "org.apache.shindig.common.cache.ehcache.EhCacheModule" };
+    }
+}

Added: 
trunk/platform-bundles/shindig-application/src/main/java/org/amdatu/platform/shindig/application/service/GuiceInjectorServlet.java
==============================================================================
--- (empty file)
+++ 
trunk/platform-bundles/shindig-application/src/main/java/org/amdatu/platform/shindig/application/service/GuiceInjectorServlet.java
  Thu Nov  4 16:06:52 2010
@@ -0,0 +1,29 @@
+/*
+    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.platform.shindig.application.service;
+
+/**
+ * This interface enables dependencies on the availability of the Guice 
injector servlet using service dependencies.
+ * When a service dependency on this interface is created, the dependency 
implies that the Guice injector servlet is
+ * registered AND initialized, as it registers the service AFTER 
initialization of the servlet. This dependency is 
+ * needed since each servlet and filter that uses Guice needs this servlet to 
be registered first.
+ * 
+ * @author ivol
+ */
+public interface GuiceInjectorServlet {
+
+}

Modified: 
trunk/platform-bundles/shindig-application/src/main/java/org/amdatu/platform/shindig/application/service/ShindigRegistrationServiceImpl.java
==============================================================================
--- 
trunk/platform-bundles/shindig-application/src/main/java/org/amdatu/platform/shindig/application/service/ShindigRegistrationServiceImpl.java
        (original)
+++ 
trunk/platform-bundles/shindig-application/src/main/java/org/amdatu/platform/shindig/application/service/ShindigRegistrationServiceImpl.java
        Thu Nov  4 16:06:52 2010
@@ -24,25 +24,20 @@
 import java.io.InputStream;
 import java.net.URL;
 import java.util.ArrayList;
+import java.util.Dictionary;
+import java.util.Hashtable;
 import java.util.List;
-import java.util.Properties;
 
-import javax.servlet.ServletConfig;
-import javax.servlet.ServletContext;
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServlet;
+import javax.servlet.Filter;
+import javax.servlet.Servlet;
 
 import org.amdatu.platform.httpcontext.HttpContextServiceFactory;
 import org.amdatu.platform.httpcontext.ResourceProvider;
-import org.amdatu.platform.shindig.application.OAuthModule;
-import org.amdatu.platform.shindig.application.SocialApiModule;
-import 
org.amdatu.platform.shindig.application.module.ConfigurationAdminGuiceModule;
 import org.amdatu.platform.shindig.application.oauth.AmdatuOAuthServlet;
 import org.amdatu.platform.shindig.application.osgi.Activator;
 import org.apache.felix.dm.Component;
-import org.apache.felix.http.api.ExtHttpService;
+import org.apache.felix.dm.DependencyManager;
 import org.apache.shindig.auth.AuthenticationServletFilter;
-import org.apache.shindig.common.servlet.GuiceServletContextListener;
 import org.apache.shindig.gadgets.servlet.ConcatProxyServlet;
 import org.apache.shindig.gadgets.servlet.GadgetRenderingServlet;
 import org.apache.shindig.gadgets.servlet.JsServlet;
@@ -55,15 +50,8 @@
 import org.osgi.framework.BundleContext;
 import org.osgi.service.http.HttpContext;
 import org.osgi.service.http.HttpService;
-import org.osgi.service.http.NamespaceException;
 import org.osgi.service.log.LogService;
 
-import com.google.inject.Guice;
-import com.google.inject.Injector;
-import com.google.inject.Module;
-import com.google.inject.Stage;
-import com.google.inject.tools.jmx.Manager;
-
 /**
  * This service is responsible for registration and unregistration of Shindig 
servlets, filters and static
  * resources.
@@ -71,12 +59,6 @@
  * @author ivol
  */
 public class ShindigRegistrationServiceImpl implements ResourceProvider {
-    /**
-     * This a path to a fake servlet used to initialize the Guice context. 
This servlet is registered *before* all other
-     * servlets and it activates a common HttpContext in its {@link 
HttpServlet#init(javax.servlet.ServletConfig)}
-     * method. So all other servlets could find the Guice injector stored by 
this fake servlet.
-     */
-    private static final String PATH_TO_FAKE_SERVLET = 
"/this/is/a/fake/servlet";
 
     // Base URLs for filters, servlets and static resources
     private static final String GADGETS_BASE = "/gadgets";
@@ -93,36 +75,67 @@
     private static final String OAUTH_BASE = "/oauth";
     private static final String ECHO_BASE = GADGETS_BASE + "/api/echo";
 
-    private static final String WINK_REST_BASE = "/rest/services";
-
     // These variables are injected by the Felix dependency manager
     private volatile BundleContext m_bundleContext;
-    private volatile ExtHttpService m_httpService;
+    private volatile HttpService m_httpService;
     private volatile Component m_httpContextComponent;
     private volatile LogService m_logService;
     private volatile HttpContextServiceFactory m_httpContextFactoryService;
-    private volatile SocialApiModule m_socialApiModule;
-    private volatile OAuthModule m_oAuthModule;
-    private volatile ConfigurationAdminGuiceModule 
m_shindigConfigurationModule;
+    private volatile DependencyManager m_dependencyManager;
+    private volatile GuiceInjectorService m_guiceInjectorService;
 
     // Other instance variables
-    private boolean m_jmxInitialized;
-    private ServletContext m_servletContext = null;
     private HttpContext m_httpContext;
     private List<String> m_registeredServletPaths = new ArrayList<String>();
-    private AuthenticationServletFilter m_authenticationServletFilter;
 
     /**
      * The init() method is invoked by the Felix dependency manager.
      */
     public void init() {
-        // Create our own http context and register resources
+        // Beware! The order in which httpcontext, Guice servlet and other 
services are created is very important!
+        // 
+
+        // First of all we need to create our own http context to register 
resources, filters and servlets
         m_httpContextComponent = 
m_httpContextFactoryService.create(m_bundleContext, this);
         m_httpContext = (HttpContext) m_httpContextComponent.getService();
 
+        // Now we need to register the Guice injector servlet. This servlet 
will create the Guice injector
+        // and set it onto the servlet context. The Guice injector servlet 
needs to be registered on the same
+        // httpcontext, therefore we register the servlet and not the Guice 
injector service itself.
+        // When the servlet is initialized it will register itself as a 
GuiceInjectorServlet service (at this moment
+        // the servlet is registered with the GuiceInjectorService interface)
+        registerServlet(GuiceInjectorServiceImpl.SERVLET_ALIAS, 
m_guiceInjectorService);
+
+        // Now register the authentication filter as a service. This filter 
needs the Guice injector to be initialized,
+        // which is done when the GuiceInjectorServlet is initialized. So we 
define a service dependency on the
+        // GuiceInjectorServlet
+        String baseMatch = "[/\\?]?.*";
+        String regex = ".*("
+            + GADGET_SERVLET_BASE + "[^/]*|"
+            + MAKEREQUEST_BASE + "[^/]*|"
+            + REST_BASE + baseMatch + "|"
+            + GADGETS_REST_BASE + baseMatch + "|"
+            + GADGETS_RPC_BASE + baseMatch + ")";
+        Dictionary<String, String> properties = new Hashtable<String, 
String>();
+        properties.put("pattern", regex);
+        properties.put("service.ranking", "0");
+        properties.put("contextId", this.getResourceId());
+        Component component = m_dependencyManager.createComponent();
+        component.setImplementation(AuthenticationServletFilter.class);
+        component.setInterface(Filter.class.getName(), properties);
+        
component.add(m_dependencyManager.createServiceDependency().setService(GuiceInjectorServlet.class).setRequired(
+            true));
+        m_dependencyManager.add(component);
+
+        // Append a dependency on the GuiceInjectorServlet such that any 
servlets registered later on
+        // are not registered before the Guice injector is initialized
+        
m_dependencyManager.createServiceDependency().setService(GuiceInjectorServlet.class.getName())
+            .setRequired(true);
+
         copySecurityTokenKey();
 
         m_logService.log(LogService.LOG_INFO, getClass().getName() + " service 
initialized");
+
     }
 
     /**
@@ -130,33 +143,7 @@
      */
     public void start() {
         m_logService.log(LogService.LOG_INFO, "Starting " + 
getClass().getName() + " service");
-
-        try {
-            // Initialize the GUICE context.
-            initGuiceInjector(m_httpContext);
-            int retryCount = 0;
-            while (m_servletContext == null && retryCount < 5) {
-                // TODO The servlet registration is asynchronous? Really?
-                try {
-                    System.out.println("Fake Guice servlet not yet available, 
sleeping for 1 second... ("
-                        + (5 - retryCount) + " retries left)");
-                    Thread.sleep(1000);
-                }
-                catch (InterruptedException i) {}
-                retryCount++;
-            }
-
-            // Register statics, servlets and filters. This can only be done 
after initializing
-            // the Guice context, for that reason we do it here.
-            registerResources();
-        }
-        catch (ServletException e) {
-            m_logService.log(LogService.LOG_ERROR, "Shindig service could not 
be started due to error", e);
-        }
-        catch (NamespaceException e) {
-            m_logService.log(LogService.LOG_ERROR, "Shindig service could not 
be started due to error", e);
-        }
-
+        registerResources();
         m_logService.log(LogService.LOG_INFO, getClass().getName() + " service 
started.");
     }
 
@@ -217,17 +204,6 @@
     }
 
     /**
-     * Invoked by the Guice servlet init() method to let the main registration 
service know
-     * that the fake Guice servlet is initialized. This is requried before 
other servlets are
-     * registered within the same context
-     * 
-     * @param servletContext the servlet context of the fake Guice servlet
-     */
-    private void setServletContext(ServletContext servletContext) {
-        m_servletContext = servletContext;
-    }
-
-    /**
      * This method sets the given {@link HttpService} object and initializes 
all Shindig-specific servlets.
      * Since it can only be invoked when the Guice context is available, it is 
invoked from there
      */
@@ -236,33 +212,23 @@
             // Register the gadget rendering servlet. The gadget rendering 
servlet takes a gadget XML file
             // (for example 
http://gerculanum.appspot.com/gadgets/com.example.chessgadget.client.ChessGadget.gadget.xml)
             // and converts it to HTML. 'ifr' stands for the 'iframe' way of 
gadget rendering
-            addServlet(m_httpContext, GADGET_SERVLET_BASE, new 
GadgetRenderingServlet());
+            registerServlet(GADGET_SERVLET_BASE, new GadgetRenderingServlet());
 
             // Register other servlets
-            String[] params = { "handlers", 
"org.apache.shindig.social.handlers" };
-            addServlet(m_httpContext, MAKEREQUEST_BASE, new 
MakeRequestServlet());
-            addServlet(m_httpContext, PROXY_BASE, new ProxyServlet());
-            addServlet(m_httpContext, CONCAT_BASE, new ConcatProxyServlet());
-            addServlet(m_httpContext, OAUTH_CALLBACK_BASE, new 
OAuthCallbackServlet());
-            addServlet(m_httpContext, METADATA_BASE, new RpcServlet());
-            addServlet(m_httpContext, JS_BASE, new JsServlet());
-            addServlet(m_httpContext, REST_BASE, new DataServiceServlet(), 
params);
-            addServlet(m_httpContext, GADGETS_REST_BASE, new 
DataServiceServlet(), params);
-            addServlet(m_httpContext, GADGETS_RPC_BASE, new JsonRpcServlet(), 
params);
-            addServlet(m_httpContext, OAUTH_BASE, new AmdatuOAuthServlet(), 
params);
-            addServlet(m_httpContext, ECHO_BASE, new EchoServlet(), params);
-
-            // Register filters
-            m_authenticationServletFilter = new AuthenticationServletFilter();
-            String baseMatch = "[/\\?]?.*";
-            String regex = ".*(" 
-                + GADGET_SERVLET_BASE + "[^/]*|" 
-                + MAKEREQUEST_BASE + "[^/]*|" 
-                + REST_BASE + baseMatch + "|"
-                + GADGETS_REST_BASE + baseMatch + "|" 
-                + GADGETS_RPC_BASE + baseMatch + ")";
-            m_httpService.registerFilter(m_authenticationServletFilter, regex, 
null, 0, m_httpContext);
-           
+            Dictionary<String, String> servletProperties = new 
Hashtable<String, String>();
+            servletProperties.put("init.handlers", 
"org.apache.shindig.social.handlers");
+            registerServlet(MAKEREQUEST_BASE, new MakeRequestServlet());
+            registerServlet(PROXY_BASE, new ProxyServlet());
+            registerServlet(CONCAT_BASE, new ConcatProxyServlet());
+            registerServlet(OAUTH_CALLBACK_BASE, new OAuthCallbackServlet());
+            registerServlet(METADATA_BASE, new RpcServlet());
+            registerServlet(JS_BASE, new JsServlet());
+            registerServlet(REST_BASE, new DataServiceServlet(), 
servletProperties);
+            registerServlet(GADGETS_REST_BASE, new DataServiceServlet(), 
servletProperties);
+            registerServlet(GADGETS_RPC_BASE, new JsonRpcServlet(), 
servletProperties);
+            registerServlet(OAUTH_BASE, new AmdatuOAuthServlet(), 
servletProperties);
+            registerServlet(ECHO_BASE, new EchoServlet(), servletProperties);
+
             // Since /gadgets is already registered automatically by the http 
context factory service,
             // unregister it first.
             m_httpService.unregister("/" + Activator.RESOURCE_ID);
@@ -283,129 +249,40 @@
             m_httpService.unregister(m_registeredServletPaths.get(0));
             m_registeredServletPaths.remove(0);
         }
-        m_httpService.unregisterFilter(m_authenticationServletFilter);
         m_httpService.unregister("/gadgets");
         m_httpService.unregister("/features");
         m_httpService.unregister("/shindig");
     }
 
-    /**
-     * An utility method used to add a new servlet to the HttpService object.
-     * 
-     * @param context the HttpContext common for all servlets
-     * @param path the path of the servlet
-     * @param servlet the servlet to register
-     * @param params parameters to add to the servlet configuration
-     * @throws ServletException
-     * @throws NamespaceException
-     */
-    private void addServlet(HttpContext context, String path, HttpServlet 
servlet, String... params)
-        throws ServletException, NamespaceException {
-        Properties p = new Properties();
-        String key = null;
-        for (int i = 0; i < params.length; i++) {
-            if ((i % 2) == 0) {
-                key = params[i] != null ? params[i].toString() : null;
-            }
-            else {
-                p.put(key, params[i]);
-            }
-        }
-        m_registeredServletPaths.add(path);
-        m_httpService.registerServlet(path, servlet, p, context);
+    public URL getResource(String name) {
+        return null;
     }
 
-    /**
-     * @return a newly created Guice injector which is shared between all 
Shindig servlets using a common HttpContext
-     */
-    private Injector createGuiceInjector() {
-        String[] moduleNames = getGuiceModules();
-        List<Module> modules = new ArrayList<Module>();
-        if (moduleNames != null) {
-            // First add the properties module
-            modules.add(m_shindigConfigurationModule);
-
-            // Now add all Guice-injected modules
-            for (String moduleName : moduleNames) {
-                try {
-                    moduleName = moduleName.trim();
-                    if (moduleName.length() > 0) {
-                        ClassLoader cl = Module.class.getClassLoader();
-                        Module moduleInstance = (Module) 
cl.loadClass(moduleName).newInstance();
-                        modules.add(moduleInstance);
-                    }
-                }
-                catch (InstantiationException e) {
-                    m_logService.log(LogService.LOG_ERROR, "Could not create 
Guice module", e);
-                }
-                catch (ClassNotFoundException e) {
-                    m_logService.log(LogService.LOG_ERROR, "Could not create 
Guice module", e);
-                }
-                catch (IllegalAccessException e) {
-                    m_logService.log(LogService.LOG_ERROR, "Could not create 
Guice module", e);
-                }
-                catch (ClassCastException e) {
-                    m_logService.log(LogService.LOG_ERROR, "Could not create 
Guice module", e);
-                }
-            }
-
-            // Add our own oAuth module
-            modules.add(m_oAuthModule);
-
-            // Finally add our own social api module
-            modules.add(m_socialApiModule);
-        }
-        Injector injector = Guice.createInjector(Stage.PRODUCTION, modules);
-        injector.injectMembers(this);
-        try {
-            if (m_jmxInitialized == false) {
-                Manager.manage("ShindigGuiceContext", injector);
-                m_jmxInitialized = true;
-            }
-        }
-        catch (Exception e) {
-            // Ignore errors
-        }
-        return injector;
+    public String getResourceId() {
+        return RESOURCE_ID;
     }
 
-    private String[] getGuiceModules() {
-        return new String[] {
-            "org.apache.shindig.gadgets.DefaultGuiceModule",
-            "org.apache.shindig.extras.ShindigExtrasGuiceModule",
-            "org.apache.shindig.common.cache.ehcache.EhCacheModule" };
+    private void registerServlet(String alias, Servlet servlet) {
+        registerServlet(alias, servlet, null);
     }
 
     /**
-     * This method creates a fake servlet which is registered *before* all 
others servlets and used to initialize the
-     * Guice injector for all other servlets sharing the given HttpContext. 
The {@link HttpServlet#init(ServletConfig)}
-     * method of this fake servlet creates a new Guice instance, configures it 
and sets in the given HttpContext. The
-     * same HttpContext instance will be used to register all other Shindig 
servlets, so they will have access to the
-     * already configured Guice.
-     * 
-     * @param context the HttpContext instance where a Guice context will be 
stored.
-     * @throws ServletException
-     * @throws NamespaceException
-     */
-    private void initGuiceInjector(HttpContext context) throws 
ServletException, NamespaceException {
-        addServlet(context, PATH_TO_FAKE_SERVLET, new HttpServlet() {
-            private static final long serialVersionUID = 1L;
-
-            @Override
-            public void init(ServletConfig config) throws ServletException {
-                Injector injector = createGuiceInjector();
-                ServletContext context = config.getServletContext();
-                
context.setAttribute(GuiceServletContextListener.INJECTOR_ATTRIBUTE, injector);
-                setServletContext(context);
-            }
-        });
-    }
-
-    public URL getResource(String name) {
-        return null;
-    }
-
-    public String getResourceId() {
-        return RESOURCE_ID;
+     * Registers a servlet whiteboard-style. Note that we should not mix 
whiteboard style with direct calls to the
+     * HttpService;
+     * they do not share the same servlet context and the Guice injector is 
only registered on the servlet context for
+     * the
+     * whiteboard-style http service.
+     */
+    private void registerServlet(String alias, Servlet servlet, 
Dictionary<String, String> servletProperties) {
+        if (servletProperties == null) {
+            servletProperties = new Hashtable<String, String>();
+        }
+        servletProperties.put("alias", alias);
+        servletProperties.put("contextId", getResourceId());
+        Component servletComponent = m_dependencyManager.createComponent();
+        servletComponent.setImplementation(servlet);
+        servletComponent.setInterface(Servlet.class.getName(), 
servletProperties);
+        m_dependencyManager.add(servletComponent);
+        m_registeredServletPaths.add(alias);
     }
 }

Modified: trunk/src/main/resources/conf/felix-config.properties
==============================================================================
--- trunk/src/main/resources/conf/felix-config.properties       (original)
+++ trunk/src/main/resources/conf/felix-config.properties       Thu Nov  4 
16:06:52 2010
@@ -114,3 +114,4 @@
 org.apache.felix.http.jettyEnabled=true
 org.apache.felix.http.debug=true
 org.apache.felix.log.storeDebug=true
+org.apache.felix.http.whiteboardEnabled=true
\ No newline at end of file

Reply via email to