Author: zhoresh
Date: Thu Jun 9 21:48:11 2011
New Revision: 1134099
URL: http://svn.apache.org/viewvc?rev=1134099&view=rev
Log:
Break compile function to allow override | https://reviews.apache.org/r/861/
Modified:
shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/js/CompilationProcessor.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
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=1134099&r1=1134098&r2=1134099&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
Thu Jun 9 21:48:11 2011
@@ -35,6 +35,7 @@ public class CompilationProcessor implem
* Compile content in the inbound JsResponseBuilder.
* TODO: Re-add support for externs here if they're ever used.
* TODO: Convert JsCompiler to take JsResponseBuilder directly rather than
Iterable<JsContent>
+ * @throws JsException
*/
public boolean process(JsRequest request, JsResponseBuilder builder) throws
JsException {
Iterable<JsContent> jsContents = builder.build().getAllJsContent();
@@ -51,6 +52,11 @@ public class CompilationProcessor implem
builder.clearJs().appendAllJs(result.getAllJsContent());
builder.setStatusCode(result.getStatusCode());
builder.addErrors(result.getErrors());
+ int refresh = result.getCacheTtlSecs();
+ if (refresh > 0) {
+ // Allow ttl overwrite by compiler
+ builder.setCacheTtlSecs(refresh);
+ }
return true;
}
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=1134099&r1=1134098&r2=1134099&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
Thu Jun 9 21:48:11 2011
@@ -63,13 +63,12 @@ public class ClosureJsCompiler implement
+ "var parts=name.split('.'),cur=window,part;"
+ "for(;parts.length&&(part=parts.shift());){if(!parts.length){"
+ "cur[part]=obj;}else{cur=cur[part]||(cur[part]={})}}};",
"[goog.exportSymbol]");
-
+
@VisibleForTesting
static final String CACHE_NAME = "CompiledJs";
private final DefaultJsCompiler defaultCompiler;
private final Cache<String, JsResponse> cache;
- private JsResponse lastResult;
@Inject
public ClosureJsCompiler(DefaultJsCompiler defaultCompiler, CacheProvider
cacheProvider) {
@@ -82,14 +81,14 @@ public class ClosureJsCompiler implement
CompilationLevel.ADVANCED_OPTIMIZATIONS.setOptionsForCompilationLevel(result);
return result;
}
-
+
protected CompilerOptions getCompilerOptions(JsUri uri) {
CompilerOptions options = defaultCompilerOptions();
if (outputCorrelatedJs()) {
setSourceMapCompilerOptions(options);
}
-
+
return options;
}
@@ -118,92 +117,104 @@ public class ClosureJsCompiler implement
String cacheKey = makeCacheKey(exportResponse.toJsString(), externs,
jsUri);
JsResponse cachedResult = cache.getElement(cacheKey);
if (cachedResult != null) {
- lastResult = cachedResult;
return cachedResult;
}
- JsResponseBuilder builder = new JsResponseBuilder();
-
// Only run actual compiler if necessary.
CompilerOptions options = getCompilerOptions(jsUri);
-
+
if (!jsUri.isDebug() || options.isExternExportsEnabled()) {
- List<JSSourceFile> allExterns = Lists.newArrayList();
- allExterns.add(JSSourceFile.fromCode("externs", externs));
+ return doCompile(jsUri, content, externs, cacheKey);
+ }
- List<JsContent> allContent = Lists.newLinkedList(content);
- if (options.isExternExportsEnabled()) {
- allContent.add(EXPORTSYMBOL_CODE);
- }
-
- Compiler actualCompiler = newCompiler();
- Result result = actualCompiler.compile(
- allExterns,
- convertToJsSource(allContent),
- options);
-
- if (actualCompiler.hasErrors()) {
- ImmutableList.Builder<String> errors = ImmutableList.builder();
- for (JSError error : actualCompiler.getErrors()) {
- errors.add(error.toString());
- }
- return cacheAndReturnErrorResult(
- builder, cacheKey,
- HttpResponse.SC_NOT_FOUND,
- errors.build());
+ return doDebug(content, cacheKey);
+ }
+
+ protected JsResponse doDebug(Iterable<JsContent> content, String cacheKey) {
+ JsResponseBuilder builder = new JsResponseBuilder();
+ builder.appendAllJs(content);
+ JsResponse result = builder.build();
+ cache.addElement(cacheKey, result);
+ return result;
+ }
+
+ protected JsResponse doCompile(JsUri jsUri, Iterable<JsContent> content,
String externs,
+ String cacheKey) {
+ JsResponseBuilder builder = new JsResponseBuilder();
+
+ CompilerOptions options = getCompilerOptions(jsUri);
+
+ List<JSSourceFile> allExterns = Lists.newArrayList();
+ allExterns.add(JSSourceFile.fromCode("externs", externs));
+
+ List<JsContent> allContent = Lists.newLinkedList(content);
+ if (options.isExternExportsEnabled()) {
+ allContent.add(EXPORTSYMBOL_CODE);
+ }
+
+ Compiler actualCompiler = newCompiler();
+ Result result = actualCompiler.compile(
+ allExterns,
+ convertToJsSource(allContent),
+ options);
+
+ if (actualCompiler.hasErrors()) {
+ ImmutableList.Builder<String> errors = ImmutableList.builder();
+ for (JSError error : actualCompiler.getErrors()) {
+ errors.add(error.toString());
}
+ return cacheAndReturnErrorResult(
+ builder, cacheKey,
+ HttpResponse.SC_NOT_FOUND,
+ errors.build());
+ }
- String compiled = compileToSource(actualCompiler, result, jsUri);
- if (outputCorrelatedJs()) {
- // Emit code correlated w/ original source.
- // This operation is equivalent in final code to bundled-output,
- // but is less efficient and should perhaps only be used in code
profiling.
- SourceMappings sm = processSourceMap(result, allContent);
- if (sm != null) {
- builder.appendAllJs(sm.mapCompiled(compiled));
- } else {
- return cacheAndReturnErrorResult(
- builder, cacheKey,
- HttpResponse.SC_INTERNAL_SERVER_ERROR,
- Lists.newArrayList("Parse error for source map"));
- }
+ String compiled = compileToSource(actualCompiler, result, jsUri);
+ if (outputCorrelatedJs()) {
+ // Emit code correlated w/ original source.
+ // This operation is equivalent in final code to bundled-output,
+ // but is less efficient and should perhaps only be used in code
profiling.
+ SourceMappings sm = processSourceMap(result, allContent);
+ if (sm != null) {
+ builder.appendAllJs(sm.mapCompiled(compiled));
} else {
- builder.appendJs(compiled, "[compiled]");
+ return cacheAndReturnErrorResult(
+ builder, cacheKey,
+ HttpResponse.SC_INTERNAL_SERVER_ERROR,
+ Lists.newArrayList("Parse error for source map"));
}
-
- builder.clearExterns().appendRawExtern(result.externExport);
} else {
- // Otherwise, return original content and null exports.
- builder.appendAllJs(content);
+ builder.appendJs(compiled, "[compiled]");
}
- JsResponse result = builder.build();
- cache.addElement(cacheKey, result);
- lastResult = result;
- return result;
+ builder.clearExterns().appendRawExtern(result.externExport);
+
+ JsResponse response = builder.build();
+ cache.addElement(cacheKey, response);
+ return response;
}
protected String compileToSource(Compiler compiler, Result result, JsUri
jsUri) {
return compiler.toSource();
}
-
+
private JsResponse cacheAndReturnErrorResult(
JsResponseBuilder builder, String cacheKey,
int statusCode, List<String> messages) {
builder.setStatusCode(statusCode);
builder.addErrors(messages);
- JsResponse result = builder.build();
+ JsResponse result = builder.build();
cache.addElement(cacheKey, result);
return result;
}
-
+
// Override this method to return "true" for cases where individual chunks of
// compiled JS should be emitted as JsContent objects, each correlating
output JS
// with the original source file from which they came.
protected boolean outputCorrelatedJs() {
return false;
}
-
+
private List<JSSourceFile> convertToJsSource(Iterable<JsContent> content) {
Map<String, Integer> sourceMap = Maps.newHashMap();
List<JSSourceFile> sources = Lists.newLinkedList();
@@ -212,7 +223,7 @@ public class ClosureJsCompiler implement
}
return sources;
}
-
+
// Return a unique string to represent the inbound "source" parameter.
// Closure Compiler errors out when two JSSourceFiles with the same name are
// provided, so this method tracks the currently-used source names (in the
@@ -226,7 +237,7 @@ public class ClosureJsCompiler implement
sourceMap.put(source, ix + 1);
return ret;
}
-
+
private static String getRootSrc(String source) {
int colIx = source.lastIndexOf(":");
if (colIx == -1) {
@@ -262,10 +273,6 @@ public class ClosureJsCompiler implement
return builder;
}
- public JsResponse getLastResult() {
- return this.lastResult;
- }
-
protected String makeCacheKey(String code, String externs, JsUri uri) {
// TODO: include compilation options in the cache key
return Joiner.on(":").join(
@@ -275,7 +282,7 @@ public class ClosureJsCompiler implement
uri.isDebug(),
outputCorrelatedJs());
}
-
+
/**
* Pull the source map out of the given Closure Result, and convert
* it to a local SourceMappings object used to correlate compiled
@@ -295,12 +302,12 @@ public class ClosureJsCompiler implement
return null;
}
}
-
+
private static class SourceMappings {
private final Map<String, JsContent> orig;
private final int[][] lines;
private final String[] mappings;
-
+
private SourceMappings(int[][] lines, String[] mappings, List<JsContent>
content) {
this.lines = lines;
this.mappings = mappings;
@@ -309,14 +316,15 @@ public class ClosureJsCompiler implement
orig.put(js.getSource(), js);
}
}
-
+
private List<JsContent> mapCompiled(String compiled) {
List<JsContent> compiledOut = Lists.newLinkedList();
int codeStart = 0;
int codePos = 0;
int curMapping = -1;
- for (int[] line : lines) {
- for (int nextMapping : line) {
+ for (int line = 0; line < lines.length; ++line) {
+ for (int col = 0; col < lines[line].length; ++col) {
+ int nextMapping = lines[line][col];
codePos++;
if (nextMapping != curMapping && curMapping != -1) {
appendJsContent(compiledOut, codeStart, codePos, compiled,
curMapping);
@@ -328,8 +336,8 @@ public class ClosureJsCompiler implement
appendJsContent(compiledOut, codeStart, codePos + 1, compiled,
curMapping);
return compiledOut;
}
-
- private void appendJsContent(List<JsContent> out, int startPos, int
codePos,
+
+ private void appendJsContent(List<JsContent> out, int startPos, int
codePos,
String compiled, int mapping) {
JsContent sourceJs = orig.get(getRootSrc(mappings[mapping]));
String sourceName = "[closure-compiler-synthesized]";
@@ -341,16 +349,16 @@ public class ClosureJsCompiler implement
out.add(JsContent.fromFeature(compiled.substring(startPos, codePos),
sourceName, bundle, null));
}
-
+
private static final String BEGIN_COMMENT = "/*";
private static final String END_COMMENT = "*/";
private static SourceMappings parseV1(String sourcemap, List<JsContent>
orig)
throws IOException, JSONException {
BufferedReader reader = new BufferedReader(new StringReader(sourcemap));
JSONObject summary = new JSONObject(stripComment(reader.readLine()));
-
+
int lineCount = summary.getInt("count");
-
+
// Read lines info.
int maxMappingIndex = 0;
int[][] lines = new int[lineCount][];
@@ -364,13 +372,13 @@ public class ClosureJsCompiler implement
maxMappingIndex = Math.max(mappingIndex, maxMappingIndex);
}
}
-
+
// Bypass comment and unused file info for each line.
reader.readLine(); // comment
for (int i = 0; i < lineCount; ++i) {
reader.readLine();
}
-
+
// Read mappings objects.
reader.readLine(); // comment
String[] mappings = new String[maxMappingIndex + 1];
@@ -379,10 +387,10 @@ public class ClosureJsCompiler implement
JSONArray mappingObj = new JSONArray(mappingLine);
mappings[i] = mappingObj.getString(0);
}
-
+
return new SourceMappings(lines, mappings, orig);
}
-
+
private static String stripComment(String line) {
int begin = line.indexOf(BEGIN_COMMENT);
if (begin != -1) {
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=1134099&r1=1134098&r2=1134099&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
Thu Jun 9 21:48:11 2011
@@ -83,6 +83,29 @@ public class CompilationProcessorTest {
assertFalse(outIterator.hasNext());
}
+ @Test
+ public void compilerTtlIsUsed() throws Exception {
+ JsUri jsUri = control.createMock(JsUri.class);
+ JsResponseBuilder builder =
+ new JsResponseBuilder().setCacheTtlSecs(1234).setStatusCode(200)
+ .appendJs("content1:", "source1");
+ JsResponse outputResponse =
+ new JsResponseBuilder().setCacheTtlSecs(789)
+ .appendJs("content3", "s3").build();
+ JsRequest request = control.createMock(JsRequest.class);
+ expect(request.getJsUri()).andReturn(jsUri);
+ expect(compiler.compile(same(jsUri), eq(builder.build().getAllJsContent()),
+ isA(String.class))).andReturn(outputResponse);
+
+ control.replay();
+ boolean status = processor.process(request, builder);
+ control.verify();
+
+ JsResponse compResult = builder.build();
+ assertEquals(200, compResult.getStatusCode());
+ assertEquals(789, compResult.getCacheTtlSecs());
+ }
+
private FeatureBundle mockBundle(String... externs) {
FeatureBundle result = createMock(FeatureBundle.class);
expect(result.getApis(ApiDirective.Type.JS, false)).andReturn(