Skip to content

Commit eac634e

Browse files
committed
add a mechanism for running mustache templates on a web server using .json files as input.
1 parent 2c3b404 commit eac634e

4 files changed

Lines changed: 204 additions & 2 deletions

File tree

handlebar/pom.xml

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
2+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
3+
<modelVersion>4.0.0</modelVersion>
4+
5+
<groupId>com.sampullara.mustache.java</groupId>
6+
<artifactId>handlebar</artifactId>
7+
<version>0.1-SNAPSHOT</version>
8+
<packaging>jar</packaging>
9+
10+
<name>handlebar</name>
11+
<url>http://maven.apache.org</url>
12+
13+
<properties>
14+
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
15+
</properties>
16+
17+
<dependencies>
18+
<!-- Mustache -->
19+
<dependency>
20+
<groupId>com.google.code.cli-parser</groupId>
21+
<artifactId>cli</artifactId>
22+
<version>7</version>
23+
</dependency>
24+
<dependency>
25+
<groupId>com.sampullara.mustache.java</groupId>
26+
<artifactId>compiler</artifactId>
27+
<version>0.1-SNAPSHOT</version>
28+
</dependency>
29+
30+
<!-- Jetty -->
31+
<dependency>
32+
<groupId>org.eclipse.jetty</groupId>
33+
<artifactId>jetty-server</artifactId>
34+
<version>7.0.2.v20100331</version>
35+
</dependency>
36+
37+
<!-- Testing -->
38+
<dependency>
39+
<groupId>junit</groupId>
40+
<artifactId>junit</artifactId>
41+
<version>4.8.1</version>
42+
<scope>test</scope>
43+
</dependency>
44+
</dependencies>
45+
46+
<build>
47+
<plugins>
48+
<plugin>
49+
<groupId>org.apache.maven.plugins</groupId>
50+
<artifactId>maven-compiler-plugin</artifactId>
51+
<configuration>
52+
<source>1.6</source>
53+
<target>1.6</target>
54+
</configuration>
55+
</plugin>
56+
<plugin>
57+
<artifactId>maven-assembly-plugin</artifactId>
58+
59+
<configuration>
60+
<descriptorRefs>
61+
<descriptorRef>jar-with-dependencies</descriptorRef>
62+
</descriptorRefs>
63+
<archive>
64+
<manifest>
65+
<mainClass>com.sampullara.mustache.Handlebar</mainClass>
66+
</manifest>
67+
</archive>
68+
</configuration>
69+
70+
<executions>
71+
<execution>
72+
<id>make-assembly</id>
73+
<phase>package</phase>
74+
<goals>
75+
<goal>attached</goal>
76+
</goals>
77+
</execution>
78+
</executions>
79+
80+
</plugin>
81+
</plugins>
82+
</build>
83+
84+
</project>
Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
package com.sampullara.mustache;
2+
3+
import com.sampullara.cli.Args;
4+
import com.sampullara.cli.Argument;
5+
import com.sampullara.util.FutureWriter;
6+
import org.codehaus.jackson.JsonFactory;
7+
import org.codehaus.jackson.JsonNode;
8+
import org.codehaus.jackson.JsonParser;
9+
import org.codehaus.jackson.map.MappingJsonFactory;
10+
import org.eclipse.jetty.server.Handler;
11+
import org.eclipse.jetty.server.Request;
12+
import org.eclipse.jetty.server.Server;
13+
import org.eclipse.jetty.server.handler.AbstractHandler;
14+
15+
import javax.servlet.ServletException;
16+
import javax.servlet.http.HttpServletRequest;
17+
import javax.servlet.http.HttpServletResponse;
18+
import java.io.BufferedInputStream;
19+
import java.io.BufferedReader;
20+
import java.io.File;
21+
import java.io.FileInputStream;
22+
import java.io.FileReader;
23+
import java.io.IOException;
24+
import java.io.OutputStream;
25+
import java.util.HashMap;
26+
import java.util.Map;
27+
import java.util.Stack;
28+
import java.util.concurrent.atomic.AtomicInteger;
29+
30+
/**
31+
* Run a local server and merge .js and .html files using mustache.
32+
* <p/>
33+
* User: sam
34+
* Date: Jun 15, 2010
35+
* Time: 4:25:31 PM
36+
*/
37+
public class Handlebar {
38+
39+
@Argument(alias = "p")
40+
private static Integer port = 8000;
41+
42+
@Argument(alias = "m", required = true)
43+
private static String mocks;
44+
45+
private static Map<String, String> mimeTypes = new HashMap<String, String>();
46+
static {
47+
mimeTypes.put("html", "text/html");
48+
mimeTypes.put("png" , "image/png");
49+
mimeTypes.put("gif" , "image/gif");
50+
mimeTypes.put("jpg" , "image/jpg");
51+
mimeTypes.put("js" , "text/javascript");
52+
mimeTypes.put("css" , "text/css");
53+
}
54+
55+
public static void main(String[] args) throws Exception {
56+
try {
57+
Args.parse(Handlebar.class, args);
58+
} catch (IllegalArgumentException e) {
59+
Args.usage(Handlebar.class);
60+
System.exit(1);
61+
}
62+
final MustacheCompiler mc = new MustacheCompiler(new File("."));
63+
final JsonFactory jf = new MappingJsonFactory();
64+
Handler handler = new AbstractHandler() {
65+
public void handle(String s, Request r, HttpServletRequest req, HttpServletResponse res) throws IOException, ServletException {
66+
String pathInfo = req.getPathInfo();
67+
String extension = pathInfo.substring(pathInfo.lastIndexOf(".") + 1);
68+
String base = pathInfo.substring(0, pathInfo.lastIndexOf("."));
69+
String mimeType = mimeTypes.get(extension);
70+
res.setContentType(mimeType == null ? "text/html" : mimeType);
71+
res.setCharacterEncoding("utf-8");
72+
if (mimeType == null || mimeType.equals("text/html")) {
73+
// Handle like a template
74+
String filename = pathInfo.endsWith("/") ? pathInfo + "index.html" : pathInfo.substring(1);
75+
try {
76+
Mustache mustache = mc.compile(new BufferedReader(new FileReader(filename)), new Stack<String>(), new AtomicInteger(0), Handlebar.class.getClassLoader());
77+
FutureWriter fw = new FutureWriter(res.getWriter());
78+
File file = new File(mocks, base + ".json");
79+
res.setStatus(HttpServletResponse.SC_OK);
80+
if (file.exists()) {
81+
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file));
82+
JsonParser parser = jf.createJsonParser(bis);
83+
JsonNode json = parser.readValueAsTree();
84+
mustache.execute(fw, new Scope(json));
85+
} else {
86+
mustache.execute(fw, new Scope());
87+
}
88+
fw.flush();
89+
r.setHandled(true);
90+
} catch (MustacheException e) {
91+
e.printStackTrace(res.getWriter());
92+
r.setHandled(true);
93+
res.setStatus(500);
94+
}
95+
} else {
96+
// Handle like a file
97+
res.setStatus(HttpServletResponse.SC_OK);
98+
OutputStream os = res.getOutputStream();
99+
byte[] bytes = new byte[8192];
100+
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(pathInfo.substring(1)));
101+
int read;
102+
while((read = bis.read(bytes)) != -1) {
103+
os.write(bytes, 0, read);
104+
}
105+
os.close();
106+
}
107+
}
108+
};
109+
110+
Server server = new Server(port);
111+
server.setHandler(handler);
112+
server.start();
113+
}
114+
}

pom.xml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,10 @@
55
<groupId>com.sampullara.mustache.java</groupId>
66
<artifactId>compiler</artifactId>
77
<version>0.1-SNAPSHOT</version>
8-
<packaging>jar</packaging>
8+
<modules>
9+
<module>handlebar</module>
10+
</modules>
11+
<packaging>pom</packaging>
912

1013
<name>mustache.java</name>
1114
<url>http://maven.apache.org</url>

src/main/java/com/sampullara/mustache/Mustache.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package com.sampullara.mustache;
22

33
import com.sampullara.util.FutureWriter;
4+
import org.codehaus.jackson.JsonNode;
45

56
import java.io.File;
67
import java.io.IOException;
@@ -160,7 +161,7 @@ public Iterator<Scope> iterator() {
160161
Iterator i;
161162

162163
{
163-
if (value instanceof Iterable) {
164+
if (value instanceof Iterable && !(value instanceof JsonNode)) {
164165
i = ((Iterable) value).iterator();
165166
} else {
166167
i = new SingleValueIterator(value);

0 commit comments

Comments
 (0)