You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@shindig.apache.org by mh...@apache.org on 2011/04/05 05:08:52 UTC

svn commit: r1088872 - in /shindig/trunk/java/gadgets/src: main/java/org/apache/shindig/gadgets/js/ main/java/org/apache/shindig/gadgets/rewrite/js/ main/java15/org/apache/shindig/gadgets/js/ main/java16/org/apache/shindig/gadgets/js/ main/java16/org/a...

Author: mhermanto
Date: Tue Apr  5 03:08:51 2011
New Revision: 1088872

URL: http://svn.apache.org/viewvc?rev=1088872&view=rev
Log:
- Replace ExportJsCompiler with Processor.
- Pulls-in feature externs.
http://codereview.appspot.com/4352049/

Added:
    shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/js/ExportJsProcessor.java
    shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/js/ExportJsProcessorTest.java
Removed:
    shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/rewrite/js/ExportJsCompiler.java
    shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/rewrite/js/ExportJsCompilerTest.java
Modified:
    shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/js/CompilationProcessor.java
    shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/js/JsResponseBuilder.java
    shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/js/JsServingPipelineModule.java
    shindig/trunk/java/gadgets/src/main/java15/org/apache/shindig/gadgets/js/JsCompilerModule.java
    shindig/trunk/java/gadgets/src/main/java16/org/apache/shindig/gadgets/js/JsCompilerModule.java
    shindig/trunk/java/gadgets/src/main/java16/org/apache/shindig/gadgets/rewrite/js/ClosureJsCompiler.java
    shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/js/CompilationProcessorTest.java
    shindig/trunk/java/gadgets/src/test/java16/org/apache/shindig/gadgets/rewrite/js/ClosureJsCompilerTest.java

Modified: shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/js/CompilationProcessor.java
URL: http://svn.apache.org/viewvc/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/js/CompilationProcessor.java?rev=1088872&r1=1088871&r2=1088872&view=diff
==============================================================================
--- shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/js/CompilationProcessor.java (original)
+++ shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/js/CompilationProcessor.java Tue Apr  5 03:08:51 2011
@@ -17,21 +17,21 @@
  */
 package org.apache.shindig.gadgets.js;
 
-import java.util.List;
-
-import org.apache.shindig.gadgets.rewrite.js.JsCompiler;
-
 import com.google.common.collect.ImmutableList;
 import com.google.inject.Inject;
 
+import org.apache.shindig.gadgets.features.ApiDirective;
+import org.apache.shindig.gadgets.features.FeatureRegistry.FeatureBundle;
+import org.apache.shindig.gadgets.rewrite.js.JsCompiler;
+
 public class CompilationProcessor implements JsProcessor {
   private final JsCompiler compiler;
-  
+
   @Inject
   public CompilationProcessor(JsCompiler compiler) {
     this.compiler = compiler;
   }
-      
+
   /**
    * Compile content in the inbound JsResponseBuilder.
    * TODO: Re-add support for externs here if they're ever used.
@@ -39,9 +39,16 @@ public class CompilationProcessor implem
    */
   public boolean process(JsRequest request, JsResponseBuilder builder)
       throws JsException {
-    List<String> externs = ImmutableList.of();
+    ImmutableList.Builder<String> externsBuilder = ImmutableList.builder();
+    for (JsContent jsc : builder.build().getAllJsContent()) {
+      FeatureBundle bundle = jsc.getFeatureBundle();
+      if (bundle != null) {
+        externsBuilder.addAll(bundle.getApis(ApiDirective.Type.JS, false));
+      }
+    }
+
     JsResponse result = compiler.compile(request.getJsUri(),
-        builder.build().getAllJsContent(), externs);
+        builder.build().getAllJsContent(), externsBuilder.build());
     builder.clearJs().appendAllJs(result.getAllJsContent());
     return true;
   }

Added: 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=1088872&view=auto
==============================================================================
--- shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/js/ExportJsProcessor.java (added)
+++ shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/js/ExportJsProcessor.java Tue Apr  5 03:08:51 2011
@@ -0,0 +1,219 @@
+/*
+ * 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.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.FeatureResource;
+import org.apache.shindig.gadgets.uri.JsUriManager.JsUri;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+
+public class ExportJsProcessor implements JsProcessor {
+
+  @VisibleForTesting
+  static final String FEATURE_NAME = "exportjs";
+
+  private static final String FUNCTION_NAME = "exportJs";
+
+  private final FeatureRegistry featureRegistry;
+  private final Provider<GadgetContext> context;
+
+  @Inject
+  public ExportJsProcessor(FeatureRegistry featureRegistry, Provider<GadgetContext> context) {
+    this.featureRegistry = featureRegistry;
+    this.context = context;
+  }
+
+  public boolean process(JsRequest jsRequest, JsResponseBuilder builder) {
+    JsUri jsUri = jsRequest.getJsUri();
+    ImmutableList.Builder<JsContent> resp = ImmutableList.builder();
+
+    boolean neededExportJs = false;
+    FeatureBundle last = null;
+    for (JsContent jsc : builder.build().getAllJsContent()) {
+      FeatureBundle current = jsc.getFeatureBundle();
+      if (last != null && current != last) {
+        neededExportJs |= appendExportJsStatementsForFeature(resp, jsUri, last);
+      }
+      resp.add(jsc);
+      last = current;
+    }
+    if (last != null) {
+      neededExportJs |= appendExportJsStatementsForFeature(resp, jsUri, last);
+    }
+
+    builder.clearJs();
+    if (neededExportJs) {
+      builder.appendAllJs(getExportJsContents());
+    }
+    builder.appendAllJs(resp.build());
+    return true;
+  }
+
+  private boolean appendExportJsStatementsForFeature(ImmutableList.Builder<JsContent> builder,
+      JsUri jsUri, FeatureBundle bundle) {
+    List<String> exports = Lists.newArrayList();
+
+    // Add exports of bundle, regardless.
+    if (jsUri.getCompileMode() == JsCompileMode.ALL_RUN_TIME) {
+      exports = bundle.getApis(ApiDirective.Type.JS, true);
+
+    // Add exports of bundle if it is an explicitly-specified feature.
+    } else if (jsUri.getCompileMode() == JsCompileMode.EXPLICIT_RUN_TIME) {
+      if (jsUri.getLibs().contains(bundle.getName())) {
+        exports = bundle.getApis(ApiDirective.Type.JS, true);
+      }
+    }
+
+    if (!exports.isEmpty()) {
+      StringBuilder sb = new StringBuilder();
+      for (Input input : generateInputs(exports)) {
+        sb.append(input.toExportStatement());
+      }
+      builder.add(JsContent.fromFeature(sb.toString(),
+          "[generated-symbol-exports]", bundle, null));
+      return true;
+    }
+    return false;
+  }
+
+  private List<JsContent> getExportJsContents() {
+    ImmutableList.Builder<JsContent> result = ImmutableList.builder();
+    LookupResult lookup = featureRegistry.getFeatureResources(context.get(),
+        ImmutableList.of(FEATURE_NAME), null);
+    for (FeatureBundle bundle : lookup.getBundles()) {
+      for (FeatureResource resource : bundle.getResources()) {
+        result.add(JsContent.fromFeature(
+            resource.getDebugContent(), resource.getName(),
+            bundle, resource));
+      }
+    }
+    return result.build();
+  }
+
+  private static class Input {
+    String namespace;
+    List<String> components;
+    List<String> properties;
+
+    private Input(String namespace, List<String> components) {
+      this.namespace = namespace;
+      this.components = components;
+      this.properties = Lists.newArrayList();
+    }
+
+    static Input newGlobal() {
+      return new Input(null, ImmutableList.<String>of());
+    }
+
+    static Input newLocal(String namespace, List<String> components) {
+      return new Input(namespace, components);
+    }
+
+    public String toExportStatement() {
+      StringBuilder result = new StringBuilder();
+
+      // Local namespace.
+      if (namespace != null) {
+        result.append(FUNCTION_NAME).append("('").append(namespace).append("',[");
+        result.append(Joiner.on(',').join(components));
+        result.append("],{");
+        for (int i = 0; i < properties.size(); i++) {
+          String prop = properties.get(i);
+          if (i > 0) result.append(",");
+          result.append(prop).append(":'").append(prop).append("'");
+        }
+        result.append("});");
+
+      // Global/window namespace.
+      } else {
+        for (int i = 0; i < properties.size(); i++) {
+          String prop = properties.get(i);
+          result.append(FUNCTION_NAME).append("(");
+          result.append("'").append(prop).append("',[").append(prop);
+          result.append("]);");
+        }
+      }
+      return result.toString();
+    }
+  }
+
+  private List<String> expandNamespace(String namespace) {
+    List<String> result = Lists.newArrayList();
+    for (int from = 0; ;) {
+      int idx = namespace.indexOf('.', from);
+      if (idx >= 0) {
+        result.add(namespace.substring(0, idx));
+        from = idx + 1;
+      } else {
+        result.add(namespace);
+        break;
+      }
+    }
+    return result;
+  }
+
+  private Collection<Input> generateInputs(List<String> symbols) {
+    Map<String, Input> result = Maps.newLinkedHashMap();
+    for (String symbol : symbols) {
+      String ns = getNamespace(symbol);
+      Input input = result.get(ns);
+      if (input == null) {
+        input = (ns != null) ? Input.newLocal(ns, expandNamespace(ns)) : Input.newGlobal();
+        result.put(ns, input);
+      }
+      String property = (ns != null) ? getProperty(symbol) : symbol;
+      input.properties.add(property);
+    }
+    return result.values();
+  }
+
+  /**
+   * Return the namespace for symbol (before last dot). If symbol is global,
+   * return null, to indicate "window" namespace.
+   */
+  private String getNamespace(String symbol) {
+    int idx = symbol.lastIndexOf('.');
+    return (idx >= 0) ? symbol.substring(0, idx) : null;
+  }
+
+  /**
+   * Return the property of symbol (after last dot). If symbol is global,
+   * return the original string.
+   */
+  private String getProperty(String symbol) {
+    int idx = symbol.lastIndexOf('.');
+    return (idx >= 0) ? symbol.substring(idx + 1) : symbol;
+  }
+
+}

Modified: shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/js/JsResponseBuilder.java
URL: http://svn.apache.org/viewvc/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/js/JsResponseBuilder.java?rev=1088872&r1=1088871&r2=1088872&view=diff
==============================================================================
--- shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/js/JsResponseBuilder.java (original)
+++ shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/js/JsResponseBuilder.java Tue Apr  5 03:08:51 2011
@@ -56,6 +56,22 @@ public class JsResponseBuilder {
   }
 
   /**
+   * Prepend a JS to the response.
+   */
+  public JsResponseBuilder prependJs(JsContent jsContent) {
+    jsCode.addFirst(jsContent);
+    return this;
+  }
+
+  /**
+   * Insert a JS at a specific index.
+   */
+  public JsResponseBuilder insertJsAt(int index, JsContent jsContent) {
+    jsCode.add(index, jsContent);
+    return this;
+  }
+
+  /**
    * Appends more JS to the response.
    */
   public JsResponseBuilder appendJs(JsContent jsContent) {

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=1088872&r1=1088871&r2=1088872&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 Tue Apr  5 03:08:51 2011
@@ -15,7 +15,7 @@
  * 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.collect.ImmutableList;
@@ -43,6 +43,7 @@ public class JsServingPipelineModule ext
       IfModifiedSinceProcessor ifModifiedSinceProcessor,
       GetJsContentProcessor getJsContentProcessor,
       CajaJsSubtractingProcessor cajaJsSubtractingProcessor,
+      ExportJsProcessor exportJsProcessor,
       SeparatorCommentingProcessor separatorCommentingProcessor,
       ConfigInjectionProcessor configInjectionProcessor,
       AddOnloadFunctionProcessor addOnloadFunctionProcessor,
@@ -55,6 +56,7 @@ public class JsServingPipelineModule ext
         ifModifiedSinceProcessor,
         getJsContentProcessor,
         cajaJsSubtractingProcessor,
+        exportJsProcessor,
         separatorCommentingProcessor,
         configInjectionProcessor,
         addOnloadFunctionProcessor,
@@ -62,5 +64,5 @@ public class JsServingPipelineModule ext
         compilationProcessor,
         anonFuncProcessor);
   }
-  
+
 }

Modified: shindig/trunk/java/gadgets/src/main/java15/org/apache/shindig/gadgets/js/JsCompilerModule.java
URL: http://svn.apache.org/viewvc/shindig/trunk/java/gadgets/src/main/java15/org/apache/shindig/gadgets/js/JsCompilerModule.java?rev=1088872&r1=1088871&r2=1088872&view=diff
==============================================================================
--- shindig/trunk/java/gadgets/src/main/java15/org/apache/shindig/gadgets/js/JsCompilerModule.java (original)
+++ shindig/trunk/java/gadgets/src/main/java15/org/apache/shindig/gadgets/js/JsCompilerModule.java Tue Apr  5 03:08:51 2011
@@ -22,7 +22,6 @@ import com.google.inject.Inject;
 import com.google.inject.Provides;
 
 import org.apache.shindig.gadgets.rewrite.js.JsCompiler;
-import org.apache.shindig.gadgets.rewrite.js.ExportJsCompiler;
 
 import java.util.List;
 
@@ -35,11 +34,4 @@ public class JsCompilerModule extends Ab
   protected void configure() {
     // nothing to configure here
   }
-
-  @Provides
-  @Inject
-  public JsCompiler provideJsCompiler(ExportJsCompiler compiler) {
-    return compiler;
-  }
-  
 }

Modified: shindig/trunk/java/gadgets/src/main/java16/org/apache/shindig/gadgets/js/JsCompilerModule.java
URL: http://svn.apache.org/viewvc/shindig/trunk/java/gadgets/src/main/java16/org/apache/shindig/gadgets/js/JsCompilerModule.java?rev=1088872&r1=1088871&r2=1088872&view=diff
==============================================================================
--- shindig/trunk/java/gadgets/src/main/java16/org/apache/shindig/gadgets/js/JsCompilerModule.java (original)
+++ shindig/trunk/java/gadgets/src/main/java16/org/apache/shindig/gadgets/js/JsCompilerModule.java Tue Apr  5 03:08:51 2011
@@ -21,7 +21,6 @@ import com.google.inject.AbstractModule;
 import com.google.inject.Inject;
 import com.google.inject.Provides;
 
-import org.apache.shindig.gadgets.rewrite.js.ExportJsCompiler;
 import org.apache.shindig.gadgets.rewrite.js.JsCompiler;
 
 import java.util.List;
@@ -35,11 +34,4 @@ public class JsCompilerModule extends Ab
   protected void configure() {
     // nothing to configure here
   }
-
-  @Provides
-  @Inject
-  public JsCompiler provideJsCompiler(ExportJsCompiler compiler) {
-    return compiler;
-  }
-  
 }

Modified: shindig/trunk/java/gadgets/src/main/java16/org/apache/shindig/gadgets/rewrite/js/ClosureJsCompiler.java
URL: http://svn.apache.org/viewvc/shindig/trunk/java/gadgets/src/main/java16/org/apache/shindig/gadgets/rewrite/js/ClosureJsCompiler.java?rev=1088872&r1=1088871&r2=1088872&view=diff
==============================================================================
--- shindig/trunk/java/gadgets/src/main/java16/org/apache/shindig/gadgets/rewrite/js/ClosureJsCompiler.java (original)
+++ shindig/trunk/java/gadgets/src/main/java16/org/apache/shindig/gadgets/rewrite/js/ClosureJsCompiler.java Tue Apr  5 03:08:51 2011
@@ -45,7 +45,6 @@ import org.apache.shindig.gadgets.js.JsC
 import org.apache.shindig.gadgets.js.JsException;
 import org.apache.shindig.gadgets.js.JsResponse;
 import org.apache.shindig.gadgets.js.JsResponseBuilder;
-import org.apache.shindig.gadgets.rewrite.js.ExportJsCompiler;
 import org.apache.shindig.gadgets.rewrite.js.JsCompiler;
 import org.apache.shindig.gadgets.uri.JsUriManager.JsUri;
 import org.json.JSONArray;
@@ -70,19 +69,14 @@ public class ClosureJsCompiler implement
   @VisibleForTesting
   static final String CACHE_NAME = "CompiledJs";
 
-  private final ExportJsCompiler exportCompiler;
+  private final DefaultJsCompiler defaultCompiler;
   private final Cache<String, JsResponse> cache;
   private JsResponse lastResult;
 
   @Inject
-  public ClosureJsCompiler(CacheProvider cacheProvider, FeatureRegistry registry) {
-    this(new ExportJsCompiler(registry), cacheProvider);
-  }
-
-  @VisibleForTesting
-  ClosureJsCompiler(ExportJsCompiler exportCompiler, CacheProvider cacheProvider) {
+  public ClosureJsCompiler(DefaultJsCompiler defaultCompiler, CacheProvider cacheProvider) {
     this.cache = cacheProvider.createCache(CACHE_NAME);
-    this.exportCompiler = exportCompiler;
+    this.defaultCompiler = defaultCompiler;
   }
 
   public static CompilerOptions defaultCompilerOptions() {
@@ -130,7 +124,7 @@ public class ClosureJsCompiler implement
 
   public JsResponse compile(JsUri jsUri, Iterable<JsContent> content, List<String> externs) 
       throws JsException {
-    JsResponse exportResponse = exportCompiler.compile(jsUri, content, externs);
+    JsResponse exportResponse = defaultCompiler.compile(jsUri, content, externs);
     content = exportResponse.getAllJsContent();
 
     String externStr = toExternString(externs);
@@ -182,7 +176,7 @@ public class ClosureJsCompiler implement
       } else {
         builder.appendJs(compiled, "[compiled]");
       }
-      
+
       builder.setExterns(result.externExport);
     } else {
       // Otherwise, return original content and null exports.
@@ -240,7 +234,7 @@ public class ClosureJsCompiler implement
         return true;
       }
     };
-    List<JsContent> builder = Lists.newLinkedList(exportCompiler.getJsContent(jsUri, bundle));
+    List<JsContent> builder = Lists.newLinkedList(defaultCompiler.getJsContent(jsUri, bundle));
 
     CompilerOptions options = getCompilerOptions();
     if (options.isExternExportsEnabled()) {

Modified: shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/js/CompilationProcessorTest.java
URL: http://svn.apache.org/viewvc/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/js/CompilationProcessorTest.java?rev=1088872&r1=1088871&r2=1088872&view=diff
==============================================================================
--- shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/js/CompilationProcessorTest.java (original)
+++ shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/js/CompilationProcessorTest.java Tue Apr  5 03:08:51 2011
@@ -18,8 +18,10 @@
 package org.apache.shindig.gadgets.js;
 
 import static org.easymock.EasyMock.createControl;
+import static org.easymock.EasyMock.createMock;
 import static org.easymock.EasyMock.eq;
 import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.replay;
 import static org.easymock.EasyMock.same;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
@@ -28,6 +30,8 @@ import static org.junit.Assert.assertTru
 import java.util.Iterator;
 import java.util.List;
 
+import org.apache.shindig.gadgets.features.ApiDirective;
+import org.apache.shindig.gadgets.features.FeatureRegistry.FeatureBundle;
 import org.apache.shindig.gadgets.rewrite.js.JsCompiler;
 import org.apache.shindig.gadgets.uri.JsUriManager.JsUri;
 import org.easymock.IMocksControl;
@@ -35,36 +39,40 @@ import org.junit.Before;
 import org.junit.Test;
 
 import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Lists;
 
 public class CompilationProcessorTest {
   private IMocksControl control;
   private JsCompiler compiler;
   private CompilationProcessor processor;
-  
+
   @Before
   public void setUp() throws Exception {
     control = createControl();
     compiler = control.createMock(JsCompiler.class);
     processor = new CompilationProcessor(compiler);
   }
-  
+
   @Test
   public void compilerIsRun() throws Exception {
     JsUri jsUri = control.createMock(JsUri.class);
+    FeatureBundle bundle = control.createMock(FeatureBundle.class);
     JsResponseBuilder builder =
         new JsResponseBuilder().setCacheTtlSecs(1234).setStatusCode(200)
-          .appendJs("content1:", "source1").appendJs("content2", "source2");
+          .appendJs("content1:", "source1")
+          .appendJs("content2", "source2")
+          .appendJs(JsContent.fromFeature("content3:", null, mockBundle("extern3"), null))
+          .appendJs(JsContent.fromFeature("content4:", null, mockBundle("extern4"), null));
     JsResponse outputResponse = new JsResponseBuilder().appendJs("content3", "s3").build();
     JsRequest request = control.createMock(JsRequest.class);
     expect(request.getJsUri()).andReturn(jsUri);
-    List<String> emptyList = ImmutableList.of();
-    expect(compiler.compile(same(jsUri), eq(builder.build().getAllJsContent()), eq(emptyList)))
-        .andReturn(outputResponse);
-    
+    expect(compiler.compile(same(jsUri), eq(builder.build().getAllJsContent()),
+        eq(Lists.newArrayList("extern3", "extern4")))).andReturn(outputResponse);
+
     control.replay();
     boolean status = processor.process(request, builder);
     control.verify();
-    
+
     assertTrue(status);
     JsResponse compResult = builder.build();
     assertEquals(200, compResult.getStatusCode());
@@ -91,4 +99,12 @@ public class CompilationProcessorTest {
     control.replay();
     processor.process(request, builder);
   }
+
+  private FeatureBundle mockBundle(String... externs) {
+    FeatureBundle result = createMock(FeatureBundle.class);
+    expect(result.getApis(ApiDirective.Type.JS, false)).andReturn(
+        Lists.newArrayList(externs)).anyTimes();
+    replay(result);
+    return result;
+  }
 }

Added: 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=1088872&view=auto
==============================================================================
--- shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/js/ExportJsProcessorTest.java (added)
+++ shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/js/ExportJsProcessorTest.java Tue Apr  5 03:08:51 2011
@@ -0,0 +1,228 @@
+/*
+ * 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.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.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 ExportJsProcessorTest {
+  private final String EXPORT_JS_DEB = "function exportJs() { };";
+  private final String TEXT_CONTENT_1 = "text1;";
+  private final String TEXT_CONTENT_2 = "text2;";
+  private final String FEATURE_CONTENT_1 = "feature1;";
+  private final String FEATURE_CONTENT_2 = "feature2;";
+  private final String FEATURE_CONTENT_3 = "feature3;";
+
+  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 List<String> EXPORTS_3 = ImmutableList.<String>of();
+
+  private final String EXPORT_STRING_1 =
+      "exportJs('gadgets',[gadgets]);" +
+      "exportJs('shindig',[shindig]);" +
+      "exportJs('gadgets.rpc',[gadgets,gadgets.rpc],{call:'call'});" +
+      "exportJs('shindig',[shindig],{random:'random'});";
+
+  private final String EXPORT_STRING_2 =
+      "exportJs('foo',[foo]);" +
+      "exportJs('foo.prototype',[foo,foo.prototype],{bar:'bar'});";
+
+  private final String EXPORT_STRING_3 = "";
+
+  private JsContent textJsContent1;
+  private JsContent textJsContent2;
+  private JsContent featureJsContent1;
+  private JsContent featureJsContent2;
+  private JsContent featureJsContent3;
+  private ExportJsProcessor compiler;
+
+  @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);
+    FeatureRegistry featureRegistryMock = mockRegistry(lookupMock);
+
+    textJsContent1 = JsContent.fromText(TEXT_CONTENT_1, null);
+    textJsContent2 = JsContent.fromText(TEXT_CONTENT_2, null);
+    featureJsContent1 = JsContent.fromFeature(FEATURE_CONTENT_1, null, mockBundle(EXPORTS_1), null);
+    featureJsContent2 = JsContent.fromFeature(FEATURE_CONTENT_2, null, mockBundle(EXPORTS_2), null);
+    featureJsContent3 = JsContent.fromFeature(FEATURE_CONTENT_3, null, mockBundle(EXPORTS_3), null);
+    compiler = new ExportJsProcessor(featureRegistryMock, contextProviderMock);
+  }
+
+  @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();
+    replay(result);
+    return result;
+  }
+
+  private JsUri mockJsUri(JsCompileMode mode) {
+    JsUri result = createMock(JsUri.class);
+    expect(result.getCompileMode()).andReturn(mode).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) {
+    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();
+    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;
+  }
+
+  @Test
+  public void testProcessEmpty() throws Exception {
+    JsUri jsUri = mockJsUri(JsCompileMode.ALL_RUN_TIME);
+    JsRequest jsRequest = new JsRequest(jsUri, null, false);
+    JsResponseBuilder jsBuilder = new JsResponseBuilder();
+    boolean actualReturnCode = compiler.process(jsRequest, jsBuilder);
+    assertTrue(actualReturnCode);
+    assertEquals("", jsBuilder.build().toJsString());
+  }
+
+  @Test
+  public void testProcessWithOneText() throws Exception {
+    JsUri jsUri = mockJsUri(JsCompileMode.ALL_RUN_TIME);
+    JsRequest jsRequest = new JsRequest(jsUri, null, false);
+    JsResponseBuilder jsBuilder = new JsResponseBuilder();
+    jsBuilder.appendJs(textJsContent1);
+    boolean actualReturnCode = compiler.process(jsRequest, jsBuilder);
+    assertTrue(actualReturnCode);
+    assertEquals(
+        TEXT_CONTENT_1,
+        jsBuilder.build().toJsString());
+  }
+
+  @Test
+  public void testProcessWithOneNonEmptyFeature() throws Exception {
+    JsUri jsUri = mockJsUri(JsCompileMode.ALL_RUN_TIME);
+    JsRequest jsRequest = new JsRequest(jsUri, null, false);
+    JsResponseBuilder jsBuilder = new JsResponseBuilder();
+    jsBuilder.appendJs(featureJsContent1);
+    boolean actualReturnCode = compiler.process(jsRequest, jsBuilder);
+    assertTrue(actualReturnCode);
+    assertEquals(
+        EXPORT_JS_DEB + FEATURE_CONTENT_1 + EXPORT_STRING_1,
+        jsBuilder.build().toJsString());
+  }
+
+  @Test
+  public void testProcessWithOneEmptyFeature() throws Exception {
+    JsUri jsUri = mockJsUri(JsCompileMode.ALL_RUN_TIME);
+    JsRequest jsRequest = new JsRequest(jsUri, null, false);
+    JsResponseBuilder jsBuilder = new JsResponseBuilder();
+    jsBuilder.appendJs(featureJsContent3);
+    boolean actualReturnCode = compiler.process(jsRequest, jsBuilder);
+    assertTrue(actualReturnCode);
+    assertEquals(
+        FEATURE_CONTENT_3 + EXPORT_STRING_3,
+        jsBuilder.build().toJsString());
+  }
+
+  @Test
+  public void testProcessWithFeaturesAndTexts() throws Exception {
+    JsUri jsUri = mockJsUri(JsCompileMode.ALL_RUN_TIME);
+    JsRequest jsRequest = new JsRequest(jsUri, null, false);
+    JsResponseBuilder jsBuilder = new JsResponseBuilder();
+    jsBuilder.appendJs(textJsContent1);
+    jsBuilder.appendJs(featureJsContent1);
+    jsBuilder.appendJs(featureJsContent2);
+    jsBuilder.appendJs(textJsContent2);
+    jsBuilder.appendJs(featureJsContent3);
+    boolean actualReturnCode = compiler.process(jsRequest, jsBuilder);
+    assertTrue(actualReturnCode);
+    assertEquals(EXPORT_JS_DEB + TEXT_CONTENT_1 +
+        FEATURE_CONTENT_1 + EXPORT_STRING_1 +
+        FEATURE_CONTENT_2 + EXPORT_STRING_2 +
+        TEXT_CONTENT_2 +
+        FEATURE_CONTENT_3 + EXPORT_STRING_3,
+        jsBuilder.build().toJsString());
+  }
+}

Modified: shindig/trunk/java/gadgets/src/test/java16/org/apache/shindig/gadgets/rewrite/js/ClosureJsCompilerTest.java
URL: http://svn.apache.org/viewvc/shindig/trunk/java/gadgets/src/test/java16/org/apache/shindig/gadgets/rewrite/js/ClosureJsCompilerTest.java?rev=1088872&r1=1088871&r2=1088872&view=diff
==============================================================================
--- shindig/trunk/java/gadgets/src/test/java16/org/apache/shindig/gadgets/rewrite/js/ClosureJsCompilerTest.java (original)
+++ shindig/trunk/java/gadgets/src/test/java16/org/apache/shindig/gadgets/rewrite/js/ClosureJsCompilerTest.java Tue Apr  5 03:08:51 2011
@@ -42,7 +42,7 @@ import org.apache.shindig.gadgets.featur
 import org.apache.shindig.gadgets.features.FeatureRegistry.FeatureBundle;
 import org.apache.shindig.gadgets.js.JsContent;
 import org.apache.shindig.gadgets.js.JsResponse;
-import org.apache.shindig.gadgets.rewrite.js.ExportJsCompiler;
+import org.apache.shindig.gadgets.rewrite.js.DefaultJsCompiler;
 import org.apache.shindig.gadgets.uri.UriStatus;
 import org.apache.shindig.gadgets.uri.JsUriManager.JsUri;
 
@@ -53,7 +53,7 @@ public class ClosureJsCompilerTest exten
   private Compiler realCompMock;
   private CompilerOptions realOptionsMock;
   private Result realResultMock;
-  private ExportJsCompiler exportCompilerMock;
+  private DefaultJsCompiler compilerMock;
   private JsResponse exportResponseMock;
   private JsUri jsUriMock;
   private CacheProvider cacheMock;
@@ -79,12 +79,12 @@ public class ClosureJsCompilerTest exten
     super.setUp();
     cacheMock = new MockProvider();
     exportResponseMock = mockJsResponse();
-    exportCompilerMock = mockExportJsCompiler(exportResponseMock);
+    compilerMock = mockDefaultJsCompiler(exportResponseMock);
   }
 
   public void testGetJsContentWithGoogSymbolExports() throws Exception {
     realOptionsMock = mockRealJsCompilerOptions(true); // with
-    compiler = newClosureJsCompiler(null, realOptionsMock, exportCompilerMock, cacheMock);
+    compiler = newClosureJsCompiler(null, realOptionsMock, compilerMock, cacheMock);
     FeatureBundle bundle = mockBundle(EXPORTS);
     Iterable<JsContent> actual = compiler.getJsContent(mockJsUri(false), bundle);
     assertEquals(EXPORT_COMPILER_STRING +
@@ -95,7 +95,7 @@ public class ClosureJsCompilerTest exten
 
   public void testGetJsContentWithoutGoogSymbolExports() throws Exception {
     realOptionsMock = mockRealJsCompilerOptions(false); // without
-    compiler = newClosureJsCompiler(null, realOptionsMock, exportCompilerMock, cacheMock);
+    compiler = newClosureJsCompiler(null, realOptionsMock, compilerMock, cacheMock);
     FeatureBundle bundle = mockBundle(EXPORTS);
     Iterable<JsContent> actual = compiler.getJsContent(mockJsUri(false), bundle);
     assertEquals(EXPORT_COMPILER_STRING, getContent(actual));
@@ -106,7 +106,7 @@ public class ClosureJsCompilerTest exten
     realResultMock = mockRealJsResult();
     realCompMock = mockRealJsCompiler(null, realResultMock, ACTUAL_COMPILER_OUTPUT);
     realOptionsMock = mockRealJsCompilerOptions(false);
-    compiler = newClosureJsCompiler(realCompMock, realOptionsMock, exportCompilerMock, cacheMock);
+    compiler = newClosureJsCompiler(realCompMock, realOptionsMock, compilerMock, cacheMock);
     JsResponse actual = compiler.compile(jsUriMock, EXPORT_COMPILER_CONTENTS,
         ImmutableList.of(EXTERN));
     assertEquals(CLOSURE_ACTUAL_COMPILER_OUTPUT, actual.toJsString());
@@ -118,7 +118,7 @@ public class ClosureJsCompilerTest exten
     realResultMock = mockRealJsResult();
     realCompMock = mockRealJsCompiler(null, realResultMock, ACTUAL_COMPILER_OUTPUT);
     realOptionsMock = mockRealJsCompilerOptions(false);
-    compiler = newClosureJsCompiler(realCompMock, realOptionsMock, exportCompilerMock, cacheMock);
+    compiler = newClosureJsCompiler(realCompMock, realOptionsMock, compilerMock, cacheMock);
     JsResponse actual = compiler.compile(jsUriMock, EXPORT_COMPILER_CONTENTS,
         ImmutableList.of(EXTERN));
     assertEquals(CLOSURE_EXPORT_COMPILER_OUTPUT, actual.toJsString());
@@ -129,7 +129,7 @@ public class ClosureJsCompilerTest exten
     jsUriMock = mockJsUri(false); // opt
     realCompMock = mockRealJsCompiler(JS_ERROR, realResultMock, ACTUAL_COMPILER_OUTPUT);
     realOptionsMock = mockRealJsCompilerOptions(true); // force compiler to run
-    compiler = newClosureJsCompiler(realCompMock, realOptionsMock, exportCompilerMock, cacheMock);
+    compiler = newClosureJsCompiler(realCompMock, realOptionsMock, compilerMock, cacheMock);
     JsResponse actual = compiler.compile(jsUriMock, EXPORT_COMPILER_CONTENTS,
         ImmutableList.of(EXTERN));
     assertTrue(actual.getErrors().get(0).contains(ERROR_NAME));
@@ -140,7 +140,7 @@ public class ClosureJsCompilerTest exten
     jsUriMock = mockJsUri(true); // debug
     realCompMock = mockRealJsCompiler(JS_ERROR, realResultMock, ACTUAL_COMPILER_OUTPUT);
     realOptionsMock = mockRealJsCompilerOptions(true); // force compiler to run
-    compiler = newClosureJsCompiler(realCompMock, realOptionsMock, exportCompilerMock, cacheMock);
+    compiler = newClosureJsCompiler(realCompMock, realOptionsMock, compilerMock, cacheMock);
     JsResponse actual = compiler.compile(jsUriMock, EXPORT_COMPILER_CONTENTS,
         ImmutableList.of(EXTERN));
     assertTrue(actual.getErrors().get(0).contains(ERROR_NAME));
@@ -148,8 +148,8 @@ public class ClosureJsCompilerTest exten
   }
 
   private ClosureJsCompiler newClosureJsCompiler(final Compiler realComp,
-      CompilerOptions realOptions, ExportJsCompiler exportComp, CacheProvider cache) {
-    return new ClosureJsCompiler(exportComp, cache) {
+      CompilerOptions realOptions, DefaultJsCompiler defaultComp, CacheProvider cache) {
+    return new ClosureJsCompiler(defaultComp, cache) {
       @Override
       Compiler newCompiler() {
         return realComp;
@@ -171,8 +171,8 @@ public class ClosureJsCompilerTest exten
   }
 
   @SuppressWarnings("unchecked")
-  private ExportJsCompiler mockExportJsCompiler(JsResponse res) {
-    ExportJsCompiler result = createMock(ExportJsCompiler.class);
+  private DefaultJsCompiler mockDefaultJsCompiler(JsResponse res) {
+    DefaultJsCompiler result = createMock(DefaultJsCompiler.class);
     expect(result.getJsContent(isA(JsUri.class), isA(FeatureBundle.class)))
         .andReturn(EXPORT_COMPILER_CONTENTS).anyTimes();
     expect(result.compile(isA(JsUri.class), isA(Iterable.class), isA(List.class)))