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