2525import java .nio .file .Path ;
2626import java .nio .file .Paths ;
2727import java .nio .file .WatchEvent .Kind ;
28+ import java .util .List ;
2829import java .util .concurrent .atomic .AtomicReference ;
29- import java .util .stream .Collectors ;
3030
31- import org .jooby .MediaType ;
3231import org .jooby .Request ;
3332import org .jooby .Response ;
34- import org .jooby .Results ;
3533import org .jooby .Route ;
3634import org .jooby .assets .AssetCompiler ;
3735import org .jooby .assets .AssetException ;
3836import 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 ;
4339import com .typesafe .config .Config ;
4440
4541public 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 }
0 commit comments