You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tapestry.apache.org by jk...@apache.org on 2015/10/06 14:34:41 UTC

tapestry-5 git commit: TAP5-2238: if a module is requested that is part of a JavaScript stack, send a redirect to the stack

Repository: tapestry-5
Updated Branches:
  refs/heads/master db1b19361 -> 1e73d6b52


TAP5-2238: if a module is requested that is part of a JavaScript stack, send a redirect to the stack


Project: http://git-wip-us.apache.org/repos/asf/tapestry-5/repo
Commit: http://git-wip-us.apache.org/repos/asf/tapestry-5/commit/1e73d6b5
Tree: http://git-wip-us.apache.org/repos/asf/tapestry-5/tree/1e73d6b5
Diff: http://git-wip-us.apache.org/repos/asf/tapestry-5/diff/1e73d6b5

Branch: refs/heads/master
Commit: 1e73d6b52ea163cee6f7bfcbdb09fe4d333d9197
Parents: db1b193
Author: Jochen Kemnade <jo...@eddyson.de>
Authored: Fri Sep 18 10:44:12 2015 +0200
Committer: Jochen Kemnade <jo...@eddyson.de>
Committed: Tue Oct 6 14:30:52 2015 +0200

----------------------------------------------------------------------
 .../services/javascript/ModuleDispatcher.java   | 67 +++++++++++++++++++-
 .../tapestry5/modules/JavaScriptModule.java     | 12 +++-
 .../javascript/ModuleDispatcherTests.groovy     | 51 ++++++++++++++-
 3 files changed, 123 insertions(+), 7 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/1e73d6b5/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/javascript/ModuleDispatcher.java
----------------------------------------------------------------------
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/javascript/ModuleDispatcher.java b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/javascript/ModuleDispatcher.java
index 372fabd..4050b39 100644
--- a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/javascript/ModuleDispatcher.java
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/javascript/ModuleDispatcher.java
@@ -12,20 +12,27 @@
 
 package org.apache.tapestry5.internal.services.javascript;
 
+import org.apache.tapestry5.SymbolConstants;
 import org.apache.tapestry5.internal.services.AssetDispatcher;
+import org.apache.tapestry5.internal.services.RequestConstants;
 import org.apache.tapestry5.internal.services.ResourceStreamer;
 import org.apache.tapestry5.ioc.IOOperation;
 import org.apache.tapestry5.ioc.OperationTracker;
 import org.apache.tapestry5.ioc.Resource;
+import org.apache.tapestry5.ioc.annotations.Symbol;
+import org.apache.tapestry5.ioc.internal.util.CollectionFactory;
 import org.apache.tapestry5.services.Dispatcher;
 import org.apache.tapestry5.services.PathConstructor;
 import org.apache.tapestry5.services.Request;
 import org.apache.tapestry5.services.Response;
+import org.apache.tapestry5.services.javascript.JavaScriptStackSource;
 import org.apache.tapestry5.services.javascript.ModuleManager;
 
 import javax.servlet.http.HttpServletResponse;
 import java.io.IOException;
 import java.util.EnumSet;
+import java.util.List;
+import java.util.Map;
 import java.util.Set;
 
 /**
@@ -43,25 +50,41 @@ public class ModuleDispatcher implements Dispatcher
 
     private final OperationTracker tracker;
 
+    private final JavaScriptStackSource javaScriptStackSource;
+
+    private final JavaScriptStackPathConstructor javaScriptStackPathConstructor;
+
     private final String requestPrefix;
 
+    private final String stackPathPrefix;
+
     private final boolean compress;
 
     private final Set<ResourceStreamer.Options> omitExpiration = EnumSet.of(ResourceStreamer.Options.OMIT_EXPIRATION);
 
+    private Map<String, String> moduleNameToStackName;
+
+
     public ModuleDispatcher(ModuleManager moduleManager,
                             ResourceStreamer streamer,
                             OperationTracker tracker,
                             PathConstructor pathConstructor,
+                            JavaScriptStackSource javaScriptStackSource,
+                            JavaScriptStackPathConstructor javaScriptStackPathConstructor,
                             String prefix,
+                            @Symbol(SymbolConstants.ASSET_PATH_PREFIX)
+                            String assetPrefix,
                             boolean compress)
     {
         this.moduleManager = moduleManager;
         this.streamer = streamer;
         this.tracker = tracker;
+        this.javaScriptStackSource = javaScriptStackSource;
+        this.javaScriptStackPathConstructor = javaScriptStackPathConstructor;
         this.compress = compress;
 
         requestPrefix = pathConstructor.constructDispatchPath(compress ? prefix + ".gz" : prefix) + "/";
+        stackPathPrefix = pathConstructor.constructDispatchPath(assetPrefix, RequestConstants.STACK_FOLDER) + "/";
     }
 
     public boolean dispatch(Request request, Response response) throws IOException
@@ -72,7 +95,7 @@ public class ModuleDispatcher implements Dispatcher
         {
             String extraPath = path.substring(requestPrefix.length());
 
-            if (! handleModuleRequest(extraPath))
+            if (!handleModuleRequest(extraPath, response))
             {
                 response.sendError(HttpServletResponse.SC_NOT_FOUND, String.format("No module for path '%s'.", extraPath));
             }
@@ -84,7 +107,7 @@ public class ModuleDispatcher implements Dispatcher
 
     }
 
-    private boolean handleModuleRequest(String extraPath) throws IOException
+    private boolean handleModuleRequest(String extraPath, Response response) throws IOException
     {
         // Ensure request ends with '.js'.  That's the extension tacked on by RequireJS because it expects there
         // to be a hierarchy of static JavaScript files here. In reality, we may be cross-compiling CoffeeScript to
@@ -105,6 +128,22 @@ public class ModuleDispatcher implements Dispatcher
 
         final String moduleName = extraPath.substring(0, dotx);
 
+        String stackName = findStackForModule(moduleName);
+
+        if (stackName != null)
+        {
+            List<String> libraryUrls = javaScriptStackPathConstructor.constructPathsForJavaScriptStack(stackName);
+            if (libraryUrls.size() == 1)
+            {
+                String firstUrl = libraryUrls.get(0);
+                if (firstUrl.startsWith(stackPathPrefix))
+                {
+                    response.sendRedirect(firstUrl);
+                    return true;
+                }
+            }
+        }
+
         return tracker.perform(String.format("Streaming %s %s",
                 compress ? "compressed module" : "module",
                 moduleName), new IOOperation<Boolean>()
@@ -124,4 +163,28 @@ public class ModuleDispatcher implements Dispatcher
             }
         });
     }
+
+    private String findStackForModule(String moduleName)
+    {
+        return getModuleNameToStackName().get(moduleName);
+    }
+
+    private Map<String, String> getModuleNameToStackName()
+    {
+
+        if (moduleNameToStackName == null)
+        {
+            moduleNameToStackName = CollectionFactory.newMap();
+
+            for (String stackName : javaScriptStackSource.getStackNames())
+            {
+                for (String moduleName : javaScriptStackSource.getStack(stackName).getModules())
+                {
+                    moduleNameToStackName.put(moduleName, stackName);
+                }
+            }
+        }
+
+        return moduleNameToStackName;
+    }
 }

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/1e73d6b5/tapestry-core/src/main/java/org/apache/tapestry5/modules/JavaScriptModule.java
----------------------------------------------------------------------
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/modules/JavaScriptModule.java b/tapestry-core/src/main/java/org/apache/tapestry5/modules/JavaScriptModule.java
index 4ac11d7..91d1d12 100644
--- a/tapestry-core/src/main/java/org/apache/tapestry5/modules/JavaScriptModule.java
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/modules/JavaScriptModule.java
@@ -214,15 +214,21 @@ public class JavaScriptModule
                                               OperationTracker tracker,
                                               ResourceStreamer resourceStreamer,
                                               PathConstructor pathConstructor,
+                                              JavaScriptStackSource javaScriptStackSource,
+                                              JavaScriptStackPathConstructor javaScriptStackPathConstructor,
                                               @Symbol(SymbolConstants.MODULE_PATH_PREFIX)
-                                              String modulePathPrefix)
+                                              String modulePathPrefix,
+                                              @Symbol(SymbolConstants.ASSET_PATH_PREFIX)
+                                              String assetPathPrefix)
     {
         configuration.add("Modules",
-                new ModuleDispatcher(moduleManager, resourceStreamer, tracker, pathConstructor, modulePathPrefix, false),
+                new ModuleDispatcher(moduleManager, resourceStreamer, tracker, pathConstructor,
+                    javaScriptStackSource, javaScriptStackPathConstructor, modulePathPrefix, assetPathPrefix, false),
                 "after:Asset", "before:ComponentEvent");
 
         configuration.add("ComnpressedModules",
-                new ModuleDispatcher(moduleManager, resourceStreamer, tracker, pathConstructor, modulePathPrefix, true),
+                new ModuleDispatcher(moduleManager, resourceStreamer, tracker, pathConstructor,
+                    javaScriptStackSource, javaScriptStackPathConstructor, modulePathPrefix, assetPathPrefix, true),
                 "after:Modules", "before:ComponentEvent");
     }
 

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/1e73d6b5/tapestry-core/src/test/groovy/org/apache/tapestry5/services/javascript/ModuleDispatcherTests.groovy
----------------------------------------------------------------------
diff --git a/tapestry-core/src/test/groovy/org/apache/tapestry5/services/javascript/ModuleDispatcherTests.groovy b/tapestry-core/src/test/groovy/org/apache/tapestry5/services/javascript/ModuleDispatcherTests.groovy
index 30d0066..691469e 100644
--- a/tapestry-core/src/test/groovy/org/apache/tapestry5/services/javascript/ModuleDispatcherTests.groovy
+++ b/tapestry-core/src/test/groovy/org/apache/tapestry5/services/javascript/ModuleDispatcherTests.groovy
@@ -1,5 +1,6 @@
 package org.apache.tapestry5.services.javascript
 
+import org.apache.tapestry5.internal.services.javascript.JavaScriptStackPathConstructor;
 import org.apache.tapestry5.internal.services.javascript.ModuleDispatcher
 import org.apache.tapestry5.ioc.internal.QuietOperationTracker
 import org.apache.tapestry5.ioc.test.TestBase
@@ -19,8 +20,12 @@ class ModuleDispatcherTests extends TestBase {
         def request = newMock Request
         def response = newMock Response
         def pc = newMock PathConstructor
+        def javaScriptStackSource = newMock JavaScriptStackSource
+        def javaScriptStackPathConstructor = newMock JavaScriptStackPathConstructor
+
 
         expect(pc.constructDispatchPath("modules")).andReturn("/modules")
+        expect(pc.constructDispatchPath("assets", "stack")).andReturn("/assets/stack")
 
         expect(request.path).andReturn(path)
 
@@ -28,7 +33,8 @@ class ModuleDispatcherTests extends TestBase {
 
         replay()
 
-        def handler = new ModuleDispatcher(null, null, new QuietOperationTracker(), pc, "modules", false)
+        def handler = new ModuleDispatcher(null, null, new QuietOperationTracker(), pc,
+          javaScriptStackSource, javaScriptStackPathConstructor, "modules", "assets", false)
 
         assert handler.dispatch(request, response) == true
 
@@ -52,8 +58,12 @@ class ModuleDispatcherTests extends TestBase {
         def request = newMock Request
         def response = newMock Response
         def pc = newMock PathConstructor
+        def javaScriptStackSource = newMock JavaScriptStackSource
+        def javaScriptStackPathConstructor = newMock JavaScriptStackPathConstructor
+
 
         expect(pc.constructDispatchPath("modules")).andReturn("/modules")
+        expect(pc.constructDispatchPath("assets", "stack")).andReturn("/assets/stack")
 
         expect(request.path).andReturn("/modules/foo/bar.js")
 
@@ -61,9 +71,46 @@ class ModuleDispatcherTests extends TestBase {
 
         expect(response.sendError(EasyMock.eq(HttpServletResponse.SC_NOT_FOUND), EasyMock.notNull()))
 
+        expect(javaScriptStackSource.getStackNames()).andReturn([])
+
+        replay()
+
+        def handler = new ModuleDispatcher(manager, null, new QuietOperationTracker(), pc,
+          javaScriptStackSource, javaScriptStackPathConstructor, "modules", "assets", false)
+
+        assert handler.dispatch(request, response) == true
+
+        verify()
+    }
+
+    @Test
+    //TAP5-2238
+    void "redirect if module is part of a stack"() {
+
+        def manager = newMock ModuleManager
+        def request = newMock Request
+        def response = newMock Response
+        def pc = newMock PathConstructor
+        def stack = newMock JavaScriptStack
+        def javaScriptStackSource = newMock JavaScriptStackSource
+        def javaScriptStackPathConstructor = newMock JavaScriptStackPathConstructor
+
+
+        expect(pc.constructDispatchPath("modules")).andReturn("/modules")
+        expect(pc.constructDispatchPath("assets", "stack")).andReturn("/assets/stack")
+
+        expect(request.path).andReturn("/modules/foo/bar.js")
+
+        expect(javaScriptStackSource.getStackNames()).andReturn(["default"])
+        expect(javaScriptStackSource.getStack("default")).andReturn(stack)
+        expect(stack.getModules()).andReturn(["foo/bar"])
+        expect(javaScriptStackPathConstructor.constructPathsForJavaScriptStack("default")).andReturn(["/assets/stack/default.js"])
+        expect(response.sendRedirect("/assets/stack/default.js"))
+
         replay()
 
-        def handler = new ModuleDispatcher(manager, null, new QuietOperationTracker(), pc, "modules", false)
+        def handler = new ModuleDispatcher(manager, null, new QuietOperationTracker(), pc,
+          javaScriptStackSource, javaScriptStackPathConstructor, "modules", "assets", false)
 
         assert handler.dispatch(request, response) == true