serverside/src/main/java/org/apidesign/bck2brwsr/demo/serverside/ChatServerResource.java
changeset 11 40fce839ac01
parent 10 80715a1dd72e
     1.1 --- a/serverside/src/main/java/org/apidesign/bck2brwsr/demo/serverside/ChatServerResource.java	Sun May 05 17:20:46 2013 +0200
     1.2 +++ b/serverside/src/main/java/org/apidesign/bck2brwsr/demo/serverside/ChatServerResource.java	Sun May 05 18:04:13 2013 +0200
     1.3 @@ -26,13 +26,20 @@
     1.4  import java.io.Closeable;
     1.5  import java.lang.reflect.Field;
     1.6  import java.util.ArrayList;
     1.7 +import java.util.IdentityHashMap;
     1.8  import java.util.List;
     1.9 +import java.util.Map;
    1.10  import java.util.concurrent.Callable;
    1.11 +import java.util.logging.Level;
    1.12 +import java.util.logging.Logger;
    1.13 +import javax.inject.Singleton;
    1.14  import javax.ws.rs.Consumes;
    1.15 +import javax.ws.rs.DefaultValue;
    1.16  import javax.ws.rs.GET;
    1.17  import javax.ws.rs.PUT;
    1.18  import javax.ws.rs.Path;
    1.19  import javax.ws.rs.Produces;
    1.20 +import javax.ws.rs.QueryParam;
    1.21  import javax.ws.rs.container.AsyncResponse;
    1.22  import javax.ws.rs.container.Suspended;
    1.23  import javax.ws.rs.core.MediaType;
    1.24 @@ -44,10 +51,11 @@
    1.25  import org.glassfish.jersey.server.ContainerFactory;
    1.26  import org.glassfish.jersey.server.ResourceConfig;
    1.27  
    1.28 -/** Server side of the chat application.
    1.29 - */
    1.30 -@Path("/")
    1.31 +/** Server side of the chat application.*/
    1.32 +@Path("/") @Singleton
    1.33  public final class ChatServerResource {
    1.34 +    private static final Logger LOG = Logger.getLogger(ChatServerResource.class.getName());
    1.35 + 
    1.36      public static void main(String... args) throws Exception {
    1.37          ResourceConfig rc = new ResourceConfig(ChatServerResource.class);
    1.38          GrizzlyHttpContainer c = ContainerFactory.createContainer(GrizzlyHttpContainer.class, rc);
    1.39 @@ -73,17 +81,53 @@
    1.40          msgs.add(welcome);
    1.41      }
    1.42      
    1.43 +    private final Map<AsyncResponse, Long> awaiting = new IdentityHashMap<>();
    1.44 +    
    1.45      @Produces(MediaType.APPLICATION_JSON)
    1.46 -    @GET public void getResources(@Suspended AsyncResponse ar) {
    1.47 -        Query q = new Query(Context.findDefault(Query.class));
    1.48 -        q.getMessages().addAll(msgs);
    1.49 -        ar.resume(q);
    1.50 +    @GET public synchronized void getResources(
    1.51 +        @QueryParam("since") @DefaultValue("0") long since,
    1.52 +        @Suspended AsyncResponse ar
    1.53 +    ) {
    1.54 +        Query q = new Query(Context.findDefault(ChatServerResource.class));
    1.55 +        for (Message m : msgs) {
    1.56 +            if (m.getWhen() >= since) {
    1.57 +                q.getMessages().add(m);
    1.58 +            }
    1.59 +        }
    1.60 +        if (!q.getMessages().isEmpty()) {
    1.61 +            ar.resume(q);
    1.62 +        } else {
    1.63 +            awaiting.put(ar, since);
    1.64 +        }
    1.65      }
    1.66      
    1.67 -    @Consumes(MediaType.APPLICATION_JSON)
    1.68 -    @PUT public void publish(Message msg) {
    1.69 -        if (msg != null) {
    1.70 -            msgs.add(msg);
    1.71 +    private void handleAwaiting(long newest) {
    1.72 +        assert Thread.holdsLock(this);
    1.73 +        AGAIN: for (;;) {
    1.74 +            for (Map.Entry<AsyncResponse, Long> entry : awaiting.entrySet()) {
    1.75 +                AsyncResponse ar = entry.getKey();
    1.76 +                Long since = entry.getValue();
    1.77 +                if (since <= newest) {
    1.78 +                    awaiting.remove(ar);
    1.79 +                    getResources(since, ar);
    1.80 +                    continue AGAIN;
    1.81 +                }
    1.82 +            }
    1.83 +            return;
    1.84          }
    1.85      }
    1.86 +    
    1.87 +    @Path("addComment") @GET 
    1.88 +    public synchronized Message publish(
    1.89 +        @QueryParam("user") String user,
    1.90 +        @QueryParam("comment") String comment
    1.91 +    ) {
    1.92 +        Message msg = new Message(Context.findDefault(ChatServerResource.class));
    1.93 +        msg.setUser(user);
    1.94 +        msg.setComment(comment);
    1.95 +        msg.setWhen(System.currentTimeMillis());
    1.96 +        msgs.add(msg);
    1.97 +        handleAwaiting(msg.getWhen());
    1.98 +        return msg;
    1.99 +    }
   1.100  }