freemarkerdor/src/main/java/cz/xelfi/quoridor/freemarkerdor/UI.java
author Jaroslav Tulach <jaroslav.tulach@apidesign.org>
Thu, 04 Mar 2010 19:37:58 +0100
changeset 233 ecddc9f373bb
parent 220 fca206f8e5ef
child 234 0a71b6bd786f
permissions -rw-r--r--
Changing an email needs to be confirmed by receiving an email and responding to an URL send inside it
jtulach@41
     1
/*
jtulach@41
     2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
jtulach@41
     3
 *
jtulach@41
     4
 * The contents of this file are subject to the terms of either the GNU
jtulach@41
     5
 * General Public License Version 2 only ("GPL") or the Common
jtulach@41
     6
 * Development and Distribution License("CDDL") (collectively, the
jtulach@41
     7
 * "License"). You may not use this file except in compliance with the
jtulach@41
     8
 * License. You can obtain a copy of the License at
jtulach@41
     9
 * http://www.netbeans.org/cddl-gplv2.html
jtulach@41
    10
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
jtulach@41
    11
 * specific language governing permissions and limitations under the
jtulach@41
    12
 * License.  When distributing the software, include this License Header
jtulach@41
    13
 * Notice in each file and include the License file at
jtulach@41
    14
 * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
jtulach@41
    15
 * particular file as subject to the "Classpath" exception as provided
jtulach@41
    16
 * by Sun in the GPL Version 2 section of the License file that
jtulach@41
    17
 * accompanied this code. If applicable, add the following below the
jtulach@41
    18
 * License Header, with the fields enclosed by brackets [] replaced by
jtulach@41
    19
 * your own identifying information:
jtulach@41
    20
 * "Portions Copyrighted [year] [name of copyright owner]"
jtulach@41
    21
 *
jtulach@41
    22
 * Contributor(s):
jtulach@41
    23
 *
jtulach@41
    24
 * Portions Copyrighted 2009 Jaroslav Tulach
jtulach@41
    25
 */
jtulach@41
    26
jtulach@41
    27
package cz.xelfi.quoridor.freemarkerdor;
jtulach@41
    28
jtulach@41
    29
import com.sun.jersey.api.client.Client;
jaroslav@56
    30
import com.sun.jersey.api.client.UniformInterfaceException;
jtulach@41
    31
import com.sun.jersey.api.client.WebResource;
jtulach@41
    32
import com.sun.jersey.api.container.httpserver.HttpServerFactory;
jtulach@41
    33
import com.sun.jersey.api.core.PackagesResourceConfig;
jtulach@41
    34
import com.sun.jersey.api.core.ResourceConfig;
jtulach@41
    35
import com.sun.jersey.api.view.Viewable;
jtulach@41
    36
import com.sun.net.httpserver.HttpServer;
jaroslav@99
    37
import cz.xelfi.quoridor.Board;
jaroslav@99
    38
import cz.xelfi.quoridor.IllegalPositionException;
jaroslav@88
    39
import java.io.IOException;
jaroslav@88
    40
import java.io.InputStream;
jaroslav@179
    41
import java.io.StringWriter;
jtulach@41
    42
import java.net.URI;
jaroslav@233
    43
import java.text.MessageFormat;
jaroslav@172
    44
import java.util.Date;
jaroslav@55
    45
import java.util.HashMap;
jaroslav@156
    46
import java.util.List;
jaroslav@59
    47
import java.util.Locale;
jaroslav@55
    48
import java.util.Map;
jaroslav@59
    49
import java.util.MissingResourceException;
jaroslav@88
    50
import java.util.Properties;
jaroslav@59
    51
import java.util.ResourceBundle;
jaroslav@50
    52
import java.util.concurrent.Callable;
jtulach@43
    53
import javax.ws.rs.DefaultValue;
jaroslav@47
    54
import javax.ws.rs.FormParam;
jtulach@41
    55
import javax.ws.rs.GET;
jaroslav@46
    56
import javax.ws.rs.POST;
jtulach@41
    57
import javax.ws.rs.Path;
jtulach@41
    58
import javax.ws.rs.PathParam;
jaroslav@46
    59
import javax.ws.rs.Produces;
jtulach@42
    60
import javax.ws.rs.QueryParam;
jaroslav@129
    61
import javax.ws.rs.core.CacheControl;
jtulach@42
    62
import javax.ws.rs.core.Context;
jaroslav@101
    63
import javax.ws.rs.core.Cookie;
jtulach@42
    64
import javax.ws.rs.core.HttpHeaders;
jtulach@41
    65
import javax.ws.rs.core.MediaType;
jaroslav@46
    66
import javax.ws.rs.core.NewCookie;
jaroslav@46
    67
import javax.ws.rs.core.Response;
jaroslav@101
    68
import javax.ws.rs.core.Response.ResponseBuilder;
jaroslav@99
    69
import org.openide.util.Exceptions;
jaroslav@48
    70
import org.w3c.dom.Document;
jtulach@41
    71
jtulach@41
    72
/**
jtulach@41
    73
 *
jtulach@41
    74
 * @author Jaroslav Tulach <jtulach@netbeans.org>
jtulach@41
    75
 */
jtulach@41
    76
@Path("/")
jtulach@41
    77
public final class UI {
jaroslav@88
    78
    private static final String version;
jaroslav@88
    79
    static {
jaroslav@88
    80
        Properties p = new Properties();
jaroslav@88
    81
        try {
jaroslav@186
    82
            InputStream is = FreemarkerProcessor.class.getResourceAsStream("/META-INF/maven/cz.xelfi.quoridor/freemarkerdor/pom.properties"); // NOI18N
jaroslav@88
    83
            if (is != null) {
jaroslav@88
    84
                p.load(is);
jaroslav@88
    85
            }
jaroslav@88
    86
        } catch (IOException ex) {
jaroslav@88
    87
            ex.printStackTrace();
jaroslav@88
    88
        }
jaroslav@88
    89
        version = p.getProperty("version", "unknown"); // NOI18N
jaroslav@88
    90
    }
jtulach@41
    91
    private static WebResource base;
jaroslav@178
    92
    private static WebResource stat;
jaroslav@233
    93
    private static WebResource web;
jaroslav@233
    94
    private static Requests requests;
jtulach@42
    95
jtulach@42
    96
    @Context
jtulach@42
    97
    private HttpHeaders headers;
jaroslav@146
    98
    private UserInfo user;
jtulach@82
    99
    private String uuid;
jtulach@42
   100
jtulach@41
   101
    public UI() {
jtulach@41
   102
    }
jtulach@41
   103
jaroslav@233
   104
    private String login() {
jaroslav@101
   105
        Cookie cookie = headers.getCookies().get("login");
jaroslav@101
   106
        if (cookie != null) {
jaroslav@233
   107
            return cookie.getValue();
jaroslav@233
   108
        }
jaroslav@233
   109
        return null;
jaroslav@233
   110
    }
jaroslav@233
   111
jaroslav@233
   112
    private Viewable checkLogin() {
jaroslav@233
   113
        String id = login();
jaroslav@233
   114
        if (id != null) {
jaroslav@146
   115
            UserInfo us;
jaroslav@85
   116
            try {
jaroslav@146
   117
                us = base.path("users").queryParam("loginID", id).
jaroslav@146
   118
                    accept(MediaType.TEXT_XML).get(UserInfo.class);
jaroslav@146
   119
            } catch (Exception ex) {
jaroslav@85
   120
                ex.printStackTrace();
jaroslav@146
   121
                us = null;
jaroslav@85
   122
            }
jaroslav@146
   123
            if (us != null && us.getId().length() > 0) {
jtulach@83
   124
                user = us;
jtulach@83
   125
                uuid = id;
jtulach@83
   126
                return null;
jtulach@83
   127
            }
jaroslav@46
   128
        }
jaroslav@56
   129
        return viewable("login.fmt", null);
jaroslav@46
   130
    }
jaroslav@46
   131
jaroslav@46
   132
    @POST
jaroslav@46
   133
    @Path("login")
jaroslav@46
   134
    @Produces(MediaType.TEXT_HTML)
jaroslav@46
   135
    public Response login(
jaroslav@47
   136
        @FormParam("name") String name, @FormParam("password") String password
jaroslav@46
   137
    ) throws Exception {
jtulach@82
   138
        uuid = base.path("login").queryParam("name", name).queryParam("password", password).
jtulach@82
   139
            accept(MediaType.TEXT_PLAIN).put(String.class);
jtulach@82
   140
        if (uuid != null) {
jaroslav@146
   141
            user = new UserInfo(name);
jaroslav@101
   142
            NewCookie nc = new NewCookie("login", uuid, null, null, null, 3600 * 24 * 7, false);
jaroslav@101
   143
            return Response.ok().cookie(nc).entity(viewable("login.fmt", null)).build();
jaroslav@46
   144
        } else {
jaroslav@56
   145
            Viewable v = viewable("login.fmt", null, "message", "Invalid name or password: " + name);
jaroslav@46
   146
            return Response.status(1).entity(v).build();
jaroslav@46
   147
        }
jaroslav@46
   148
    }
jaroslav@46
   149
jtulach@41
   150
    @GET
jaroslav@46
   151
    @Produces(MediaType.TEXT_HTML)
jaroslav@129
   152
    public Response welcome(@QueryParam("maxItems") @DefaultValue("10") int maxItems) {
jaroslav@46
   153
        Viewable v = checkLogin();
jaroslav@129
   154
        ResponseBuilder resp = Response.ok();
jaroslav@129
   155
        if (v == null) {
jaroslav@129
   156
            v = welcomeImpl("maxItems", maxItems);
jtulach@42
   157
        }
jaroslav@129
   158
        CacheControl cc = new CacheControl();
jaroslav@129
   159
        cc.setNoCache(true);
jaroslav@129
   160
        resp.cacheControl(cc);
jaroslav@129
   161
        return resp.entity(v).build();
jtulach@41
   162
    }
jtulach@41
   163
jaroslav@105
   164
    @GET
jaroslav@105
   165
    @Path("games/{id}.png")
jaroslav@105
   166
    @Produces("image/png")
jaroslav@129
   167
    public Response getBoardImage(
jaroslav@105
   168
        @PathParam("id") String id,
jaroslav@105
   169
        @QueryParam("fieldSize") @DefaultValue("50") int fieldSize,
jaroslav@105
   170
        @QueryParam("move") @DefaultValue("-1") int move
jaroslav@105
   171
    ) throws IllegalPositionException {
jaroslav@105
   172
        WebResource wr = base.path("games").path(id);
jaroslav@105
   173
        if (move != -1) {
jaroslav@106
   174
            wr = wr.queryParam("move", "" + move);
jaroslav@105
   175
        }
jaroslav@105
   176
        String txt = wr.accept(MediaType.TEXT_PLAIN).get(String.class);
jaroslav@105
   177
        Board b = Board.valueOf(txt);
jaroslav@178
   178
//        Board b = new Board(txt);
jaroslav@129
   179
        ResponseBuilder resp = Response.ok();
jaroslav@129
   180
        CacheControl cc = new CacheControl();
jaroslav@129
   181
        cc.setNoCache(true);
jaroslav@129
   182
        resp.cacheControl(cc);
jaroslav@129
   183
        return resp.entity(BoardImage.draw(b, fieldSize)).build();
jaroslav@105
   184
    }
jaroslav@105
   185
jaroslav@105
   186
jaroslav@101
   187
    private Response board(String id) {
jaroslav@100
   188
        return board(id, "", null);
jaroslav@95
   189
    }
jtulach@41
   190
    @GET
jtulach@43
   191
    @Path("games/{id}/")
jaroslav@46
   192
    @Produces(MediaType.TEXT_HTML)
jaroslav@101
   193
    public Response board(
jaroslav@100
   194
        @PathParam("id") String id,
jaroslav@100
   195
        @QueryParam("format") @DefaultValue("") String format,
jaroslav@100
   196
        @QueryParam("move") @DefaultValue("-1") String move
jaroslav@100
   197
    ) {
jaroslav@100
   198
        return board(id, null, format, move);
jaroslav@56
   199
    }
jaroslav@101
   200
    private Response board(@PathParam("id") String id, String msg, String format, String m) {
jaroslav@46
   201
        Viewable v = checkLogin();
jaroslav@46
   202
        if (v != null) {
jaroslav@101
   203
            return Response.ok().entity(v).build();
jaroslav@46
   204
        }
jaroslav@100
   205
        int move;
jaroslav@100
   206
        try {
jaroslav@100
   207
            move = Integer.parseInt(m);
jaroslav@100
   208
        } catch (NumberFormatException ex) {
jaroslav@100
   209
            move = -1;
jaroslav@100
   210
        }
jtulach@170
   211
        WebResource url = base.path("games").queryParam("loginID", uuid).path(id);
jaroslav@100
   212
        if (move >= 0) {
jaroslav@100
   213
            url = url.queryParam("move", "" + move);
jaroslav@100
   214
        }
jaroslav@101
   215
        ResponseBuilder resp = Response.ok();
jaroslav@129
   216
        CacheControl cc = new CacheControl();
jaroslav@129
   217
        cc.setNoCache(true);
jaroslav@129
   218
        resp.cacheControl(cc);
jaroslav@101
   219
        Cookie cFormat = headers.getCookies().get("format");
jaroslav@101
   220
        if (format.length() == 0) {
jaroslav@101
   221
            if (cFormat != null) {
jaroslav@101
   222
                format = cFormat.getValue();
jaroslav@156
   223
            } else {
jaroslav@156
   224
                if (isMobile(headers)) {
jaroslav@156
   225
                    format = "small";
jaroslav@156
   226
                }
jaroslav@101
   227
            }
jaroslav@101
   228
        } else {
jaroslav@101
   229
            if (cFormat == null || !format.equals(cFormat.getValue())) {
jaroslav@101
   230
                resp.cookie(new NewCookie("format", format));
jaroslav@101
   231
            }
jaroslav@101
   232
        }
jaroslav@101
   233
jaroslav@100
   234
        Document doc = url.accept(MediaType.TEXT_XML).get(Document.class);
jaroslav@99
   235
        Board b;
jaroslav@178
   236
        String t = doc.getElementsByTagName("board").item(0).getTextContent();
jaroslav@99
   237
        try {
jaroslav@99
   238
            b = Board.valueOf(doc.getElementsByTagName("board").item(0).getTextContent());
jaroslav@178
   239
        } catch (Exception ex) {
jaroslav@178
   240
//            b = new Board(t);
jaroslav@178
   241
//        } catch (IllegalStateException ex) {
jaroslav@99
   242
            Exceptions.printStackTrace(ex);
jaroslav@99
   243
            b = Board.empty();
jaroslav@99
   244
        }
jaroslav@178
   245
        String bCode = null;
jaroslav@178
   246
        try{
jaroslav@179
   247
            bCode = stat.path("openings").path(b.getCode()+".check").queryParam("loginID", user.getId()).accept(MediaType.TEXT_PLAIN).get(String.class);
jaroslav@178
   248
        }catch(Exception e){
jaroslav@178
   249
            bCode = null;
jaroslav@178
   250
        }
jaroslav@178
   251
        if(bCode == null || "".equals(bCode))
jaroslav@179
   252
            v = viewable("game.fmt", doc, "message", msg, "format", format, "board", b,"textPicture", boardToPicture(b));
jaroslav@178
   253
        else
jaroslav@179
   254
            v = viewable("game.fmt", doc, "message", msg, "format", format, "board", b,"textPicture", boardToPicture(b),"bCode", bCode);
jaroslav@101
   255
        return resp.entity(v).build();
jtulach@42
   256
    }
jtulach@41
   257
jaroslav@179
   258
    private static String boardToPicture(Board b) {
jaroslav@179
   259
        StringWriter w = new StringWriter();
jaroslav@179
   260
        try {
jaroslav@179
   261
            b.write(w);
jaroslav@179
   262
        } catch (IOException ex) {
jaroslav@179
   263
            return ex.toString();
jaroslav@179
   264
        }
jaroslav@179
   265
        return w.toString();
jaroslav@179
   266
    }
jaroslav@179
   267
jtulach@42
   268
    @GET
jtulach@43
   269
    @Path("games/{id}/move")
jaroslav@46
   270
    @Produces(MediaType.TEXT_HTML)
jaroslav@101
   271
    public Response move(
jtulach@43
   272
        @PathParam("id") String id,
jtulach@43
   273
        @QueryParam("type") String type,
jtulach@43
   274
        @QueryParam("direction") String direction,
jtulach@43
   275
        @QueryParam("direction-next") @DefaultValue("") String directionNext,
jtulach@43
   276
        @QueryParam("column") @DefaultValue("") String column,
jtulach@43
   277
        @QueryParam("row") @DefaultValue("") String row
jtulach@54
   278
    ) {
jaroslav@46
   279
        Viewable v = checkLogin();
jaroslav@46
   280
        if (v != null) {
jaroslav@101
   281
            return Response.ok().entity(v).build();
jaroslav@46
   282
        }
jtulach@82
   283
        WebResource wr = base.path("games").path(id).
jtulach@82
   284
            queryParam("loginID", uuid).
jaroslav@146
   285
            queryParam("player", user.getId());
jaroslav@56
   286
        try {
jtulach@75
   287
            if (type.equals("resign")) {
jtulach@75
   288
                wr.queryParam("move", "RESIGN").put();
jtulach@75
   289
                return board(id);
jtulach@75
   290
            }
jaroslav@56
   291
            if (type.equals("fence")) {
jaroslav@56
   292
                wr.queryParam("move", direction.charAt(0) + column + row).put();
jaroslav@56
   293
                return board(id);
jaroslav@56
   294
            }
jaroslav@56
   295
            if (type.equals("move")) {
jaroslav@56
   296
                wr.queryParam("move", direction + directionNext).put();
jaroslav@56
   297
                return board(id);
jaroslav@56
   298
            }
jaroslav@56
   299
        } catch (UniformInterfaceException ex) {
jaroslav@100
   300
            return board(id, "WRONG_MOVE", "-1");
jtulach@43
   301
        }
jtulach@43
   302
        return board(id);
jtulach@43
   303
    }
jtulach@43
   304
jtulach@43
   305
    @GET
jaroslav@115
   306
    @Path("games/{id}/comment")
jaroslav@115
   307
    @Produces(MediaType.TEXT_HTML)
jaroslav@115
   308
    public Response comment(
jaroslav@115
   309
        @PathParam("id") String id,
jaroslav@115
   310
        @QueryParam("comment") String comment
jaroslav@115
   311
    ) {
jaroslav@115
   312
        Viewable v = checkLogin();
jaroslav@115
   313
        if (v != null) {
jaroslav@115
   314
            return Response.ok().entity(v).build();
jaroslav@115
   315
        }
jaroslav@115
   316
        WebResource wr = base.path("games").path(id).
jaroslav@115
   317
            queryParam("loginID", uuid).
jaroslav@146
   318
            queryParam("player", user.getId()).
jaroslav@115
   319
            queryParam("comment", comment);
jaroslav@115
   320
        wr.put();
jaroslav@115
   321
        
jaroslav@115
   322
        return board(id);
jaroslav@115
   323
    }
jaroslav@115
   324
jaroslav@115
   325
    @GET
jtulach@42
   326
    @Path("games/create")
jaroslav@46
   327
    @Produces(MediaType.TEXT_HTML)
jaroslav@73
   328
    public Response create(
jtulach@42
   329
        @QueryParam("white") String white,
jtulach@42
   330
        @QueryParam("black") String black
jtulach@54
   331
    ) {
jaroslav@46
   332
        Viewable v = checkLogin();
jaroslav@46
   333
        if (v != null) {
jaroslav@73
   334
            return Response.status(Response.Status.FORBIDDEN).entity(v).build();
jaroslav@46
   335
        }
jaroslav@57
   336
jaroslav@146
   337
        if (user.getId().equals(white) || user.getId().equals(black)) {
jaroslav@57
   338
            Object obj =
jtulach@82
   339
                base.path("games").
jtulach@82
   340
                queryParam("loginID", uuid).
jtulach@82
   341
                queryParam("white", white).
jaroslav@73
   342
                queryParam("black", black).accept(MediaType.TEXT_XML).post(Document.class);
jaroslav@73
   343
            return Response.ok(welcomeImpl()).build();
jaroslav@57
   344
        } else {
jaroslav@73
   345
            return Response.status(Response.Status.NOT_FOUND).
jaroslav@146
   346
                entity(welcomeImpl("message", "You (" + user.getId() + ") must be white or black!")).build();
jaroslav@57
   347
        }
jtulach@41
   348
    }
jtulach@41
   349
jaroslav@57
   350
    private Viewable welcomeImpl(Object... args) {
jtulach@168
   351
        final Document got = base.path("games").queryParam("loginID", uuid).accept(MediaType.TEXT_XML).get(Document.class);
jaroslav@57
   352
        return viewable("index.fmt", got, args);
jtulach@41
   353
    }
jtulach@41
   354
jaroslav@233
   355
    @Path("requests")
jaroslav@233
   356
    public Requests getRequests() {
jaroslav@233
   357
        if (requests == null) {
jaroslav@233
   358
            requests = new Requests(web.path("requests"));
jaroslav@233
   359
        }
jaroslav@233
   360
        return requests;
jaroslav@233
   361
    }
jaroslav@233
   362
jaroslav@146
   363
jaroslav@146
   364
    @GET
jaroslav@146
   365
    @Path("options")
jaroslav@146
   366
    public Response changeOptions(
jaroslav@146
   367
        @QueryParam("email") String email,
jaroslav@233
   368
        @QueryParam("language") String language,
jaroslav@233
   369
        @QueryParam("verified") String verified
jaroslav@233
   370
    ) throws IOException {
jaroslav@146
   371
        Viewable v = checkLogin();
jaroslav@146
   372
        if (v != null) {
jaroslav@146
   373
            return Response.status(Response.Status.FORBIDDEN).entity(v).build();
jaroslav@146
   374
        }
jaroslav@146
   375
jaroslav@146
   376
        if (email != null) {
jaroslav@233
   377
            if (getRequests().isVerified(verified)) {
jaroslav@233
   378
                UserInfo ui = base.path("users/" + user.getId()).
jaroslav@233
   379
                    queryParam("loginID", uuid).
jaroslav@233
   380
                    queryParam("name", "email").
jaroslav@233
   381
                    queryParam("value", email).accept(MediaType.TEXT_XML).post(UserInfo.class);
jaroslav@233
   382
            } else {
jaroslav@233
   383
                WebResource request;
jaroslav@233
   384
                request = web.path("options").queryParam("name", "email").queryParam("email", email);
jaroslav@233
   385
                URI callback = getRequests().register(login(), request);
jaroslav@233
   386
jaroslav@233
   387
                ResourceBundle rb = bundle(null);
jaroslav@233
   388
                String subject = rb.getString("MSG_ChangeEmailSubject");
jaroslav@233
   389
                String text = MessageFormat.format(rb.getString("MSG_ChangeEmailText"), user.getId(), callback);
jaroslav@233
   390
                EmailService.getDefault().sendEmail(email, subject, text);
jaroslav@233
   391
                return Response.ok(viewable("email.fmt", null)).build();
jaroslav@233
   392
jaroslav@233
   393
            }
jaroslav@146
   394
        }
jaroslav@146
   395
jaroslav@146
   396
        if (language != null) {
jaroslav@146
   397
            UserInfo ui = base.path("users/" + user.getId()).
jaroslav@146
   398
                queryParam("loginID", uuid).
jaroslav@146
   399
                queryParam("name", "language").
jaroslav@146
   400
                queryParam("value", language).
jaroslav@146
   401
                accept(MediaType.TEXT_XML).post(UserInfo.class);
jaroslav@146
   402
        }
jaroslav@146
   403
jaroslav@146
   404
        return welcome(10);
jaroslav@146
   405
    }
jaroslav@178
   406
jaroslav@178
   407
    @GET
jaroslav@178
   408
    @Path("elo")
jaroslav@178
   409
    @Produces(MediaType.TEXT_HTML)
martin@195
   410
    public Response getEloList(
martin@212
   411
            @QueryParam("historyId") @DefaultValue("0") Integer historyId){
jaroslav@178
   412
        Viewable v = checkLogin();
jaroslav@178
   413
        if (v != null) {
jaroslav@178
   414
            return Response.status(Response.Status.FORBIDDEN).entity(v).build();
jaroslav@178
   415
        }
martin@212
   416
        final Document got = stat.path("elo").path("list").path(historyId.toString()).accept(MediaType.TEXT_XML).get(Document.class);
martin@212
   417
        return Response.ok(viewable("elo.fmt", got, "historyId", historyId)).build();
jaroslav@178
   418
    }
jaroslav@146
   419
    
jaroslav@178
   420
    @GET
jaroslav@178
   421
    @Path("openings")
jaroslav@178
   422
    @Produces(MediaType.TEXT_HTML)
jaroslav@178
   423
    public Response getOpeningRoot(){
jaroslav@178
   424
        return getOpeningNode("ROOT");
jaroslav@178
   425
    }
jaroslav@178
   426
jaroslav@178
   427
    @GET
jaroslav@178
   428
    @Path("openings/{code}")
jaroslav@178
   429
    @Produces(MediaType.TEXT_HTML)
jaroslav@178
   430
    public Response getOpeningNode(@PathParam("code") String code){
jaroslav@178
   431
        Viewable v = checkLogin();
jaroslav@178
   432
        if (v != null) {
jaroslav@178
   433
            return Response.status(Response.Status.FORBIDDEN).entity(v).build();
jaroslav@178
   434
        }
jaroslav@178
   435
        final Document got = stat.path("openings").path(code).queryParam("loginID", user.getId()).accept(MediaType.TEXT_XML).get(Document.class);
jaroslav@178
   436
        Board b;
jaroslav@178
   437
        try {
jaroslav@178
   438
            b = Board.valueOf(got.getElementsByTagName("nodeCode").item(0).getTextContent());
jaroslav@178
   439
        } catch (Exception ex) {
jaroslav@178
   440
            Exceptions.printStackTrace(ex);
jaroslav@178
   441
            b = Board.empty();
jaroslav@178
   442
        }
jaroslav@178
   443
        return Response.ok(viewable("openings.fmt", got, "whitefences",b.getPlayers().get(0).getFences(),"blackfences",b.getPlayers().get(1).getFences())).build();
jaroslav@178
   444
    }
jaroslav@178
   445
jaroslav@178
   446
    @GET
jaroslav@178
   447
    @Path("openings/{code}/{status}")
jaroslav@178
   448
    @Produces(MediaType.TEXT_HTML)
jaroslav@178
   449
    public Response getOpeningNodeGames(@PathParam("code") String code, @PathParam("status") String status){
jaroslav@178
   450
        Viewable v = checkLogin();
jaroslav@178
   451
        if (v != null) {
jaroslav@178
   452
            return Response.status(Response.Status.FORBIDDEN).entity(v).build();
jaroslav@178
   453
        }
jaroslav@178
   454
        final Document got = stat.path("openings").path(code).path(status).queryParam("loginID", user.getId()).accept(MediaType.TEXT_XML).get(Document.class);
jaroslav@178
   455
        return Response.ok(viewable("opening_games.fmt", got,"code",code,"color",status)).build();
jaroslav@178
   456
    }
jaroslav@178
   457
jaroslav@178
   458
    @GET
jaroslav@178
   459
    @Path("openings/{code}.png")
jaroslav@178
   460
    @Produces("image/png")
jaroslav@178
   461
    public Response getOpeningBoardImage(
jaroslav@178
   462
        @PathParam("code") String code,
jaroslav@178
   463
        @QueryParam("fieldSize") @DefaultValue("40") int fieldSize
jaroslav@178
   464
    ) throws IllegalPositionException {
jaroslav@179
   465
        Board b = Board.valueOf(code);
jaroslav@178
   466
        ResponseBuilder resp = Response.ok();
jaroslav@178
   467
        CacheControl cc = new CacheControl();
jaroslav@178
   468
        cc.setNoCache(true);
jaroslav@178
   469
        resp.cacheControl(cc);
jaroslav@178
   470
        return resp.entity(BoardImage.draw(b, fieldSize)).build();
jaroslav@178
   471
    }
jaroslav@178
   472
jtulach@41
   473
    //
jtulach@41
   474
    // start the server
jtulach@41
   475
    //
jtulach@41
   476
jtulach@41
   477
    public static void main(String[] args) throws Exception {
jaroslav@121
   478
        int port = 9333;
jaroslav@68
   479
        if (args.length > 1) {
jaroslav@68
   480
            port = Integer.parseInt(args[0]);
jaroslav@68
   481
        }
jaroslav@132
   482
        String remoteAPI = args.length >= 2 ? args[1] : null;
martin@180
   483
        String remoteStatistics = args.length >= 3 ? args[2] : null;
jaroslav@50
   484
jaroslav@146
   485
        Locale.setDefault(Locale.ROOT);
jaroslav@68
   486
martin@180
   487
        Callable<Void> r = startServers(port, remoteAPI, remoteStatistics);
jaroslav@68
   488
martin@180
   489
        if (args.length < 3 || !args[args.length - 1].equals("--kill")) {
jaroslav@68
   490
            System.out.println("Hit enter to stop it...");
jaroslav@68
   491
            System.in.read();
jaroslav@68
   492
        } else {
jaroslav@68
   493
            synchronized (UI.class) {
jaroslav@68
   494
                UI.class.wait();
jaroslav@68
   495
            }
jaroslav@68
   496
        }
jaroslav@50
   497
        r.call();
jaroslav@50
   498
        System.exit(0);
jaroslav@50
   499
    }
jaroslav@50
   500
martin@180
   501
    static Callable<Void> startServers(int port, String remoteAPI, String remoteStatistics) throws Exception {
jaroslav@121
   502
        Client client = new Client();
jaroslav@178
   503
        Client client1 = new Client();
jaroslav@72
   504
jaroslav@121
   505
        final HttpServer apiServer;
jaroslav@121
   506
        if (remoteAPI == null) {
jaroslav@126
   507
            throw new IllegalArgumentException("Provide URL to API server"); // NOI18N
jaroslav@121
   508
        } else {
jaroslav@121
   509
            base = client.resource(new URI(remoteAPI));
martin@180
   510
            apiServer = null;
martin@180
   511
        }
martin@180
   512
jaroslav@220
   513
        if (remoteStatistics != null) {
jaroslav@220
   514
            stat = client1.resource(new URI(remoteStatistics));
martin@180
   515
        } else {
jaroslav@178
   516
            stat = client1.resource(new URI("http://localhost:9444"));
jaroslav@73
   517
        }
jaroslav@72
   518
jaroslav@72
   519
        ResourceConfig rc = new PackagesResourceConfig(
jaroslav@72
   520
            "cz.xelfi.quoridor.freemarkerdor"
jaroslav@72
   521
        );
jaroslav@72
   522
jaroslav@72
   523
        final String baseUri = "http://localhost:" + port + "/";
jaroslav@72
   524
        final HttpServer server = HttpServerFactory.create(baseUri, rc);
jaroslav@233
   525
        Client c3 = new Client();
jaroslav@233
   526
        web = c3.resource(baseUri);
jaroslav@72
   527
        server.start();
jaroslav@68
   528
        System.out.println("Quoridor started at port " + port);
jaroslav@50
   529
jaroslav@50
   530
        return new Callable<Void>() {
jaroslav@50
   531
            public Void call() throws Exception {
jaroslav@121
   532
                if (apiServer != null) {
jaroslav@121
   533
                    apiServer.stop(0);
jaroslav@121
   534
                }
jaroslav@72
   535
                server.stop(0);
jaroslav@50
   536
                return null;
jaroslav@50
   537
            }
jaroslav@50
   538
        };
jtulach@41
   539
    }
jtulach@41
   540
jaroslav@233
   541
    private ResourceBundle bundle(Locale[] locale) {
jaroslav@59
   542
        ResourceBundle rb = null;
jaroslav@146
   543
        String lng = user == null ? null : user.getProperty("language"); // NOI18N
jaroslav@146
   544
        if (lng != null) {
jaroslav@233
   545
            try {
jaroslav@233
   546
                Locale l = new Locale(lng);
jaroslav@233
   547
                rb = ResourceBundle.getBundle("cz.xelfi.quoridor.freemarkerdor.UI.Bundle", l);
jaroslav@233
   548
                if (locale != null) {
jaroslav@233
   549
                    locale[0] = l;
jaroslav@146
   550
                }
jaroslav@233
   551
            } catch (MissingResourceException e) {
jaroslav@233
   552
                // OK
jaroslav@233
   553
            }
jaroslav@146
   554
        }
jaroslav@146
   555
        if (rb == null) {
jaroslav@146
   556
            for (Locale l : headers.getAcceptableLanguages()) {
jaroslav@146
   557
                try {
jaroslav@146
   558
                    rb = ResourceBundle.getBundle("cz.xelfi.quoridor.freemarkerdor.UI.Bundle", l);
jaroslav@233
   559
                    if (locale != null) {
jaroslav@233
   560
                        locale[0] = l;
jaroslav@233
   561
                    }
jaroslav@172
   562
                    break;
jaroslav@146
   563
                } catch (MissingResourceException e) {
jaroslav@146
   564
                    // OK
jaroslav@146
   565
                }
jaroslav@59
   566
            }
jaroslav@59
   567
        }
jaroslav@59
   568
        if (rb == null) {
jtulach@80
   569
            rb = ResourceBundle.getBundle("cz.xelfi.quoridor.freemarkerdor.UI.Bundle", Locale.ENGLISH);
jaroslav@233
   570
            if (locale != null) {
jaroslav@233
   571
                locale[0] = Locale.ENGLISH;
jaroslav@233
   572
            }
jaroslav@59
   573
        }
jaroslav@233
   574
        return rb;
jaroslav@233
   575
    }
jaroslav@233
   576
jaroslav@233
   577
    private Viewable viewable(String page, Document doc, Object... more) {
jaroslav@233
   578
        Locale[] locale = new Locale[1];
jaroslav@233
   579
        ResourceBundle rb = bundle(locale);
jaroslav@59
   580
jaroslav@56
   581
        Map<String,Object> map = new HashMap<String,Object>();
jaroslav@172
   582
        class ConvertToDate extends HashMap<Object,Object> {
jaroslav@172
   583
            @Override
jaroslav@172
   584
            public Object get(Object o) {
jaroslav@172
   585
                long time = Long.parseLong(o.toString());
jaroslav@172
   586
                return new Date(time);
jaroslav@172
   587
            }
jaroslav@172
   588
        }
jaroslav@172
   589
jaroslav@233
   590
        map.put("locale", locale[0].toString());
jaroslav@56
   591
        map.put("doc", doc);
jaroslav@146
   592
        if (user != null) {
jaroslav@146
   593
            map.put("user", user.getId());
jaroslav@146
   594
            map.put("email", user.getProperty("email"));
jaroslav@146
   595
        }
jaroslav@59
   596
        map.put("bundle", rb);
jaroslav@172
   597
        map.put("toDate", new ConvertToDate());
jtulach@78
   598
        map.put("now", System.currentTimeMillis());
jaroslav@88
   599
        map.put("version", version);
jaroslav@56
   600
        for (int i = 0; i < more.length; i += 2) {
jaroslav@56
   601
            map.put((String)more[i],more[i + 1]);
jaroslav@56
   602
        }
jaroslav@56
   603
        return new Viewable(page, map);
jaroslav@56
   604
    }
jaroslav@56
   605
jaroslav@156
   606
jaroslav@156
   607
    private static boolean isMobile(HttpHeaders headers) {
jaroslav@156
   608
        final String[] keywords = {
jaroslav@156
   609
            "Profile/MIDP",
jaroslav@156
   610
        };
jaroslav@156
   611
        List<String> agent = headers.getRequestHeader(HttpHeaders.USER_AGENT);
jaroslav@156
   612
        if (agent != null) {
jaroslav@156
   613
            for (String a : agent) {
jaroslav@156
   614
                for (String k : keywords) {
jaroslav@156
   615
                    if (a.contains(k)) {
jaroslav@156
   616
                        return true;
jaroslav@156
   617
                    }
jaroslav@156
   618
                }
jaroslav@156
   619
            }
jaroslav@156
   620
        }
jaroslav@156
   621
        return false;
jaroslav@156
   622
    }
jaroslav@156
   623
jtulach@41
   624
}