Author: mhermanto
Date: Mon Jul 18 20:10:13 2011
New Revision: 1148035
URL: http://svn.apache.org/viewvc?rev=1148035&view=rev
Log:
Avoid dual-mode deferred (and immediate) export JS processor.
http://codereview.appspot.com/4748053/
Added:
shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/js/DeferredExportJsProcessor.java
shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/js/DeferredExportJsProcessorTest.java
Modified:
shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/js/ExportJsProcessor.java
shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/js/JsServingPipelineModule.java
shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/js/ExportJsProcessorTest.java
Added:
shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/js/DeferredExportJsProcessor.java
URL:
http://svn.apache.org/viewvc/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/js/DeferredExportJsProcessor.java?rev=1148035&view=auto
==============================================================================
---
shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/js/DeferredExportJsProcessor.java
(added)
+++
shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/js/DeferredExportJsProcessor.java
Mon Jul 18 20:10:13 2011
@@ -0,0 +1,97 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations under the License.
+ */
+package org.apache.shindig.gadgets.js;
+
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Joiner;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+import com.google.inject.Inject;
+import com.google.inject.Provider;
+
+import org.apache.shindig.gadgets.GadgetContext;
+import org.apache.shindig.gadgets.GadgetException;
+import org.apache.shindig.gadgets.JsCompileMode;
+import org.apache.shindig.gadgets.features.ApiDirective;
+import org.apache.shindig.gadgets.features.FeatureRegistry;
+import org.apache.shindig.gadgets.features.FeatureRegistry.FeatureBundle;
+import org.apache.shindig.gadgets.features.FeatureRegistry.LookupResult;
+import org.apache.shindig.gadgets.features.FeatureRegistryProvider;
+import org.apache.shindig.gadgets.features.FeatureResource;
+import org.apache.shindig.gadgets.uri.JsUriManager.JsUri;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+
+public class DeferredExportJsProcessor extends ExportJsProcessor {
+
+ @VisibleForTesting
+ static final String FEATURE_NAME = "exportjs";
+
+ private static final String FUNCTION_NAME = "exportJs";
+
+ @Inject
+ public DeferredExportJsProcessor(FeatureRegistryProvider
featureRegistryProvider,
+ Provider<GadgetContext> context) {
+ super(featureRegistryProvider, context);
+ }
+
+ @Override
+ public boolean process(JsRequest jsRequest, JsResponseBuilder builder)
throws JsException {
+ JsUri jsUri = jsRequest.getJsUri();
+ ImmutableList.Builder<JsContent> resp = ImmutableList.builder();
+
+ FeatureRegistry featureRegistry;
+ try {
+ featureRegistry = featureRegistryProvider.get(jsUri.getRepository());
+ } catch (GadgetException e) {
+ throw new JsException(e.getHttpStatusCode(), e.getMessage());
+ }
+
+ boolean neededExportJs = false;
+ FeatureBundle last = null;
+ if (jsUri.isJsload()) {
+ // append all exports for deferred symbols
+ neededExportJs = appendExportJsStatementsDeferred(featureRegistry, resp,
jsRequest);
+ }
+
+ builder.clearJs();
+ if (neededExportJs) {
+ builder.appendAllJs(getExportJsContents(featureRegistry));
+ }
+ builder.appendAllJs(resp.build());
+ return true;
+ }
+
+ private boolean appendExportJsStatementsDeferred(FeatureRegistry registry,
+ ImmutableList.Builder<JsContent> builder, JsRequest jsRequest) {
+ LookupResult lookup = registry.getFeatureResources(context.get(),
+ jsRequest.getNewFeatures(), null, false);
+
+ boolean neededExports = false;
+ for (FeatureBundle bundle : lookup.getBundles()) {
+ if (bundle.isSupportDefer()) {
+ neededExports |= appendExportJsStatementsForFeature(builder,
jsRequest.getJsUri(), bundle);
+ }
+ }
+
+ return neededExports;
+ }
+}
Modified:
shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/js/ExportJsProcessor.java
URL:
http://svn.apache.org/viewvc/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/js/ExportJsProcessor.java?rev=1148035&r1=1148034&r2=1148035&view=diff
==============================================================================
---
shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/js/ExportJsProcessor.java
(original)
+++
shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/js/ExportJsProcessor.java
Mon Jul 18 20:10:13 2011
@@ -47,25 +47,14 @@ public class ExportJsProcessor implement
private static final String FUNCTION_NAME = "exportJs";
- private final FeatureRegistryProvider featureRegistryProvider;
- private final Provider<GadgetContext> context;
- private final boolean deferredMode;
+ protected final FeatureRegistryProvider featureRegistryProvider;
+ protected final Provider<GadgetContext> context;
@Inject
public ExportJsProcessor(FeatureRegistryProvider featureRegistryProvider,
Provider<GadgetContext> context) {
- this(featureRegistryProvider, context, false);
- }
-
- private ExportJsProcessor(FeatureRegistryProvider featureRegistryProvider,
- Provider<GadgetContext> context, boolean defer) {
this.featureRegistryProvider = featureRegistryProvider;
this.context = context;
- this.deferredMode = defer;
- }
-
- public JsProcessor getDeferredInstance() {
- return new ExportJsProcessor(featureRegistryProvider, context, true);
}
public boolean process(JsRequest jsRequest, JsResponseBuilder builder)
throws JsException {
@@ -93,9 +82,6 @@ public class ExportJsProcessor implement
if (last != null) {
neededExportJs |= appendExportJsStatementsForFeature(resp, jsUri,
last);
}
- } else if (deferredMode) {
- // append all exports for deferred symbols
- neededExportJs = appendExportJsStatementsDeferred(featureRegistry, resp,
jsRequest);
}
builder.clearJs();
@@ -106,7 +92,7 @@ public class ExportJsProcessor implement
return true;
}
- private boolean
appendExportJsStatementsForFeature(ImmutableList.Builder<JsContent> builder,
+ protected boolean
appendExportJsStatementsForFeature(ImmutableList.Builder<JsContent> builder,
JsUri jsUri, FeatureBundle bundle) {
List<String> exports = Lists.newArrayList();
@@ -133,22 +119,7 @@ public class ExportJsProcessor implement
return false;
}
- private boolean appendExportJsStatementsDeferred(FeatureRegistry registry,
- ImmutableList.Builder<JsContent> builder, JsRequest jsRequest) {
- LookupResult lookup = registry.getFeatureResources(context.get(),
- jsRequest.getNewFeatures(), null, false);
-
- boolean neededExports = false;
- for (FeatureBundle bundle : lookup.getBundles()) {
- if (bundle.isSupportDefer()) {
- neededExports |= appendExportJsStatementsForFeature(builder,
jsRequest.getJsUri(), bundle);
- }
- }
-
- return neededExports;
- }
-
- private List<JsContent> getExportJsContents(FeatureRegistry featureRegistry)
{
+ protected List<JsContent> getExportJsContents(FeatureRegistry
featureRegistry) {
ImmutableList.Builder<JsContent> result = ImmutableList.builder();
LookupResult lookup = featureRegistry.getFeatureResources(context.get(),
ImmutableList.of(FEATURE_NAME), null);
Modified:
shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/js/JsServingPipelineModule.java
URL:
http://svn.apache.org/viewvc/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/js/JsServingPipelineModule.java?rev=1148035&r1=1148034&r2=1148035&view=diff
==============================================================================
---
shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/js/JsServingPipelineModule.java
(original)
+++
shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/js/JsServingPipelineModule.java
Mon Jul 18 20:10:13 2011
@@ -41,6 +41,7 @@ public class JsServingPipelineModule ext
@Named("shindig.js.optional-processors")
public List<JsProcessor> provideProcessors(
AddJslInfoVariableProcessor addJslInfoVariableProcessor,
+ DeferredExportJsProcessor deferredExportJsProcessor,
JsLoadProcessor jsLoaderGeneratorProcessor,
IfModifiedSinceProcessor ifModifiedSinceProcessor,
GetJsContentProcessor getJsContentProcessor,
@@ -53,7 +54,7 @@ public class JsServingPipelineModule ext
jsLoaderGeneratorProcessor.setUseAsync(true);
return ImmutableList.of(
addJslInfoVariableProcessor,
- exportJsProcessor.getDeferredInstance(),
+ deferredExportJsProcessor,
jsLoaderGeneratorProcessor,
ifModifiedSinceProcessor,
getJsContentProcessor,
Added:
shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/js/DeferredExportJsProcessorTest.java
URL:
http://svn.apache.org/viewvc/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/js/DeferredExportJsProcessorTest.java?rev=1148035&view=auto
==============================================================================
---
shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/js/DeferredExportJsProcessorTest.java
(added)
+++
shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/js/DeferredExportJsProcessorTest.java
Mon Jul 18 20:10:13 2011
@@ -0,0 +1,186 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations under the License.
+ */
+package org.apache.shindig.gadgets.js;
+
+import static org.easymock.EasyMock.createMock;
+import static org.easymock.EasyMock.eq;
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.isA;
+import static org.easymock.EasyMock.replay;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Lists;
+import com.google.inject.Provider;
+import com.google.inject.util.Providers;
+
+import org.apache.shindig.gadgets.GadgetContext;
+import org.apache.shindig.gadgets.JsCompileMode;
+import org.apache.shindig.gadgets.features.ApiDirective;
+import org.apache.shindig.gadgets.features.FeatureRegistry;
+import org.apache.shindig.gadgets.features.FeatureRegistry.FeatureBundle;
+import org.apache.shindig.gadgets.features.FeatureRegistry.LookupResult;
+import org.apache.shindig.gadgets.features.FeatureRegistryProvider;
+import org.apache.shindig.gadgets.features.FeatureResource;
+import org.apache.shindig.gadgets.uri.JsUriManager.JsUri;
+import org.easymock.EasyMock;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.util.List;
+
+public class DeferredExportJsProcessorTest {
+ private final String EXPORT_JS_DEB = "function exportJs() { };";
+
+ private final List<String> EXPORTS_1 = ImmutableList.of(
+ "gadgets",
+ "gadgets.rpc.call",
+ "shindig",
+ "shindig.random");
+
+ private final List<String> EXPORTS_2 = ImmutableList.of(
+ "foo",
+ "foo.prototype.bar");
+
+ private final String EXPORT_STRING_1_DEFER =
+ "exportJs('gadgets',[window.gadgets],{},1);" +
+ "exportJs('shindig',[window.shindig],{},1);" +
+ "exportJs('gadgets.rpc',[window.gadgets,gadgets.rpc],{call:'call'},1);" +
+ "exportJs('shindig',[window.shindig],{random:'random'},1);";
+
+ private final List<String> LIBS_WITH_DEFER = Lists.newArrayList("lib1");
+ private final List<String> LIBS_WITHOUT_DEFER = Lists.newArrayList("lib2");
+ private final List<String> LOADED = Lists.newArrayList();
+
+ private DeferredExportJsProcessor compiler;
+ private FeatureRegistry featureRegistry;
+
+ @Before
+ public void setUp() throws Exception {
+ GadgetContext ctx = new GadgetContext();
+ Provider<GadgetContext> contextProviderMock = Providers.of(ctx);
+ FeatureResource resource = mockResource(EXPORT_JS_DEB);
+ FeatureRegistry.FeatureBundle bundle = mockExportJsBundle(resource);
+ LookupResult lookupMock = mockLookupResult(bundle);
+ final FeatureRegistry featureRegistryMock = mockRegistry(lookupMock);
+ featureRegistry = featureRegistryMock;
+ FeatureRegistryProvider registryProvider = new FeatureRegistryProvider() {
+ public FeatureRegistry get(String repository) {
+ return featureRegistryMock;
+ }
+ };
+ compiler = new DeferredExportJsProcessor(registryProvider,
contextProviderMock);
+ }
+
+ @Test
+ public void testProcessWithOneNonEmptyFeatureDeferred() throws Exception {
+ JsUri jsUri = mockJsUri(JsCompileMode.CONCAT_COMPILE_EXPORT_ALL, true,
LIBS_WITH_DEFER);
+ JsRequest jsRequest = new JsRequest(jsUri, null, false, featureRegistry);
+ JsResponseBuilder jsBuilder = new JsResponseBuilder();
+ boolean actualReturnCode = compiler.process(jsRequest, jsBuilder);
+ assertTrue(actualReturnCode);
+ assertEquals(
+ EXPORT_JS_DEB + EXPORT_STRING_1_DEFER,
+ jsBuilder.build().toJsString());
+ }
+
+ @Test
+ public void testProcessWithOneNonEmptyFeatureDeferredNotSupported() throws
Exception {
+ JsUri jsUri = mockJsUri(JsCompileMode.CONCAT_COMPILE_EXPORT_ALL, true,
LIBS_WITHOUT_DEFER);
+ JsRequest jsRequest = new JsRequest(jsUri, null, false, featureRegistry);
+ JsResponseBuilder jsBuilder = new JsResponseBuilder();
+ boolean actualReturnCode = compiler.process(jsRequest, jsBuilder);
+ assertTrue(actualReturnCode);
+ assertEquals(
+ "",
+ jsBuilder.build().toJsString());
+ }
+
+ @SuppressWarnings("unchecked")
+ private FeatureRegistry mockRegistry(LookupResult lookupMock) {
+ FeatureRegistry result = createMock(FeatureRegistry.class);
+ expect(result.getFeatureResources(
+ isA(GadgetContext.class), isA(List.class),
EasyMock.isNull(List.class))).
+ andReturn(lookupMock).anyTimes();
+ expect(result.getFeatureResources(
+ isA(GadgetContext.class), eq(LIBS_WITH_DEFER),
EasyMock.isNull(List.class), eq(false))).
+ andReturn(mockLookupResult(mockBundle(EXPORTS_1, true))).anyTimes();
+ expect(result.getFeatureResources(
+ isA(GadgetContext.class), eq(LIBS_WITHOUT_DEFER),
EasyMock.isNull(List.class), eq(false))).
+ andReturn(mockLookupResult(mockBundle(EXPORTS_2, false))).anyTimes();
+
expect(result.getFeatures(LIBS_WITHOUT_DEFER)).andReturn(LIBS_WITHOUT_DEFER).anyTimes();
+
expect(result.getFeatures(LIBS_WITH_DEFER)).andReturn(LIBS_WITH_DEFER).anyTimes();
+ expect(result.getFeatures(LOADED)).andReturn(LOADED).anyTimes();
+ replay(result);
+ return result;
+ }
+
+ private JsUri mockJsUri(JsCompileMode mode, boolean isJsload, List<String>
libs) {
+ JsUri result = createMock(JsUri.class);
+ expect(result.getCompileMode()).andStubReturn(mode);
+ expect(result.getRepository()).andStubReturn(null);
+ expect(result.isJsload()).andReturn(isJsload).anyTimes();
+ expect(result.getLibs()).andReturn(libs).anyTimes();
+ expect(result.getLoadedLibs()).andReturn(LOADED).anyTimes();
+ replay(result);
+ return result;
+ }
+
+ private LookupResult mockLookupResult(FeatureRegistry.FeatureBundle
featureBundle) {
+ LookupResult result = createMock(LookupResult.class);
+
expect(result.getBundles()).andReturn(ImmutableList.of(featureBundle)).anyTimes();
+ replay(result);
+ return result;
+ }
+
+ private FeatureResource mockResource(String debContent) {
+ FeatureResource result = createMock(FeatureResource.class);
+ expect(result.getDebugContent()).andReturn(debContent).anyTimes();
+ expect(result.getName()).andReturn("js").anyTimes();
+ replay(result);
+ return result;
+ }
+
+ private FeatureBundle mockBundle(List<String> exports, boolean isDefer) {
+ List<ApiDirective> apis = Lists.newArrayList();
+ for (String e : exports) apis.add(mockApiDirective(true, e));
+ FeatureBundle result = createMock(FeatureBundle.class);
+ expect(result.getApis(ApiDirective.Type.JS,
true)).andReturn(exports).anyTimes();
+ expect(result.isSupportDefer()).andReturn(isDefer).anyTimes();
+ replay(result);
+ return result;
+ }
+
+ private FeatureBundle mockExportJsBundle(FeatureResource
featureResourceMock) {
+ FeatureRegistry.FeatureBundle featureBundle =
createMock(FeatureBundle.class);
+ expect(featureBundle.getResources()).andReturn(
+ ImmutableList.of(featureResourceMock)).anyTimes();
+ replay(featureBundle);
+ return featureBundle;
+ }
+
+ private ApiDirective mockApiDirective(boolean isExports, String value) {
+ ApiDirective result = createMock(ApiDirective.class);
+ expect(result.getType()).andReturn(ApiDirective.Type.JS).anyTimes();
+ expect(result.getValue()).andReturn(value).anyTimes();
+ expect(result.isExports()).andReturn(isExports).anyTimes();
+ replay(result);
+ return result;
+ }
+}
Modified:
shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/js/ExportJsProcessorTest.java
URL:
http://svn.apache.org/viewvc/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/js/ExportJsProcessorTest.java?rev=1148035&r1=1148034&r2=1148035&view=diff
==============================================================================
---
shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/js/ExportJsProcessorTest.java
(original)
+++
shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/js/ExportJsProcessorTest.java
Mon Jul 18 20:10:13 2011
@@ -126,7 +126,7 @@ public class ExportJsProcessorTest {
andReturn(lookupMock).anyTimes();
expect(result.getFeatureResources(
isA(GadgetContext.class), eq(LIBS_DEFER), EasyMock.isNull(List.class),
eq(false))).
- andReturn(mockLookupResult(mockBundle(EXPORTS_1, true))).anyTimes();
+ andReturn(mockLookupResult(mockBundle(EXPORTS_1))).anyTimes();
expect(result.getFeatureResources(
isA(GadgetContext.class), eq(LIBS), EasyMock.isNull(List.class),
eq(false))).
andReturn(mockLookupResult(mockBundle(EXPORTS_2))).anyTimes();
@@ -172,15 +172,11 @@ public class ExportJsProcessorTest {
}
private FeatureBundle mockBundle(List<String> exports) {
- return mockBundle(exports, false);
- }
-
- private FeatureBundle mockBundle(List<String> exports, boolean isDefer) {
List<ApiDirective> apis = Lists.newArrayList();
for (String e : exports) apis.add(mockApiDirective(true, e));
FeatureBundle result = createMock(FeatureBundle.class);
expect(result.getApis(ApiDirective.Type.JS,
true)).andReturn(exports).anyTimes();
- expect(result.isSupportDefer()).andReturn(isDefer).anyTimes();
+ expect(result.isSupportDefer()).andReturn(false).anyTimes();
replay(result);
return result;
}
@@ -237,31 +233,7 @@ public class ExportJsProcessorTest {
EXPORT_JS_DEB + FEATURE_CONTENT_1 + EXPORT_STRING_1,
jsBuilder.build().toJsString());
}
-
- @Test
- public void testProcessWithOneNonEmptyFeatureDeferred() throws Exception {
- JsUri jsUri = mockJsUri(JsCompileMode.CONCAT_COMPILE_EXPORT_ALL, true,
LIBS_DEFER);
- JsRequest jsRequest = new JsRequest(jsUri, null, false, featureRegistry);
- JsResponseBuilder jsBuilder = new JsResponseBuilder();
- boolean actualReturnCode =
compiler.getDeferredInstance().process(jsRequest, jsBuilder);
- assertTrue(actualReturnCode);
- assertEquals(
- EXPORT_JS_DEB + EXPORT_STRING_1_DEFER,
- jsBuilder.build().toJsString());
- }
-
- @Test
- public void testProcessWithOneNonEmptyFeatureDeferredNotSupported() throws
Exception {
- JsUri jsUri = mockJsUri(JsCompileMode.CONCAT_COMPILE_EXPORT_ALL, true,
LIBS); // !deferred
- JsRequest jsRequest = new JsRequest(jsUri, null, false, featureRegistry);
- JsResponseBuilder jsBuilder = new JsResponseBuilder();
- boolean actualReturnCode =
compiler.getDeferredInstance().process(jsRequest, jsBuilder);
- assertTrue(actualReturnCode);
- assertEquals(
- "",
- jsBuilder.build().toJsString());
- }
-
+
@Test
public void testProcessWithOneNonEmptyFeatureNotDeferredMode() throws
Exception {
JsUri jsUri = mockJsUri(JsCompileMode.CONCAT_COMPILE_EXPORT_ALL, true);