chat/server/src/main/java/org/apidesign/demo/chat/server/ChatServerResource.java
author Jaroslav Tulach <jaroslav.tulach@apidesign.org>
Fri, 22 Apr 2016 05:56:47 +0200
branchNewChat
changeset 238 a0f15cb8c730
child 240 2d0750864a98
permissions -rw-r--r--
Switching to newer version of the libraries
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@238
    26
import java.util.ArrayList;
jaroslav@238
    27
import java.util.IdentityHashMap;
jaroslav@238
    28
import java.util.List;
jaroslav@238
    29
import java.util.Map;
jaroslav@238
    30
import java.util.logging.Logger;
jaroslav@238
    31
import javax.inject.Singleton;
jaroslav@238
    32
import javax.ws.rs.Consumes;
jaroslav@238
    33
import javax.ws.rs.DefaultValue;
jaroslav@238
    34
import javax.ws.rs.GET;
jaroslav@238
    35
import javax.ws.rs.POST;
jaroslav@238
    36
import javax.ws.rs.Path;
jaroslav@238
    37
import javax.ws.rs.Produces;
jaroslav@238
    38
import javax.ws.rs.QueryParam;
jaroslav@238
    39
import javax.ws.rs.container.AsyncResponse;
jaroslav@238
    40
import javax.ws.rs.container.Suspended;
jaroslav@238
    41
import javax.ws.rs.core.MediaType;
jaroslav@238
    42
import org.apidesign.demo.chat.shared.Message;
jaroslav@238
    43
import org.apidesign.demo.chat.shared.Query;
jaroslav@238
    44
jaroslav@238
    45
/** Server side of the chat application.*/
jaroslav@238
    46
@Path("/chat/") @Singleton
jaroslav@238
    47
public final class ChatServerResource {
jaroslav@238
    48
    private static final Logger LOG = Logger.getLogger(ChatServerResource.class.getName());
jaroslav@238
    49
    private static final long started = System.currentTimeMillis() - 10;
jaroslav@238
    50
    
jaroslav@238
    51
    private List<Message> msgs = new ArrayList<>();
jaroslav@238
    52
    {
jaroslav@238
    53
        Message welcome = new Message();
jaroslav@238
    54
        welcome.setUser("system");
jaroslav@238
    55
        welcome.setComment("Welcome and enjoy!");
jaroslav@238
    56
        welcome.setSince(10);
jaroslav@238
    57
        msgs.add(welcome);
jaroslav@238
    58
    }
jaroslav@238
    59
    
jaroslav@238
    60
    private final Map<AsyncResponse, Long> awaiting = new IdentityHashMap<>();
jaroslav@238
    61
    
jaroslav@238
    62
    @Produces(MediaType.APPLICATION_JSON)
jaroslav@238
    63
    @GET public synchronized void getResources(
jaroslav@238
    64
        @QueryParam("since") @DefaultValue("0") long since,
jaroslav@238
    65
        @Suspended AsyncResponse ar
jaroslav@238
    66
    ) {
jaroslav@238
    67
        Query q = new Query();
jaroslav@238
    68
        for (Message m : msgs) {
jaroslav@238
    69
            if (m.getSince()>= since) {
jaroslav@238
    70
                q.getMessages().add(m);
jaroslav@238
    71
            }
jaroslav@238
    72
        }
jaroslav@238
    73
        if (!q.getMessages().isEmpty()) {
jaroslav@238
    74
            ar.resume(q);
jaroslav@238
    75
        } else {
jaroslav@238
    76
            awaiting.put(ar, since);
jaroslav@238
    77
        }
jaroslav@238
    78
    }
jaroslav@238
    79
    
jaroslav@238
    80
    private void handleAwaiting(long newest) {
jaroslav@238
    81
        assert Thread.holdsLock(this);
jaroslav@238
    82
        AGAIN: for (;;) {
jaroslav@238
    83
            for (Map.Entry<AsyncResponse, Long> entry : awaiting.entrySet()) {
jaroslav@238
    84
                AsyncResponse ar = entry.getKey();
jaroslav@238
    85
                Long since = entry.getValue();
jaroslav@238
    86
                if (since <= newest) {
jaroslav@238
    87
                    awaiting.remove(ar);
jaroslav@238
    88
                    getResources(since, ar);
jaroslav@238
    89
                    continue AGAIN;
jaroslav@238
    90
                }
jaroslav@238
    91
            }
jaroslav@238
    92
            return;
jaroslav@238
    93
        }
jaroslav@238
    94
    }
jaroslav@238
    95
    
jaroslav@238
    96
    @POST @Consumes(value = MediaType.APPLICATION_JSON)
jaroslav@238
    97
    public synchronized Message publish(Message msg) {
jaroslav@238
    98
        msg.setSince(System.currentTimeMillis() - started);
jaroslav@238
    99
        msgs.add(msg);
jaroslav@238
   100
        handleAwaiting(msg.getSince());
jaroslav@238
   101
        return msg;
jaroslav@238
   102
    }
jaroslav@238
   103
}