11package com .sampullara .mustache ;
22
3- import com .github .mustachejava .DefaultMustacheFactory ;
4- import com .github .mustachejava .Mustache ;
5- import com .github .mustachejava .MustacheException ;
6- import com .github .mustachejava .MustacheFactory ;
7- import com .sampullara .cli .Args ;
8- import com .sampullara .cli .Argument ;
3+ import java .io .BufferedInputStream ;
4+ import java .io .BufferedReader ;
5+ import java .io .File ;
6+ import java .io .FileInputStream ;
7+ import java .io .FileNotFoundException ;
8+ import java .io .IOException ;
9+ import java .io .InputStream ;
10+ import java .io .InputStreamReader ;
11+ import java .io .OutputStream ;
12+ import java .io .PrintWriter ;
13+ import java .io .StringWriter ;
14+ import java .io .UnsupportedEncodingException ;
15+ import java .util .ArrayList ;
16+ import java .util .Arrays ;
17+ import java .util .HashMap ;
18+ import java .util .Iterator ;
19+ import java .util .List ;
20+ import java .util .Map ;
21+
22+ import javax .activation .FileTypeMap ;
23+ import javax .activation .MimetypesFileTypeMap ;
24+ import javax .servlet .ServletException ;
25+ import javax .servlet .http .HttpServletRequest ;
26+ import javax .servlet .http .HttpServletResponse ;
27+
928import org .codehaus .jackson .JsonFactory ;
1029import org .codehaus .jackson .JsonNode ;
30+ import org .codehaus .jackson .JsonParseException ;
1131import org .codehaus .jackson .JsonParser ;
32+ import org .codehaus .jackson .JsonProcessingException ;
1233import org .codehaus .jackson .map .MappingJsonFactory ;
1334import org .eclipse .jetty .server .Handler ;
1435import org .eclipse .jetty .server .Request ;
1536import org .eclipse .jetty .server .Server ;
1637import org .eclipse .jetty .server .handler .AbstractHandler ;
1738
18- import javax .servlet .ServletException ;
19- import javax .servlet .http .HttpServletRequest ;
20- import javax .servlet .http .HttpServletResponse ;
21- import java .io .*;
22- import java .util .ArrayList ;
23- import java .util .HashMap ;
24- import java .util .Iterator ;
25- import java .util .Map ;
39+ import com .github .mustachejava .DefaultMustacheFactory ;
40+ import com .github .mustachejava .Mustache ;
41+ import com .github .mustachejava .MustacheFactory ;
42+ import com .sampullara .cli .Args ;
43+ import com .sampullara .cli .Argument ;
2644
2745/**
2846 * Run a local server and merge .js and .html files using mustache.
@@ -42,17 +60,21 @@ public class Handlebar {
4260
4361 private static File rootDir ;
4462
45- private static final JsonFactory JSON_FACTORY = new MappingJsonFactory () ;
63+ private static final FileTypeMap FILE_TYPE_MAP ;
4664
65+ private static final JsonFactory JSON_FACTORY = new MappingJsonFactory ();
4766
48- private static Map <String , String > mimeTypes = new HashMap <String , String >();
4967 static {
50- mimeTypes .put ("html" , "text/html" );
51- mimeTypes .put ("png" , "image/png" );
52- mimeTypes .put ("gif" , "image/gif" );
53- mimeTypes .put ("jpg" , "image/jpg" );
54- mimeTypes .put ("js" , "text/javascript" );
55- mimeTypes .put ("css" , "text/css" );
68+ FILE_TYPE_MAP = loadFileTypeMapFromContextSupportModule ();
69+ }
70+
71+ private static FileTypeMap loadFileTypeMapFromContextSupportModule () {
72+ // see if we can find the extended mime.types from the context-support module
73+ InputStream is = ClassLoader .getSystemResourceAsStream ("com/sampullara/mustache/mimes.txt" );
74+ if (null != is ) {
75+ return new MimetypesFileTypeMap (is );
76+ }
77+ return FileTypeMap .getDefaultFileTypeMap ();
5678 }
5779
5880 public static Object toObject (final JsonNode node ) {
@@ -98,70 +120,115 @@ public static void main(String[] args) throws Exception {
98120 Handler handler = new AbstractHandler () {
99121 public void handle (String s , Request r , HttpServletRequest req , HttpServletResponse res )
100122 throws IOException , ServletException {
101- String pathInfo = req .getPathInfo ();
102-
103- if (pathInfo .endsWith ("/" )) pathInfo += "index.html" ;
104-
105- String extension = pathInfo .substring (pathInfo .lastIndexOf ("." ) + 1 );
106- String base = pathInfo .substring (0 , pathInfo .lastIndexOf ("." ));
107- String mimeType = mimeTypes .get (extension );
108-
109- // create a handle to the resource
110- File staticres = new File (rootDir , pathInfo .substring (1 ));
111-
112- res .setContentType (mimeType == null ? "text/html" : mimeType );
113- res .setCharacterEncoding ("utf-8" );
114- if (mimeType == null || mimeType .equals ("text/html" )) {
115- // Handle like a template
116- String filename = pathInfo .substring (1 );
117- try {
118- MustacheFactory mc = new DefaultMustacheFactory (new File ("." ));
119- Mustache mustache = mc .compile (filename );
120- File file = new File (mocks , base + ".json" );
121- res .setStatus (HttpServletResponse .SC_OK );
122- Map parameters = new HashMap <Object , Object >(req .getParameterMap ()) {
123- @ Override
124- public Object get (Object o ) {
125- Object result = super .get (o ); // To change body of overridden methods use File |
126- // Settings | File Templates.
127- if (result instanceof String []) {
128- String [] strings = (String []) result ;
129- if (strings .length == 1 ) {
130- return strings [0 ];
131- }
132- }
133- return result ;
134- }
135- };
136-
137- if (file .exists ()) {
138- BufferedReader br = new BufferedReader (new InputStreamReader (new FileInputStream (file ), "UTF-8" ));
139- JsonParser parser = JSON_FACTORY .createJsonParser (br );
140- JsonNode json = parser .readValueAsTree ();
141- br .close ();
142- mustache .execute (res .getWriter (), new Object [] {toObject (json ), parameters });
123+ try {
124+ String pathInfo = req .getPathInfo ();
125+ if (pathInfo .endsWith ("/" )) pathInfo += "index.html" ;
126+
127+ // obtain mime type
128+ String mimeType = FILE_TYPE_MAP .getContentType (pathInfo );
129+ System .out .println (String .format ("%s: %s" , mimeType , pathInfo ));
130+
131+ // create a handle to the resource
132+ File staticres = new File (rootDir , pathInfo .substring (1 ));
133+
134+ res .setContentType (mimeType == null ? "text/html" : mimeType );
135+ res .setCharacterEncoding ("utf-8" );
136+ if (mimeType == null || mimeType .equals ("text/html" )) {
137+
138+ // Handle like a template
139+ String filename = pathInfo .substring (1 );
140+
141+ // check if file exists
142+ if (!staticres .exists ()) {
143+ res .setStatus (HttpServletResponse .SC_NOT_FOUND );
144+ processTemplate (req , res , "404.html" );
143145 } else {
144- mustache .execute (res .getWriter (), parameters );
146+ res .setStatus (HttpServletResponse .SC_OK );
147+ processTemplate (req , res , filename );
145148 }
149+
146150 r .setHandled (true );
147- } catch (MustacheException e ) {
148- e .printStackTrace (res .getWriter ());
149- r .setHandled (true );
150- res .setStatus (500 );
151+ } else {
152+ if (!staticres .exists ()) {
153+ res .setStatus (HttpServletResponse .SC_NOT_FOUND );
154+ return ;
155+ }
156+
157+ // Handle like a file
158+ res .setStatus (HttpServletResponse .SC_OK );
159+ OutputStream os = res .getOutputStream ();
160+ byte [] bytes = new byte [8192 ];
161+ BufferedInputStream bis = new BufferedInputStream (new FileInputStream (staticres ));
162+ int read ;
163+ while ((read = bis .read (bytes )) != -1 ) {
164+ os .write (bytes , 0 , read );
165+ }
166+ os .close ();
151167 }
152- } else {
153- // Handle like a file
154- res .setStatus (HttpServletResponse .SC_OK );
155- OutputStream os = res .getOutputStream ();
156- byte [] bytes = new byte [8192 ];
157- BufferedInputStream bis =
158- new BufferedInputStream (new FileInputStream (pathInfo .substring (1 )));
159- int read ;
160- while ((read = bis .read (bytes )) != -1 ) {
161- os .write (bytes , 0 , read );
168+ } catch (Exception e ) {
169+ // building stacktrace string
170+ StringWriter str = new StringWriter ();
171+ e .printStackTrace (new PrintWriter (str ));
172+ String stack = simpleEscape (str .toString ());
173+
174+ // params
175+ Map <String , String > params = new HashMap <String , String >();
176+ params .put ("stacktrace" , stack );
177+
178+ // render template
179+ res .setStatus (HttpServletResponse .SC_INTERNAL_SERVER_ERROR );
180+ processTemplate (req , res , "500.html" , params );
181+
182+ r .setHandled (true );
183+ }
184+ }
185+
186+ private void processTemplate (HttpServletRequest req , HttpServletResponse res ,
187+ String filename , Object ... scopes ) throws UnsupportedEncodingException ,
188+ FileNotFoundException , IOException , JsonParseException , JsonProcessingException {
189+
190+ if (!new File (rootDir , filename ).exists ()) {
191+ System .out .println ("template not found, skipping: " + filename );
192+ return ;
193+ }
194+
195+ MustacheFactory mc = new DefaultMustacheFactory (rootDir );
196+ Mustache mustache = mc .compile (filename );
197+
198+ String base = filename .substring (0 , filename .lastIndexOf ("." ));
199+ File file = new File (mocks , base + ".json" );
200+ Map parameters = new HashMap <Object , Object >(req .getParameterMap ()) {
201+ @ Override
202+ public Object get (Object o ) {
203+ Object result = super .get (o ); // To change body of overridden methods use File |
204+ // Settings | File Templates.
205+ if (result instanceof String []) {
206+ String [] strings = (String []) result ;
207+ if (strings .length == 1 ) {
208+ return strings [0 ];
209+ }
210+ }
211+ return result ;
162212 }
163- os .close ();
213+ };
214+
215+ List <Object > scs = new ArrayList <Object >();
216+ if (null != scopes ) scs .addAll (Arrays .<Object >asList (scopes ));
217+ scs .add (parameters );
218+
219+ if (file .exists ()) {
220+ BufferedReader br =
221+ new BufferedReader (new InputStreamReader (new FileInputStream (file ), "UTF-8" ));
222+ JsonParser parser = JSON_FACTORY .createJsonParser (br );
223+ JsonNode json = parser .readValueAsTree ();
224+ br .close ();
225+ scs .add (0 , toObject (json ));
164226 }
227+ mustache .execute (res .getWriter (), scs .toArray ());
228+ }
229+
230+ private String simpleEscape (String string ) {
231+ return string .replace ("&" , "&" ).replace ("<" , "<" ).replace (">" , ">" );
165232 }
166233 };
167234
0 commit comments