chat/server/src/main/java/org/apidesign/demo/chat/server/ChatServerResource.java
author Jaroslav Tulach <jaroslav.tulach@apidesign.org>
Fri, 22 Apr 2016 18:13:09 +0200
branchNewChat
changeset 242 58596208d06d
parent 241 6a59fdb91011
permissions -rw-r--r--
Exchanging messages over WebSockets in the default desktop client
jaroslav@238
     1
/**
jaroslav@238
     2
 * The MIT License (MIT)
jaroslav@238
     3
 *
jaroslav@238
     4
 * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
jaroslav@238
     5
 *
jaroslav@238
     6
 * Permission is hereby granted, free of charge, to any person obtaining a copy
jaroslav@238
     7
 * of this software and associated documentation files (the "Software"), to deal
jaroslav@238
     8
 * in the Software without restriction, including without limitation the rights
jaroslav@238
     9
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
jaroslav@238
    10
 * copies of the Software, and to permit persons to whom the Software is
jaroslav@238
    11
 * furnished to do so, subject to the following conditions:
jaroslav@238
    12
 *
jaroslav@238
    13
 * The above copyright notice and this permission notice shall be included in
jaroslav@238
    14
 * all copies or substantial portions of the Software.
jaroslav@238
    15
 *
jaroslav@238
    16
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
jaroslav@238
    17
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
jaroslav@238
    18
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
jaroslav@238
    19
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
jaroslav@238
    20
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
jaroslav@238
    21
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
jaroslav@238
    22
 * THE SOFTWARE.
jaroslav@238
    23
 */
jaroslav@238
    24
package org.apidesign.demo.chat.server;
jaroslav@238
    25
jaroslav@241
    26
import java.io.ByteArrayInputStream;
jaroslav@241
    27
import java.io.IOException;
jaroslav@238
    28
import java.util.ArrayList;
jaroslav@242
    29
import java.util.HashSet;
jaroslav@238
    30
import java.util.List;
jaroslav@242
    31
import java.util.Set;
jaroslav@238
    32
import java.util.logging.Logger;
jaroslav@241
    33
import net.java.html.BrwsrCtx;
jaroslav@241
    34
import net.java.html.json.Models;
jaroslav@238
    35
import org.apidesign.demo.chat.shared.Message;
jaroslav@241
    36
import org.apidesign.demo.chat.shared.Query;
jaroslav@242
    37
import org.apidesign.demo.chat.shared.Reply;
jaroslav@242
    38
import org.glassfish.grizzly.websockets.DataFrame;
jaroslav@240
    39
import org.glassfish.grizzly.websockets.WebSocket;
jaroslav@240
    40
import org.glassfish.grizzly.websockets.WebSocketApplication;
jaroslav@238
    41
jaroslav@238
    42
/** Server side of the chat application.*/
jaroslav@240
    43
public final class ChatServerResource extends WebSocketApplication {
jaroslav@238
    44
    private static final Logger LOG = Logger.getLogger(ChatServerResource.class.getName());
jaroslav@238
    45
    private static final long started = System.currentTimeMillis() - 10;
jaroslav@238
    46
    
jaroslav@238
    47
    private List<Message> msgs = new ArrayList<>();
jaroslav@238
    48
    {
jaroslav@238
    49
        Message welcome = new Message();
jaroslav@238
    50
        welcome.setUser("system");
jaroslav@238
    51
        welcome.setComment("Welcome and enjoy!");
jaroslav@238
    52
        welcome.setSince(10);
jaroslav@238
    53
        msgs.add(welcome);
jaroslav@238
    54
    }
jaroslav@240
    55
jaroslav@240
    56
jaroslav@242
    57
    private final Set<WebSocket> connected = new HashSet<>();
jaroslav@240
    58
/*
jaroslav@238
    59
    
jaroslav@238
    60
    @Produces(MediaType.APPLICATION_JSON)
jaroslav@238
    61
    @GET public synchronized void getResources(
jaroslav@238
    62
        @QueryParam("since") @DefaultValue("0") long since,
jaroslav@238
    63
        @Suspended AsyncResponse ar
jaroslav@238
    64
    ) {
jaroslav@238
    65
        Query q = new Query();
jaroslav@238
    66
        for (Message m : msgs) {
jaroslav@238
    67
            if (m.getSince()>= since) {
jaroslav@238
    68
                q.getMessages().add(m);
jaroslav@238
    69
            }
jaroslav@238
    70
        }
jaroslav@238
    71
        if (!q.getMessages().isEmpty()) {
jaroslav@238
    72
            ar.resume(q);
jaroslav@238
    73
        } else {
jaroslav@238
    74
            awaiting.put(ar, since);
jaroslav@238
    75
        }
jaroslav@238
    76
    }
jaroslav@242
    77
    */
jaroslav@242
    78
    private void handleAwaiting(Message msg) {
jaroslav@238
    79
        assert Thread.holdsLock(this);
jaroslav@242
    80
        Reply reply = new Reply();
jaroslav@242
    81
        reply.getMessages().add(msg);
jaroslav@242
    82
        String txt = reply.toString();
jaroslav@242
    83
        for (WebSocket webSocket : connected) {
jaroslav@242
    84
            webSocket.send(txt);
jaroslav@238
    85
        }
jaroslav@238
    86
    }
jaroslav@242
    87
jaroslav@242
    88
    private synchronized Message publish(Message msg) {
jaroslav@238
    89
        msg.setSince(System.currentTimeMillis() - started);
jaroslav@238
    90
        msgs.add(msg);
jaroslav@242
    91
        handleAwaiting(msg);
jaroslav@238
    92
        return msg;
jaroslav@238
    93
    }
jaroslav@242
    94
jaroslav@242
    95
    @Override
jaroslav@242
    96
    public void onConnect(WebSocket socket) {
jaroslav@242
    97
        connected.add(socket);
jaroslav@242
    98
    }
jaroslav@242
    99
jaroslav@242
   100
    @Override
jaroslav@242
   101
    public void onClose(WebSocket socket, DataFrame frame) {
jaroslav@242
   102
        connected.remove(socket);
jaroslav@242
   103
    }
jaroslav@240
   104
jaroslav@240
   105
    @Override
jaroslav@240
   106
    public void onMessage(WebSocket socket, String text) {
jaroslav@241
   107
        try {
jaroslav@241
   108
            ByteArrayInputStream is = new ByteArrayInputStream(text.getBytes("UTF-8"));
jaroslav@241
   109
            Query q = Models.parse(BrwsrCtx.findDefault(ChatServerResource.class), Query.class, is);
jaroslav@242
   110
            if (q.getPost() != null) {
jaroslav@242
   111
                publish(q.getPost());
jaroslav@242
   112
            }
jaroslav@242
   113
            if (q.isAll()) {
jaroslav@242
   114
                socket.send(new Reply(true, msgs.toArray(new Message[0])).toString());
jaroslav@242
   115
            }
jaroslav@241
   116
        } catch (IOException ex) {
jaroslav@241
   117
            throw new IllegalStateException(ex);
jaroslav@241
   118
        }
jaroslav@240
   119
    }
jaroslav@238
   120
}