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