jtulach@35: /* jaroslav@264: * Quoridor server and related libraries jaroslav@264: * Copyright (C) 2009-2010 Jaroslav Tulach jtulach@35: * jaroslav@264: * This program is free software: you can redistribute it and/or modify jaroslav@264: * it under the terms of the GNU General Public License as published by jaroslav@264: * the Free Software Foundation, either version 3 of the License. jtulach@35: * jaroslav@264: * This program is distributed in the hope that it will be useful, jaroslav@264: * but WITHOUT ANY WARRANTY; without even the implied warranty of jaroslav@264: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the jaroslav@264: * GNU General Public License for more details. jtulach@35: * jaroslav@264: * You should have received a copy of the GNU General Public License jaroslav@264: * along with this program. Look for COPYING file in the top folder. jaroslav@264: * If not, see http://www.gnu.org/licenses/. jtulach@35: */ jtulach@35: jtulach@35: package cz.xelfi.quoridor.webidor.resources; jtulach@35: jaroslav@282: import com.sun.jersey.api.container.grizzly2.GrizzlyServerFactory; jtulach@35: import com.sun.jersey.api.core.PackagesResourceConfig; jtulach@35: import com.sun.jersey.api.core.ResourceConfig; jaroslav@189: import com.sun.jersey.api.json.JSONWithPadding; jtulach@35: import com.sun.jersey.spi.resource.Singleton; jtulach@37: import java.io.File; jtulach@82: import java.io.FileInputStream; jtulach@35: import java.io.IOException; jaroslav@52: import java.net.ServerSocket; jtulach@82: import java.util.HashMap; jtulach@82: import java.util.Map; jtulach@82: import java.util.Properties; jtulach@82: import java.util.UUID; jtulach@82: import javax.ws.rs.GET; jtulach@82: import javax.ws.rs.PUT; jtulach@35: import javax.ws.rs.Path; jtulach@82: import javax.ws.rs.Produces; jtulach@82: import javax.ws.rs.QueryParam; jaroslav@189: import javax.ws.rs.WebApplicationException; jtulach@82: import javax.ws.rs.core.MediaType; jaroslav@189: import javax.ws.rs.core.Response.Status; jaroslav@282: import org.glassfish.grizzly.http.server.HttpServer; jtulach@35: jtulach@35: /** jtulach@35: * jtulach@35: * @author Jaroslav Tulach jtulach@35: */ jaroslav@124: @Path("/") jtulach@35: @Singleton jtulach@35: public final class Quoridor { jtulach@37: private final File path; jtulach@37: private Games games; jaroslav@143: private Users users; jtulach@82: private final Map loggedIn; jtulach@37: jtulach@37: public Quoridor() { jtulach@37: final String prop = System.getProperty("quoridor.dir"); // NOI18N jtulach@37: if (prop == null) { jtulach@37: throw new IllegalStateException("quoridor.dir property must be specified"); // NOI18N jtulach@37: } jtulach@37: path = new File(prop); jtulach@37: path.mkdirs(); jtulach@82: loggedIn = new HashMap(); jaroslav@189: games = new Games(new File(path, "games"), this); // NOI18N jaroslav@189: users = new Users(new File(path, "users"), this); // NOI18N jtulach@37: } jtulach@35: jtulach@35: @Path("games") jtulach@36: public Games getGames() { jtulach@35: return games; jtulach@35: } jtulach@35: jaroslav@143: @Path("users") jaroslav@143: public Users getUsers() { jaroslav@143: return users; jaroslav@143: } jaroslav@143: jtulach@82: @Path("login") jtulach@82: @PUT jaroslav@145: @Produces({ MediaType.TEXT_PLAIN }) jtulach@82: public String login( jtulach@82: @QueryParam("name") String name, jtulach@82: @QueryParam("password") String password jtulach@239: ) throws IOException { jtulach@82: File f = new File(path, "passwd"); // NOI18Nt jtulach@82: Properties p = new Properties(); jtulach@82: try { jtulach@82: p.load(new FileInputStream(f)); jtulach@82: } catch (IOException ex) { jtulach@82: ex.printStackTrace(); jtulach@82: } jtulach@239: boolean loggedInOK = false; jtulach@82: if (name != null && password.equals(p.getProperty(name))) { jtulach@239: loggedInOK = true; jtulach@239: } else { jtulach@239: loggedInOK = getUsers().verifyPassword(name, password); jtulach@239: } jtulach@239: jtulach@239: if (loggedInOK) { jtulach@82: UUID uuid = UUID.randomUUID(); jtulach@82: loggedIn.put(uuid, name); jtulach@82: return uuid.toString(); jtulach@82: } else { jtulach@82: return null; jtulach@82: } jtulach@82: jtulach@82: } jtulach@82: jtulach@82: @Path("login") jtulach@82: @GET jaroslav@145: @Produces({ MediaType.TEXT_PLAIN }) jtulach@82: public String isLoggedIn( jtulach@82: @QueryParam("id") String id jtulach@82: ) { jaroslav@85: String ret = null; jtulach@83: try { jaroslav@85: if (id != null) { jaroslav@85: ret = loggedIn.get(UUID.fromString(id)); jaroslav@85: } jtulach@83: } catch (IllegalArgumentException ex) { jaroslav@85: // OK, happens for invalid ids jtulach@83: } jaroslav@85: return ret == null ? "" : ret; jtulach@82: } jtulach@82: jaroslav@145: @Path("login") jaroslav@145: @GET jaroslav@189: @Produces({ "application/x-javascript", MediaType.APPLICATION_JSON, MediaType.TEXT_XML }) jaroslav@189: public JSONWithPadding loggedInInfo( jaroslav@189: @QueryParam("callback") String callback, jaroslav@145: @QueryParam("id") String id jaroslav@145: ) throws IOException { jaroslav@145: String ret = null; jaroslav@145: try { jaroslav@145: if (id != null) { jaroslav@145: ret = loggedIn.get(UUID.fromString(id)); jaroslav@145: } jaroslav@145: } catch (IllegalArgumentException ex) { jaroslav@145: // OK, happens for invalid ids jaroslav@145: } jaroslav@189: if (ret == null) { jaroslav@189: throw new WebApplicationException(Status.UNAUTHORIZED); jaroslav@189: } else { jaroslav@189: return getUsers().getUserInfo(callback, id, ret); jaroslav@189: } jaroslav@145: } jaroslav@145: jtulach@35: // jtulach@35: // start the server jtulach@35: // jtulach@35: jaroslav@123: public static void main(String[] args) throws IOException, InterruptedException { jaroslav@121: int port = 9222; jaroslav@121: try { jaroslav@121: port = Integer.parseInt(args[0]); jaroslav@121: } catch (Exception ex) { jaroslav@121: // OK jaroslav@121: } jaroslav@121: HttpServer s = start(port); jtulach@41: System.out.println( jaroslav@121: "Quoridor started at port " + port + "\n" + "Hit enter to stop it..." jtulach@41: ); jaroslav@123: if (args.length < 2 || !args[args.length - 1].equals("--kill")) { jaroslav@123: System.out.println("Hit enter to stop it..."); jaroslav@123: System.in.read(); jaroslav@123: } else { jaroslav@123: synchronized (Quoridor.class) { jaroslav@123: Quoridor.class.wait(); jaroslav@123: } jaroslav@123: } jtulach@41: System.in.read(); jaroslav@282: s.stop(); jtulach@41: System.exit(0); jtulach@41: } jtulach@35: jtulach@41: public static HttpServer start(int port) throws IOException { jaroslav@52: if (port == -1) { jaroslav@52: ServerSocket ss = new ServerSocket(0); jaroslav@52: port =ss.getLocalPort(); jaroslav@52: ss.close(); jaroslav@52: } jtulach@41: final String baseUri = "http://localhost:" + port + "/"; jtulach@35: jaroslav@121: if (System.getProperty("quoridor.dir") == null) { jaroslav@121: File home = new File(System.getProperty("user.home")); jaroslav@121: File quoridor = new File(home, ".quoridor"); jaroslav@121: System.setProperty("quoridor.dir", quoridor.getPath()); jaroslav@121: } jtulach@38: jtulach@35: ResourceConfig rc = new PackagesResourceConfig("cz.xelfi.quoridor.webidor"); jaroslav@282: HttpServer server = GrizzlyServerFactory.createHttpServer(baseUri, rc); jtulach@41: server.start(); jtulach@41: return server; jtulach@35: } jtulach@35: jtulach@35: }