Skip to content

Commit f2d8ce4

Browse files
committed
update asset live compiler to use whoops fix #404
1 parent 83c4a1f commit f2d8ce4

File tree

23 files changed

+169
-2162
lines changed

23 files changed

+169
-2162
lines changed

coverage-report/src/test/java/org/jooby/whoops/WhoopsTest.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ public void frame() throws Exception {
101101
assertEquals("WhoopsApp", frame.get("type"));
102102
assertEquals(
103103
Arrays.asList(ImmutableMap.of("context",
104-
unit.get(Throwable.class).getClass().getName(), "text", ": " + message)),
104+
unit.get(Throwable.class).getClass().getName(), "text", message)),
105105
frame.get("comments"));
106106
});
107107
}
@@ -158,7 +158,7 @@ public void frames() throws Exception {
158158
assertEquals("WhoopsApp", frame.get("type"));
159159
assertEquals(
160160
Arrays.asList(ImmutableMap.of("context",
161-
unit.get(Throwable.class).getClass().getName(), "text", ": " + message)),
161+
unit.get(Throwable.class).getClass().getName(), "text", message)),
162162
frame.get("comments"));
163163
});
164164
}

jooby-assets/src/main/java/org/jooby/assets/AssetException.java

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,33 +21,66 @@
2121
import static java.util.Objects.requireNonNull;
2222

2323
import java.util.List;
24+
import java.util.function.Supplier;
25+
import java.util.stream.Collectors;
2426

2527
import com.google.common.collect.ImmutableList;
2628

29+
/**
30+
* Carry information about a asset processor failure. It might have multiple {@link AssetProblem}
31+
* and the id of the processor who fail to process the input.
32+
*
33+
* @author edgar
34+
*/
2735
@SuppressWarnings("serial")
28-
public class AssetException extends RuntimeException {
36+
public class AssetException extends RuntimeException implements Supplier<String> {
2937

3038
private List<AssetProblem> problems;
3139

3240
private String id;
3341

42+
/**
43+
* Creates a new {@link AssetException}.
44+
*
45+
* @param id Processor id.
46+
* @param problem Asset problem.
47+
*/
3448
public AssetException(final String id, final AssetProblem problem) {
3549
this(id, ImmutableList.of(problem));
3650
}
3751

52+
/**
53+
* Creates a new {@link AssetException}.
54+
*
55+
* @param id Processor id.
56+
* @param problems Asset problems.
57+
*/
3858
public AssetException(final String id, final List<AssetProblem> problems) {
39-
super(requireNonNull(problems, "The problems is required.").toString());
59+
super(requireNonNull(problems, "The problems is required.").stream().map(AssetProblem::toString)
60+
.collect(Collectors.joining("\n", "\t", "")));
4061
this.id = id;
4162
this.problems = problems;
4263
}
4364

65+
/**
66+
* @return Message of the first problem (useful for better error display on whoops).
67+
*/
68+
@Override
69+
public String get() {
70+
AssetProblem problem = problems.get(0);
71+
return problem.getMessage();
72+
}
73+
4474
/**
4575
* @return processor ID.
4676
*/
4777
public String getId() {
4878
return id;
4979
}
5080

81+
/**
82+
* @return List of asset problems.
83+
*/
5184
public List<AssetProblem> getProblems() {
5285
return problems;
5386
}

jooby-assets/src/main/java/org/jooby/assets/Props.java

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -88,9 +88,9 @@ public boolean matches(final MediaType type) {
8888
public String process(final String filename, final String source, final Config conf)
8989
throws Exception {
9090
try {
91-
Env env = Env.DEFAULT.build(conf);
92-
List<String> delims = get("delims");
93-
return env.resolve(source, delims.get(0), delims.get(1));
91+
Env env = Env.DEFAULT.build(conf);
92+
List<String> delims = get("delims");
93+
return env.resolve(source, delims.get(0), delims.get(1));
9494
} catch (Exception cause) {
9595
int line = -1;
9696
int column = -1;
@@ -99,7 +99,8 @@ public String process(final String filename, final String source, final Config c
9999
line = Integer.parseInt(matcher.group(1));
100100
column = Integer.parseInt(matcher.group(2));
101101
}
102-
throw new AssetException(name(), new AssetProblem(filename, line, column, cause.getMessage(), null));
102+
throw new AssetException(name(),
103+
new AssetProblem(filename, line, column, cause.getMessage(), null));
103104
}
104105
}
105106

jooby-assets/src/main/java/org/jooby/internal/assets/LiveCompiler.java

Lines changed: 22 additions & 99 deletions
Original file line numberDiff line numberDiff line change
@@ -25,28 +25,21 @@
2525
import java.nio.file.Path;
2626
import java.nio.file.Paths;
2727
import java.nio.file.WatchEvent.Kind;
28+
import java.util.List;
2829
import java.util.concurrent.atomic.AtomicReference;
29-
import java.util.stream.Collectors;
3030

31-
import org.jooby.MediaType;
3231
import org.jooby.Request;
3332
import org.jooby.Response;
34-
import org.jooby.Results;
3533
import org.jooby.Route;
3634
import org.jooby.assets.AssetCompiler;
3735
import org.jooby.assets.AssetException;
3836
import org.jooby.assets.AssetProblem;
39-
import org.jooby.handlers.AssetHandler;
40-
import org.slf4j.Logger;
41-
import org.slf4j.LoggerFactory;
4237

38+
import com.google.common.collect.Lists;
4339
import com.typesafe.config.Config;
4440

4541
public class LiveCompiler implements Route.Handler {
4642

47-
/** The logging system. */
48-
private final Logger log = LoggerFactory.getLogger(getClass());
49-
5043
private final Config conf;
5144

5245
private final AssetCompiler compiler;
@@ -68,107 +61,37 @@ private void onChange(final Kind<?> kind, final Path path) {
6861
compiler.build(conf.getString("application.env"), outputdir);
6962
lastErr.set(null);
7063
} catch (AssetException ex) {
71-
log.error("Found " + ex.getProblems().size() + " problem(s): \n" +
72-
ex.getProblems().stream()
73-
.map(AssetProblem::toString)
74-
.collect(Collectors.joining("\n")));
75-
lastErr.set(ex);
64+
lastErr.set(rewrite(ex));
7665
} catch (Exception ex) {
77-
log.error("Found 1 problem(s): \n", ex);
78-
lastErr.set(new AssetException("compiler",
79-
new AssetProblem("unknown", -1, -1, ex.getMessage(), null)));
66+
lastErr.set(rewrite(new AssetException("compiler",
67+
new AssetProblem(path.toString(), -1, -1, ex.getMessage(), null))));
8068
}
8169
}
8270

71+
/**
72+
* Add a virtual/fake stacktrace element with the offending file, useful for whoops.
73+
*
74+
* @param ex Stack trace to rewrite.
75+
* @return Same exception with new stacktrace.
76+
*/
77+
private AssetException rewrite(final AssetException ex) {
78+
List<StackTraceElement> stacktrace = Lists.newArrayList(ex.getStackTrace());
79+
List<AssetProblem> problems = ex.getProblems();
80+
AssetProblem head = problems.get(0);
81+
stacktrace.add(0,
82+
new StackTraceElement(head.getFilename(), "", head.getFilename(), head.getLine()));
83+
ex.setStackTrace(stacktrace.toArray(new StackTraceElement[stacktrace.size()]));
84+
return ex;
85+
}
86+
8387
@Override
8488
public void handle(final Request req, final Response rsp) throws Throwable {
85-
String path = req.path();
86-
if (path.startsWith("/org/jooby/assets/live")) {
87-
new AssetHandler("/").handle(req, rsp);
88-
return;
89-
}
9089
AssetException ex = lastErr.get();
9190
if (ex != null) {
92-
reportErr(req, rsp, ex);
91+
throw ex;
9392
}
9493
}
9594

96-
private void reportErr(final Request req, final Response rsp, final AssetException ex)
97-
throws Throwable {
98-
StringBuilder buff = new StringBuilder();
99-
buff.append("<!doctype html>\n" +
100-
"<html lang=\"en\">\n" +
101-
" <head> \n" +
102-
" <meta charset=\"UTF-8\"> \n" +
103-
" <meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\"> \n" +
104-
" <title>jooby: assets compiler</title>\n" +
105-
" <link href=\"/org/jooby/assets/live/images/apps/favicon.ico\" rel=\"shortcut icon\"> \n"
106-
+
107-
" <link href=\"/org/jooby/assets/live/images/apps/favicon.png\" rel=\"icon\" sizes=\"16x16\" type=\"image/png\"> \n"
108-
+
109-
" <link href=\"/org/jooby/assets/live/images/apps/favicon32.png\" rel=\"icon\" sizes=\"32x32\" type=\"image/png\"> \n"
110-
+
111-
" <link href=\"/org/jooby/assets/live/images/apps/favicon96.png\" rel=\"icon\" sizes=\"96x96\" type=\"image/png\"> \n"
112-
+
113-
" <link href=\"/org/jooby/assets/live/images/apps/android-chrome.png\" rel=\"icon\" sizes=\"192x192\" type=\"image/png\"> \n"
114-
+
115-
" <link rel=\"stylesheet\" href=\"https://fonts.googleapis.com/css?family=Raleway:400,300,500,700\"> \n"
116-
+
117-
" <link rel=\"stylesheet\" href=\"/org/jooby/assets/live/styles/application.css\"> \n" +
118-
" <link rel=\"stylesheet\" href=\"/org/jooby/assets/live/styles/github.css\"> \n" +
119-
" </head> \n" +
120-
" <body class=\"page-section\"> \n" +
121-
" <header class=\"site-header\"> \n" +
122-
" <div class=\"row\">\n" +
123-
" <a href=\"/\" title=\"Home\" class=\"site-logo\"><img src=\"/org/jooby/assets/live/images/logo_jooby-2x.png\" alt=\"Logo Jooby\" width=\"76\" height=\"31\"></a>\n"
124-
+
125-
" </div> \n" +
126-
" </header> \n" +
127-
" <main role=\"main\" class=\"site-content\"> \n" +
128-
" <div class=\"section-title\"> \n" +
129-
" <div class=\"row\"> \n" +
130-
" <h1>Asset compiler</h1> \n" +
131-
" </div> \n" +
132-
" </div> \n" +
133-
" <div class=\"row\"> \n" +
134-
" <div class=\"section-content\"> ")
135-
.append("<h2> ").append(ex.getId()).append(" found ").append(ex.getProblems().size())
136-
.append(" problem(s):</h2>\n")
137-
.append("<ul>\n");
138-
139-
ex.getProblems().forEach(problem -> {
140-
buff.append(" <li>").append("<pre><code class=\"nohighlight\">")
141-
.append(problem.getFilename())
142-
.append(":")
143-
.append(problem.getLine())
144-
.append(":")
145-
.append(problem.getColumn())
146-
.append(": ")
147-
.append(problem.getMessage())
148-
.append("</code></pre>");
149-
String evidence = problem.getEvidence();
150-
if (evidence.length() > 0) {
151-
buff.append("<div class=\"highlighter-rouge\">");
152-
buff.append("<pre class=\"highlight\"><code>").append(evidence.trim())
153-
.append("</code></pre></div>\n");
154-
}
155-
buff.append("</li>\n");
156-
});
157-
158-
buff.append("</ul>\n")
159-
.append(
160-
"<script type=\"text/javascript\" src=\"/org/jooby/assets/live/highlight.pack.js\"></script>\n")
161-
.append("<script>hljs.initHighlightingOnLoad();</script>")
162-
.append("</div> \n" +
163-
"</div> \n" +
164-
" </main> \n" +
165-
" </body>\n" +
166-
"</html>");
167-
168-
rsp.send(Results.ok(buff.toString()).type(MediaType.html).status(200));
169-
170-
}
171-
17295
public void start() {
17396
watcher.start();
17497
}

jooby-assets/src/main/resources/org/jooby/assets/live/highlight.pack.js

Lines changed: 0 additions & 1 deletion
This file was deleted.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.

0 commit comments

Comments
 (0)