# HG changeset patch # User Jaroslav Tulach # Date 1247399947 -7200 # Node ID 2e85dd878f04772b878dc4986028dd675483db3e # Parent 34baf57f2d4e941db3963063a7eeeca2c803b0d7 Converting the webidor into Jersey based REST server diff -r 34baf57f2d4e -r 2e85dd878f04 pom.xml --- a/pom.xml Sun Jul 12 13:35:58 2009 +0200 +++ b/pom.xml Sun Jul 12 13:59:07 2009 +0200 @@ -36,8 +36,9 @@ quoridor visidor + webidor Quoridor related projects Master project that agregates all quoridor related functionality. - + \ No newline at end of file diff -r 34baf57f2d4e -r 2e85dd878f04 webidor/nb-configuration.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/webidor/nb-configuration.xml Sun Jul 12 13:59:07 2009 +0200 @@ -0,0 +1,21 @@ + + + + + + src/main/webapp/WEB-INF/applicationContext.xml + src/main/webapp/WEB-INF/dispatcher-servlet.xml + + + + src/main/webapp/WEB-INF/applicationContext.xml + src/main/webapp/WEB-INF/dispatcher-servlet.xml + + + + diff -r 34baf57f2d4e -r 2e85dd878f04 webidor/nbactions.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/webidor/nbactions.xml Sun Jul 12 13:59:07 2009 +0200 @@ -0,0 +1,15 @@ + + + + run + + process-classes + org.codehaus.mojo:exec-maven-plugin:1.1.1:exec + + + runtime + -classpath %classpath cz.xelfi.quoridor.webidor.Main + java + + + diff -r 34baf57f2d4e -r 2e85dd878f04 webidor/pom.xml --- a/webidor/pom.xml Sun Jul 12 13:35:58 2009 +0200 +++ b/webidor/pom.xml Sun Jul 12 13:59:07 2009 +0200 @@ -8,56 +8,59 @@ org.apidesign webidor - war + jar 1.0 - webidor JEE5 Webapp + webidor server http://maven.apache.org + + + maven2-repository.dev.java.net + Java.net Repository for Maven + http://download.java.net/maven/2/ + default + + + maven-repository.dev.java.net + Java.net Maven 1 Repository (legacy) + http://download.java.net/maven/1 + legacy + + - javax.servlet - servlet-api - 2.5 - provided - - - - javax.servlet.jsp - jsp-api - 2.1 - provided - - - junit junit - 3.8.1 + 4.5 test - org.springframework - spring-webmvc - 2.5 + com.sun.jersey + jersey-core + 1.1.0-ea - org.springframework - spring - 2.5 + com.sun.jersey + jersey-server + 1.1.0-ea - org.springframework.security - spring-security-openid - 2.0.4 - - - icu4j - com.ibm.icu - - - xml-apis - xml-apis - - + com.sun.jersey + jersey-json + 1.1.0-ea + jar + + + com.sun.jersey.test.framework + jersey-test-framework + 1.1.0-ea + test + + + org.apidesign + quoridor + 1.0 + jar @@ -71,15 +74,14 @@ 1.5 + + org.codehaus.mojo + exec-maven-plugin + + cz.xelfi.quoridor.webidor.Main + + webidor - - gfv3 - - - - - - diff -r 34baf57f2d4e -r 2e85dd878f04 webidor/src/main/java/cz/xelfi/quoridor/webidor/Game.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/webidor/src/main/java/cz/xelfi/quoridor/webidor/Game.java Sun Jul 12 13:59:07 2009 +0200 @@ -0,0 +1,99 @@ +/* + * 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.webidor; + +import cz.xelfi.quoridor.Board; +import cz.xelfi.quoridor.IllegalPositionException; +import cz.xelfi.quoridor.Move; +import cz.xelfi.quoridor.Player; +import java.util.UUID; +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlID; +import javax.xml.bind.annotation.XmlRootElement; + +/** + * + * @author Jaroslav Tulach + */ +@XmlRootElement +@XmlAccessorType(XmlAccessType.FIELD) +public final class Game { + @XmlAttribute + private String white; + @XmlAttribute + private String black; + @XmlID + private String id; + + private transient Board board; + + Game() { + } + + public Game(String first, String second) { + this.white = first; + this.black = second; + this.id = UUID.randomUUID().toString(); + } + + public String getId() { + return id; + } + + public String getWhite() { + return white; + } + + public String getBlack() { + return black; + } + + public Board getBoard() { + if (board == null) { + board = Board.empty(); + } + return board; + } + + public void apply(String player, Move m) throws IllegalPositionException { + Player p = null; + if (getWhite().equals(player)) { + p = getBoard().getPlayers().get(0); + } else { + if (getBlack().equals(player)) { + p = getBoard().getPlayers().get(1); + } + } + if (p != getBoard().getCurrentPlayer()) { + throw new IllegalArgumentException("Wrong player: " + player); + } + + board = getBoard().apply(m); + } +} diff -r 34baf57f2d4e -r 2e85dd878f04 webidor/src/main/java/cz/xelfi/quoridor/webidor/JAXBContextResolver.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/webidor/src/main/java/cz/xelfi/quoridor/webidor/JAXBContextResolver.java Sun Jul 12 13:59:07 2009 +0200 @@ -0,0 +1,70 @@ +/* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved. + * + * 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 https://jersey.dev.java.net/CDDL+GPL.html + * or jersey/legal/LICENSE.txt. 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 jersey/legal/LICENSE.txt. + * 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): + * + * If you wish your version of this file to be governed by only the CDDL or + * only the GPL Version 2, indicate your decision by adding "[Contributor] + * elects to include this software in this distribution under the [CDDL or GPL + * Version 2] license." If you don't indicate a single choice of license, a + * recipient has the option to distribute your version of this file under + * either the CDDL, the GPL Version 2 or to extend the choice of license to + * its licensees as provided above. However, if you add GPL Version 2 code + * and therefore, elected the GPL Version 2 license, then the option applies + * only if the new code is made subject to such option by the copyright + * holder. + */ + +package cz.xelfi.quoridor.webidor; + +import com.sun.jersey.api.json.JSONConfiguration; +import com.sun.jersey.api.json.JSONJAXBContext; +import java.util.Arrays; +import java.util.HashSet; +import java.util.Set; +import javax.ws.rs.ext.ContextResolver; +import javax.ws.rs.ext.Provider; +import javax.xml.bind.JAXBContext; + +/** + * + * @author japod + */ +@Provider +public final class JAXBContextResolver implements ContextResolver { + + private final JAXBContext context; + + private final Set types; + + private final Class[] cTypes = {Game.class }; + + public JAXBContextResolver() throws Exception { + this.types = new HashSet(Arrays.asList(cTypes)); + this.context = new JSONJAXBContext(JSONConfiguration.natural().build(), cTypes); + } + + public JAXBContext getContext(Class objectType) { + return (types.contains(objectType)) ? context : null; + } +} \ No newline at end of file diff -r 34baf57f2d4e -r 2e85dd878f04 webidor/src/main/java/cz/xelfi/quoridor/webidor/UserDetailsImpl.java --- a/webidor/src/main/java/cz/xelfi/quoridor/webidor/UserDetailsImpl.java Sun Jul 12 13:35:58 2009 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,53 +0,0 @@ -/* - * To change this template, choose Tools | Templates - * and open the template in the editor. - */ - -package cz.xelfi.quoridor.webidor; - -import org.springframework.dao.DataAccessException; -import org.springframework.security.GrantedAuthority; -import org.springframework.security.GrantedAuthorityImpl; -import org.springframework.security.userdetails.UserDetails; -import org.springframework.security.userdetails.UserDetailsService; -import org.springframework.security.userdetails.UsernameNotFoundException; - -/** - * - * @author Jaroslav Tulach - */ -public class UserDetailsImpl implements UserDetailsService { - - public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException, DataAccessException { - return new UserDetails() { - public GrantedAuthority[] getAuthorities() { - return new GrantedAuthority[] { new GrantedAuthorityImpl("ROLE_USER") }; - } - - public String getPassword() { - return "ok"; - } - - public String getUsername() { - return "jarda"; - } - - public boolean isAccountNonExpired() { - return true; - } - - public boolean isAccountNonLocked() { - return true; - } - - public boolean isCredentialsNonExpired() { - return true; - } - - public boolean isEnabled() { - return true; - } - }; - } - -} diff -r 34baf57f2d4e -r 2e85dd878f04 webidor/src/main/java/cz/xelfi/quoridor/webidor/resources/Quoridor.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/webidor/src/main/java/cz/xelfi/quoridor/webidor/resources/Quoridor.java Sun Jul 12 13:59:07 2009 +0200 @@ -0,0 +1,122 @@ +/* + * 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.webidor.resources; + +import com.sun.jersey.api.container.httpserver.HttpServerFactory; +import com.sun.jersey.api.core.PackagesResourceConfig; +import com.sun.jersey.api.core.ResourceConfig; +import cz.xelfi.quoridor.IllegalPositionException; +import cz.xelfi.quoridor.webidor.*; +import com.sun.jersey.spi.resource.Singleton; +import com.sun.net.httpserver.HttpServer; +import cz.xelfi.quoridor.Move; +import java.io.IOException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.PUT; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.QueryParam; +import javax.ws.rs.core.MediaType; + +/** + * + * @author Jaroslav Tulach + */ +@Path("/") +@Singleton +public final class Quoridor { + private List games = new ArrayList(); + + @POST + @Path("games") + public Game createGame(@QueryParam("white") String user1, @QueryParam("black") String user2) { + Game g = new Game(user1, user2); + games.add(g); + return g; + } + + @PUT + @Path("games/{id}") + public Game applyMove(@PathParam("id") String id, @QueryParam("player") String player, @QueryParam("move") String move) + throws IllegalPositionException { + Game g = findGame(id); + if (g == null) { + throw new IllegalArgumentException("Unknown game " + id); + } + Move m = Move.valueOf(move); + g.apply(player, m); + return g; + } + + @GET + @Produces(MediaType.APPLICATION_JSON) + @Path("games") + public List getGames() { + return games; + } + + private Game findGame(String id) { + for (Game g : games) { + if (g.getId().equals(id)) { + return g; + } + } + return null; + } + + + // + // start the server + // + + public static void main(String[] args) throws IOException { + + final String baseUri = "http://localhost:9998/"; + final Map initParams = new HashMap(); + + initParams.put("com.sun.jersey.config.property.packages", + "cz.xelfi.quoridor.webidor.resources"); + + System.out.println("Starting HttpServer..."); + ResourceConfig rc = new PackagesResourceConfig("cz.xelfi.quoridor.webidor"); + HttpServer threadSelector = HttpServerFactory.create(baseUri, rc); + threadSelector.start(); + System.out.println(String.format( + "Jersey app started with WADL available at %sapplication.wadl\n" + + "Try out %shelloworld\nHit enter to stop it...", baseUri, baseUri)); + System.in.read(); + threadSelector.stop(0); + System.exit(0); + } + +} diff -r 34baf57f2d4e -r 2e85dd878f04 webidor/src/main/webapp/WEB-INF/applicationContext.xml --- a/webidor/src/main/webapp/WEB-INF/applicationContext.xml Sun Jul 12 13:35:58 2009 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,41 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - diff -r 34baf57f2d4e -r 2e85dd878f04 webidor/src/main/webapp/WEB-INF/dispatcher-servlet.xml --- a/webidor/src/main/webapp/WEB-INF/dispatcher-servlet.xml Sun Jul 12 13:35:58 2009 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,39 +0,0 @@ - - - - - - - - - - indexController - - - - - - - - - - - diff -r 34baf57f2d4e -r 2e85dd878f04 webidor/src/main/webapp/WEB-INF/jsp/index.jsp --- a/webidor/src/main/webapp/WEB-INF/jsp/index.jsp Sun Jul 12 13:35:58 2009 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,19 +0,0 @@ -<%@page contentType="text/html" pageEncoding="UTF-8"%> - - - - - - Welcome to Spring Web MVC project - - - -

Hello ${id}! This is the default welcome page for a Spring Web MVC project.

-

To display a different welcome page for this project, modify - index.jsp , or create your own welcome page then change - the redirection in redirect.jsp to point to the new - welcome page and also update the welcome-file setting in - web.xml.

- - diff -r 34baf57f2d4e -r 2e85dd878f04 webidor/src/main/webapp/WEB-INF/jsp/login.jsp --- a/webidor/src/main/webapp/WEB-INF/jsp/login.jsp Sun Jul 12 13:35:58 2009 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,18 +0,0 @@ -<%@page contentType="text/html" pageEncoding="UTF-8"%> - - - - - - Login - - -

Login

- -
- Open ID: - -
- - diff -r 34baf57f2d4e -r 2e85dd878f04 webidor/src/main/webapp/WEB-INF/jsp/loginredirection.jsp --- a/webidor/src/main/webapp/WEB-INF/jsp/loginredirection.jsp Sun Jul 12 13:35:58 2009 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,20 +0,0 @@ -<%-- - ~ Copyright 2006-2008 Sxip Identity Corporation - --%> - - -<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> - - - OpenID HTML FORM Redirection - - -
- - - - -
- - diff -r 34baf57f2d4e -r 2e85dd878f04 webidor/src/main/webapp/WEB-INF/sun-web.xml --- a/webidor/src/main/webapp/WEB-INF/sun-web.xml Sun Jul 12 13:35:58 2009 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,11 +0,0 @@ - - - - - - - Keep a copy of the generated servlet class' java code. - - - - diff -r 34baf57f2d4e -r 2e85dd878f04 webidor/src/main/webapp/WEB-INF/web.xml --- a/webidor/src/main/webapp/WEB-INF/web.xml Sun Jul 12 13:35:58 2009 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,37 +0,0 @@ - - - webidor - - contextConfigLocation - /WEB-INF/applicationContext.xml - - - springSecurityFilterChain - org.springframework.web.filter.DelegatingFilterProxy - - - - springSecurityFilterChain - /* - - - org.springframework.web.context.ContextLoaderListener - - - dispatcher - org.springframework.web.servlet.DispatcherServlet - 2 - - - dispatcher - *.html - - - - 30 - - - - index.jsp - - diff -r 34baf57f2d4e -r 2e85dd878f04 webidor/src/main/webapp/index.jsp --- a/webidor/src/main/webapp/index.jsp Sun Jul 12 13:35:58 2009 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,13 +0,0 @@ -<%@page contentType="text/html" pageEncoding="UTF-8"%> - - - - - - JSP Page - - -

Hello World!

- - diff -r 34baf57f2d4e -r 2e85dd878f04 webidor/src/main/webapp/redirect.jsp --- a/webidor/src/main/webapp/redirect.jsp Sun Jul 12 13:35:58 2009 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,9 +0,0 @@ -<%-- -Views should be stored under the WEB-INF folder so that -they are not accessible except through controller process. - -This JSP is here to provide a redirect to the dispatcher -servlet but should be the only JSP outside of WEB-INF. ---%> -<%@page contentType="text/html" pageEncoding="UTF-8"%> -<% response.sendRedirect("index.html"); %> diff -r 34baf57f2d4e -r 2e85dd878f04 webidor/src/test/java/cz/xelfi/quoridor/webidor/QuoridorTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/webidor/src/test/java/cz/xelfi/quoridor/webidor/QuoridorTest.java Sun Jul 12 13:59:07 2009 +0200 @@ -0,0 +1,88 @@ +/* + * 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.webidor; + +import com.sun.jersey.api.client.GenericType; +import com.sun.jersey.api.client.UniformInterfaceException; +import com.sun.jersey.core.header.MediaTypes; +import com.sun.jersey.test.framework.JerseyTest; +import java.util.List; +import org.junit.Test; +import static org.junit.Assert.*; + +/** + * + * @author Jaroslav Tulach + */ +public class QuoridorTest extends JerseyTest { + + public QuoridorTest() throws Exception { + super("cz.xelfi.quoridor.webidor.resources"); + } + + /** + * Test if a WADL document is available at the relative path + * "application.wadl". + */ + @Test public void testApplicationWadl() { + String serviceWadl = webResource.path("application.wadl"). + accept(MediaTypes.WADL).get(String.class); + assertTrue(serviceWadl.length() > 0); + } + + @Test public void testCreateAGame() { + Game s = webResource.path("games").queryParam("white", "Jarda") + .queryParam("black", "Jirka").post(Game.class); + + String msg = webResource.path("games").get(String.class); + //List games = webResource.path("games").get(new GenericType>() {}); + + GenericType> gType = new GenericType>() {}; + + List games = webResource.path("games").accept("application/json").get(gType); + assertEquals("One game", 1, games.size()); + assertEquals("Same white", "Jarda", games.get(0).getWhite()); + assertEquals("Same black", "Jirka", games.get(0).getBlack()); + + Game s1 = webResource.path("games/" + s.getId()).queryParam("player", "Jarda").queryParam("move", "N").put(Game.class); + try { + Game s2 = webResource.path("games/" + s.getId()).queryParam("player", "Jarda").queryParam("move", "N").put(Game.class); + fail("Not Jarda's turn, previous call shall fail"); + } catch (UniformInterfaceException ex) { + // OK + } + try { + Game s2 = webResource.path("games/" + s.getId()).queryParam("player", "Jirka").queryParam("move", "NONSENCE").put(Game.class); + fail("Invalid move"); + } catch (UniformInterfaceException ex) { + // OK + } + Game s2 = webResource.path("games/" + s.getId()).queryParam("player", "Jirka").queryParam("move", "S").put(Game.class); + assertNotNull("Successful move", s2); + } + +}