# HG changeset patch # User Jaroslav Tulach # Date 1249993609 -7200 # Node ID c94f68ddef596738b59b0f5a5f109518723a6b21 # Parent e45bc8ad2eaf8f117aa6400788ff761ecf01e6b1 Simple, freemarker based textual UI diff -r e45bc8ad2eaf -r c94f68ddef59 freemarkerdor/pom.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/freemarkerdor/pom.xml Tue Aug 11 14:26:49 2009 +0200 @@ -0,0 +1,59 @@ + + + 4.0.0 + + all-quoridor + org.apidesign + 1.0 + + org.apidesign + freemarkerdor + 1.0-SNAPSHOT + freemarkerdor + http://maven.apache.org + + + junit + junit + 3.8.1 + test + + + ${project.groupId} + webidor + 1.0 + + + org.netbeans.modules + org-netbeans-libs-freemarker + RELEASE67 + + + org.netbeans.external + freemarker-2.3.8 + RELEASE67 + + + com.sun.jersey + jersey-client + 1.1.0-ea + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 2.0.2 + + 1.5 + 1.5 + + + + + + + + diff -r e45bc8ad2eaf -r c94f68ddef59 freemarkerdor/src/main/java/cz/xelfi/quoridor/freemarkerdor/FreemarkerProcessor.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/freemarkerdor/src/main/java/cz/xelfi/quoridor/freemarkerdor/FreemarkerProcessor.java Tue Aug 11 14:26:49 2009 +0200 @@ -0,0 +1,95 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common + * Development and Distribution License("CDDL") (collectively, the + * "License"). You may not use this file except in compliance with the + * License. You can obtain a copy of the License at + * http://www.netbeans.org/cddl-gplv2.html + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the + * specific language governing permissions and limitations under the + * License. When distributing the software, include this License Header + * Notice in each file and include the License file at + * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the GPL Version 2 section of the License file that + * accompanied this code. If applicable, add the following below the + * License Header, with the fields enclosed by brackets [] replaced by + * your own identifying information: + * "Portions Copyrighted [year] [name of copyright owner]" + * + * Contributor(s): + * + * Portions Copyrighted 2009 Jaroslav Tulach + */ + +package cz.xelfi.quoridor.freemarkerdor; + +import com.sun.jersey.spi.template.TemplateProcessor; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.io.OutputStreamWriter; +import java.io.Writer; +import java.util.Map; +import java.util.logging.Level; +import java.util.logging.Logger; +import javax.script.Bindings; +import javax.script.ScriptContext; +import javax.script.ScriptEngine; +import javax.script.ScriptEngineManager; +import javax.script.ScriptException; +import javax.ws.rs.ext.Provider; +import org.openide.filesystems.FileUtil; + +/** + * + * @author Jaroslav Tulach + */ +@Provider +public class FreemarkerProcessor implements TemplateProcessor { + private ScriptEngineManager manager; + + public String resolve(String name) { + return name; + } + + public void writeTo(String fqn, Object model, OutputStream out) throws IOException { + synchronized (this) { + if (manager == null) { + manager = new ScriptEngineManager(); + } + } + ScriptEngine eng = manager.getEngineByName("freemarker"); + if (eng == null) { + throw new IOException("freemarker not found!"); + } + Bindings bind = eng.getContext().getBindings(ScriptContext.ENGINE_SCOPE); + if (model instanceof Map) { + bind.putAll((Map)model); + } + bind.put("model", model); + + Writer w = new OutputStreamWriter(out); + + eng.getContext().setWriter(w); + eng.getContext().setAttribute(ScriptEngine.FILENAME, fqn, ScriptContext.ENGINE_SCOPE); + // silly workaround for + // http://openide.netbeans.org/issues/show_bug.cgi?id=170177 + eng.getContext().setAttribute("org.openide.filesystems.FileObject", FileUtil.createData(FileUtil.getConfigRoot(), fqn), ScriptContext.ENGINE_SCOPE); + + InputStream is = FreemarkerProcessor.class.getResourceAsStream(fqn); + if (is == null) { + throw new IOException("Not found " + fqn); // NOI18N + } + InputStreamReader r = new InputStreamReader(is, "UTF-8"); + try { + eng.eval(r); + } catch (ScriptException ex) { + ex.printStackTrace(); + throw new IOException(ex); + } + } +} diff -r e45bc8ad2eaf -r c94f68ddef59 freemarkerdor/src/main/java/cz/xelfi/quoridor/freemarkerdor/UI.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/freemarkerdor/src/main/java/cz/xelfi/quoridor/freemarkerdor/UI.java Tue Aug 11 14:26:49 2009 +0200 @@ -0,0 +1,133 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common + * Development and Distribution License("CDDL") (collectively, the + * "License"). You may not use this file except in compliance with the + * License. You can obtain a copy of the License at + * http://www.netbeans.org/cddl-gplv2.html + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the + * specific language governing permissions and limitations under the + * License. When distributing the software, include this License Header + * Notice in each file and include the License file at + * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the GPL Version 2 section of the License file that + * accompanied this code. If applicable, add the following below the + * License Header, with the fields enclosed by brackets [] replaced by + * your own identifying information: + * "Portions Copyrighted [year] [name of copyright owner]" + * + * Contributor(s): + * + * Portions Copyrighted 2009 Jaroslav Tulach + */ + +package cz.xelfi.quoridor.freemarkerdor; + +import com.sun.jersey.api.client.Client; +import com.sun.jersey.api.client.WebResource; +import com.sun.jersey.api.container.httpserver.HttpServerFactory; +import com.sun.jersey.api.core.PackagesResourceConfig; +import com.sun.jersey.api.core.ResourceConfig; +import com.sun.jersey.api.view.Viewable; +import com.sun.jersey.spi.resource.Singleton; +import com.sun.net.httpserver.HttpServer; +import cz.xelfi.quoridor.webidor.resources.Quoridor; +import java.io.IOException; +import java.net.URI; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.core.MediaType; +import org.codehaus.jettison.json.JSONArray; +import org.codehaus.jettison.json.JSONException; +import org.codehaus.jettison.json.JSONObject; + +/** + * + * @author Jaroslav Tulach + */ +@Path("/") +@Singleton +public final class UI { + private static WebResource base; + public UI() { + } + + @GET + @Path("/") + public Viewable welcome() throws JSONException { + Object obj = getJson(base.path("games")); + return new Viewable("index.fmt", obj); + } + + @GET + @Path("games/{id}") + public Viewable board(@PathParam("id") String id) throws JSONException { + Object obj = convert(base.path("games").path(id).accept(MediaType.TEXT_PLAIN_TYPE).get(String.class)); + + System.err.println("obj: " + obj); + return new Viewable("game.fmt", obj); + } + + + private static Object getJson(WebResource res) throws JSONException { + return convert(res.accept(MediaType.APPLICATION_JSON_TYPE).get(JSONArray.class)); + } + + private static Object convert(Object obj) throws JSONException { + if (obj instanceof JSONArray) { + JSONArray arr = (JSONArray)obj; + final int length = arr.length(); + List res = new ArrayList(length); + for (int i = 0; i < length; i++) { + res.add(convert(arr.get(i))); + } + return res; + } else if (obj instanceof JSONObject) { + JSONObject json = (JSONObject)obj; + Map map = new HashMap(json.length() * 2 / 3); + for (Iterator it = json.keys(); it.hasNext();) { + String key = (String)it.next(); + map.put(key, convert(json.get(key))); + } + return map; + } else { + return obj; + } + } + + // + // start the server + // + + public static void main(String[] args) throws Exception { + HttpServer api = Quoridor.start(9998); + Client client = new Client(); + base = client.resource(new URI("http://localhost:9998/api/")); + + HttpServer s = start(9997); + System.out.println( + "Quoridor started at port 9997\n" + "Hit enter to stop it..." + ); + System.in.read(); + s.stop(0); + System.exit(0); + } + + static HttpServer start(int port) throws IOException { + final String baseUri = "http://localhost:" + port + "/"; + ResourceConfig rc = new PackagesResourceConfig("cz.xelfi.quoridor.freemarkerdor"); + HttpServer server = HttpServerFactory.create(baseUri, rc); + server.start(); + return server; + } + +} diff -r e45bc8ad2eaf -r c94f68ddef59 freemarkerdor/src/main/resources/cz/xelfi/quoridor/freemarkerdor/UI/game.fmt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/freemarkerdor/src/main/resources/cz/xelfi/quoridor/freemarkerdor/UI/game.fmt Tue Aug 11 14:26:49 2009 +0200 @@ -0,0 +1,11 @@ + + + + + + + +

Game

+
${model}
+ + \ No newline at end of file diff -r e45bc8ad2eaf -r c94f68ddef59 freemarkerdor/src/main/resources/cz/xelfi/quoridor/freemarkerdor/UI/index.fmt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/freemarkerdor/src/main/resources/cz/xelfi/quoridor/freemarkerdor/UI/index.fmt Tue Aug 11 14:26:49 2009 +0200 @@ -0,0 +1,16 @@ + + + + + + + +

Quoridor Community Server

+ +
    + <#list model as item> +
  1. ${item.white} vs. ${item.black} board
  2. + +
+ + \ No newline at end of file diff -r e45bc8ad2eaf -r c94f68ddef59 pom.xml --- a/pom.xml Wed Jul 29 21:35:04 2009 +0200 +++ b/pom.xml Tue Aug 11 14:26:49 2009 +0200 @@ -37,6 +37,7 @@ quoridor visidor webidor + freemarkerdor Quoridor related projects Master project that agregates all quoridor related functionality. diff -r e45bc8ad2eaf -r c94f68ddef59 webidor/src/main/java/cz/xelfi/quoridor/webidor/resources/Quoridor.java --- a/webidor/src/main/java/cz/xelfi/quoridor/webidor/resources/Quoridor.java Wed Jul 29 21:35:04 2009 +0200 +++ b/webidor/src/main/java/cz/xelfi/quoridor/webidor/resources/Quoridor.java Tue Aug 11 14:26:49 2009 +0200 @@ -41,7 +41,7 @@ * * @author Jaroslav Tulach */ -@Path("/") +@Path("/api") @Singleton public final class Quoridor { private final File path; @@ -69,28 +69,27 @@ // public static void main(String[] args) throws IOException { + HttpServer s = start(9998); + System.out.println( + "Quoridor started at port 9998\n" + "Hit enter to stop it..." + ); + System.in.read(); + s.stop(0); + System.exit(0); + } - final String baseUri = "http://localhost:9998/"; - final Map initParams = new HashMap(); + public static HttpServer start(int port) throws IOException { + final String baseUri = "http://localhost:" + port + "/"; File home = new File(System.getProperty("user.home")); File quoridor = new File(home, ".quoridor"); System.setProperty("quoridor.dir", quoridor.getPath()); - initParams.put("com.sun.jersey.config.property.packages", - "cz.xelfi.quoridor.webidor.resources"); - - System.out.println("Starting Quoridor..."); ResourceConfig rc = new PackagesResourceConfig("cz.xelfi.quoridor.webidor"); - HttpServer threadSelector = HttpServerFactory.create(baseUri, rc); - threadSelector.start(); - System.out.println(String.format( - "Quoridor started with WADL available at %sapplication.wadl\n" + - "Hit enter to stop it...", baseUri, baseUri)); - System.in.read(); - threadSelector.stop(0); - System.exit(0); + HttpServer server = HttpServerFactory.create(baseUri, rc); + server.start(); + return server; } } diff -r e45bc8ad2eaf -r c94f68ddef59 webidor/src/test/java/cz/xelfi/quoridor/webidor/QuoridorTest.java --- a/webidor/src/test/java/cz/xelfi/quoridor/webidor/QuoridorTest.java Wed Jul 29 21:35:04 2009 +0200 +++ b/webidor/src/test/java/cz/xelfi/quoridor/webidor/QuoridorTest.java Tue Aug 11 14:26:49 2009 +0200 @@ -90,6 +90,7 @@ } @Test public void testCreateAGame() throws Exception { + webResource = webResource.path("api"); Game s = webResource.path("games").queryParam("white", "Jarda") .queryParam("black", "Jirka").post(Game.class);