Author: yurize
Date: Sat Apr 21 20:10:04 2012
New Revision: 1328731

URL: http://svn.apache.org/viewvc?rev=1328731&view=rev
Log:
Adds notifier servlet. https://reviews.apache.org/r/4829/

Added:
    
incubator/wave/trunk/src/org/waveprotocol/box/server/rpc/AbstractSearchServlet.java
    
incubator/wave/trunk/src/org/waveprotocol/box/server/rpc/NotificationServlet.java
Modified:
    incubator/wave/trunk/src/org/waveprotocol/box/server/ServerMain.java
    incubator/wave/trunk/src/org/waveprotocol/box/server/rpc/SearchServlet.java

Modified: incubator/wave/trunk/src/org/waveprotocol/box/server/ServerMain.java
URL: 
http://svn.apache.org/viewvc/incubator/wave/trunk/src/org/waveprotocol/box/server/ServerMain.java?rev=1328731&r1=1328730&r2=1328731&view=diff
==============================================================================
--- incubator/wave/trunk/src/org/waveprotocol/box/server/ServerMain.java 
(original)
+++ incubator/wave/trunk/src/org/waveprotocol/box/server/ServerMain.java Sat 
Apr 21 20:10:04 2012
@@ -55,12 +55,14 @@ import org.waveprotocol.box.server.rpc.A
 import org.waveprotocol.box.server.rpc.FetchProfilesServlet;
 import org.waveprotocol.box.server.rpc.FetchServlet;
 import org.waveprotocol.box.server.rpc.GadgetProviderServlet;
+import org.waveprotocol.box.server.rpc.NotificationServlet;
 import org.waveprotocol.box.server.rpc.SearchServlet;
 import org.waveprotocol.box.server.rpc.ServerRpcProvider;
 import org.waveprotocol.box.server.rpc.SignOutServlet;
 import org.waveprotocol.box.server.rpc.UserRegistrationServlet;
 import org.waveprotocol.box.server.rpc.WaveClientServlet;
 import org.waveprotocol.box.server.rpc.WaveRefServlet;
+import org.waveprotocol.box.server.waveserver.ImportServlet;
 import org.waveprotocol.box.server.waveserver.WaveBus;
 import org.waveprotocol.box.server.waveserver.WaveServerException;
 import org.waveprotocol.box.server.waveserver.WaveletProvider;
@@ -73,7 +75,6 @@ import org.waveprotocol.wave.model.versi
 import org.waveprotocol.wave.model.wave.ParticipantIdUtil;
 import org.waveprotocol.wave.util.logging.Log;
 import org.waveprotocol.wave.util.settings.SettingsBinder;
-import org.waveprotocol.box.server.waveserver.ImportServlet;
 
 import java.io.IOException;
 import java.util.Collections;
@@ -222,6 +223,7 @@ public class ServerMain {
 
     server.addServlet("/fetch/*", FetchServlet.class);
     server.addServlet("/search/*", SearchServlet.class);
+    server.addServlet("/notification/*", NotificationServlet.class);
 
     server.addServlet("/robot/dataapi", DataApiServlet.class);
     server.addServlet(DataApiOAuthServlet.DATA_API_OAUTH_PATH + "/*", 
DataApiOAuthServlet.class);

Added: 
incubator/wave/trunk/src/org/waveprotocol/box/server/rpc/AbstractSearchServlet.java
URL: 
http://svn.apache.org/viewvc/incubator/wave/trunk/src/org/waveprotocol/box/server/rpc/AbstractSearchServlet.java?rev=1328731&view=auto
==============================================================================
--- 
incubator/wave/trunk/src/org/waveprotocol/box/server/rpc/AbstractSearchServlet.java
 (added)
+++ 
incubator/wave/trunk/src/org/waveprotocol/box/server/rpc/AbstractSearchServlet.java
 Sat Apr 21 20:10:04 2012
@@ -0,0 +1,121 @@
+/**
+ * Copyright 2012 Apache Wave.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.waveprotocol.box.server.rpc;
+
+import com.google.wave.api.JsonRpcConstant.ParamsProperty;
+import com.google.wave.api.JsonRpcResponse;
+import com.google.wave.api.OperationQueue;
+import com.google.wave.api.OperationRequest;
+import com.google.wave.api.ProtocolVersion;
+import com.google.wave.api.SearchResult;
+import com.google.wave.api.data.converter.EventDataConverterManager;
+
+import org.waveprotocol.box.search.SearchProto.SearchRequest;
+import org.waveprotocol.box.server.authentication.SessionManager;
+import org.waveprotocol.box.server.robots.OperationContextImpl;
+import org.waveprotocol.box.server.robots.OperationServiceRegistry;
+import org.waveprotocol.box.server.robots.util.ConversationUtil;
+import org.waveprotocol.box.server.robots.util.OperationUtil;
+import org.waveprotocol.box.server.waveserver.WaveletProvider;
+import org.waveprotocol.wave.model.wave.ParticipantId;
+import org.waveprotocol.wave.util.logging.Log;
+
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+/**
+ * A base for servlets that provide search functionality.
+ *
+ * @author [email protected] (Yuri Z.)
+ */
+@SuppressWarnings("serial")
+public abstract class AbstractSearchServlet extends HttpServlet {
+
+  private static final Log LOG = Log.get(AbstractSearchServlet.class);
+
+  private static String DEFAULT_QUERY = "";
+  private static String DEFAULT_NUMRESULTS = "100";
+
+  protected final ConversationUtil conversationUtil;
+  protected final EventDataConverterManager converterManager;
+  protected final WaveletProvider waveletProvider;
+  protected final SessionManager sessionManager;
+  protected final OperationServiceRegistry operationRegistry;
+
+
+  private static String getParameter(HttpServletRequest req, String paramName, 
String defaultValue) {
+    String param = req.getParameter(paramName);
+    param = param == null ? defaultValue : param;
+    return param;
+  }
+
+  /**
+   * Constructor.
+   */
+  public AbstractSearchServlet(ConversationUtil conversationUtil,
+      EventDataConverterManager converterManager, WaveletProvider 
waveletProvider,
+      SessionManager sessionManager, OperationServiceRegistry 
operationRegistry) {
+    this.conversationUtil = conversationUtil;
+    this.converterManager = converterManager;
+    this.waveletProvider = waveletProvider;
+    this.sessionManager = sessionManager;
+    this.operationRegistry = operationRegistry;
+  }
+
+  /**
+   * Extracts search query params from request.
+   *
+   * @param req the request.
+   * @param response the response.
+   * @return the SearchRequest with query data.
+   */
+  public static SearchRequest parseSearchRequest(HttpServletRequest req,
+      HttpServletResponse response) {
+
+    String query = getParameter(req, "query", DEFAULT_QUERY);
+    String index = getParameter(req, "index", "0");
+    String numResults = getParameter(req, "numResults", DEFAULT_NUMRESULTS);
+    SearchRequest searchRequest =
+        
SearchRequest.newBuilder().setQuery(query).setIndex(Integer.parseInt(index))
+            .setNumResults(Integer.parseInt(numResults)).build();
+    return searchRequest;
+  }
+
+  /**
+   * Performs search using Data API.
+   */
+  protected SearchResult performSearch(SearchRequest searchRequest, 
ParticipantId user) {
+    OperationQueue opQueue = new OperationQueue();
+    opQueue.search(searchRequest.getQuery(), searchRequest.getIndex(),
+        searchRequest.getNumResults());
+    OperationContextImpl context =
+        new OperationContextImpl(waveletProvider,
+            converterManager.getEventDataConverter(ProtocolVersion.DEFAULT), 
conversationUtil);
+    LOG.fine(
+        "Performing query: " + searchRequest.getQuery() + " [" + 
searchRequest.getIndex() + ", "
+            + (searchRequest.getIndex() + searchRequest.getNumResults()) + 
"]");
+    OperationRequest operationRequest = opQueue.getPendingOperations().get(0);
+    String opId = operationRequest.getId();
+    OperationUtil.executeOperation(operationRequest, operationRegistry, 
context, user);
+    JsonRpcResponse jsonRpcResponse = context.getResponses().get(opId);
+    SearchResult searchResult =
+        (SearchResult) 
jsonRpcResponse.getData().get(ParamsProperty.SEARCH_RESULTS);
+    return searchResult;
+  }
+}

Added: 
incubator/wave/trunk/src/org/waveprotocol/box/server/rpc/NotificationServlet.java
URL: 
http://svn.apache.org/viewvc/incubator/wave/trunk/src/org/waveprotocol/box/server/rpc/NotificationServlet.java?rev=1328731&view=auto
==============================================================================
--- 
incubator/wave/trunk/src/org/waveprotocol/box/server/rpc/NotificationServlet.java
 (added)
+++ 
incubator/wave/trunk/src/org/waveprotocol/box/server/rpc/NotificationServlet.java
 Sat Apr 21 20:10:04 2012
@@ -0,0 +1,89 @@
+/**
+ * Copyright 2012 Apache Wave.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.waveprotocol.box.server.rpc;
+
+import com.google.common.annotations.VisibleForTesting;
+import com.google.gson.Gson;
+import com.google.inject.Inject;
+import com.google.inject.Singleton;
+import com.google.inject.name.Named;
+import com.google.wave.api.SearchResult;
+import com.google.wave.api.SearchResult.Digest;
+import com.google.wave.api.data.converter.EventDataConverterManager;
+
+import org.waveprotocol.box.search.SearchProto.SearchRequest;
+import org.waveprotocol.box.server.authentication.SessionManager;
+import org.waveprotocol.box.server.robots.OperationServiceRegistry;
+import org.waveprotocol.box.server.robots.util.ConversationUtil;
+import org.waveprotocol.box.server.waveserver.WaveletProvider;
+import org.waveprotocol.wave.model.wave.ParticipantId;
+
+import java.io.IOException;
+import java.util.List;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+/**
+ * Provides search result digests in JSON format.
+ *
+ * @author [email protected] (Yuri Z.)
+ */
+@SuppressWarnings("serial")
+@Singleton
+public final class NotificationServlet extends AbstractSearchServlet {
+
+  private static final Gson GSON = new Gson();
+
+  @Inject
+  public NotificationServlet(SessionManager sessionManager,
+      EventDataConverterManager converterManager,
+      @Named("DataApiRegistry") OperationServiceRegistry operationRegistry,
+      WaveletProvider waveletProvider, ConversationUtil conversationUtil, 
ProtoSerializer serializer) {
+    super(conversationUtil, converterManager, waveletProvider, sessionManager, 
operationRegistry);
+  }
+
+  /**
+   * Creates HTTP response to the search query. Main entrypoint for this class.
+   */
+  @Override
+  @VisibleForTesting
+  protected void doGet(HttpServletRequest req, HttpServletResponse response) 
throws IOException {
+    ParticipantId user = sessionManager.getLoggedInUser(req.getSession(false));
+    if (user == null) {
+      response.setStatus(HttpServletResponse.SC_FORBIDDEN);
+      return;
+    }
+    SearchRequest searchRequest = parseSearchRequest(req, response);
+    SearchResult searchResult = performSearch(searchRequest, user);
+    serializeObjectToServlet(searchResult.getDigests(), response);
+  }
+
+  /**
+   * Writes the json with search results to Response.
+   */
+  private void serializeObjectToServlet(List<Digest> digests, 
HttpServletResponse resp)
+      throws IOException {
+    resp.setStatus(HttpServletResponse.SC_OK);
+    resp.setContentType("text/html; charset=utf8");
+    // This is to make sure the fetched data is fresh - since the w3c spec
+    // is rarely respected.
+    resp.setHeader("Cache-Control", "no-store");
+    resp.getWriter().append(GSON.toJson(digests));
+  }
+}

Modified: 
incubator/wave/trunk/src/org/waveprotocol/box/server/rpc/SearchServlet.java
URL: 
http://svn.apache.org/viewvc/incubator/wave/trunk/src/org/waveprotocol/box/server/rpc/SearchServlet.java?rev=1328731&r1=1328730&r2=1328731&view=diff
==============================================================================
--- incubator/wave/trunk/src/org/waveprotocol/box/server/rpc/SearchServlet.java 
(original)
+++ incubator/wave/trunk/src/org/waveprotocol/box/server/rpc/SearchServlet.java 
Sat Apr 21 20:10:04 2012
@@ -22,11 +22,6 @@ import com.google.inject.Inject;
 import com.google.inject.Singleton;
 import com.google.inject.name.Named;
 import com.google.protobuf.MessageLite;
-import com.google.wave.api.JsonRpcConstant.ParamsProperty;
-import com.google.wave.api.JsonRpcResponse;
-import com.google.wave.api.OperationQueue;
-import com.google.wave.api.OperationRequest;
-import com.google.wave.api.ProtocolVersion;
 import com.google.wave.api.SearchResult;
 import com.google.wave.api.SearchResult.Digest;
 import com.google.wave.api.data.converter.EventDataConverterManager;
@@ -35,10 +30,8 @@ import org.waveprotocol.box.search.Searc
 import org.waveprotocol.box.search.SearchProto.SearchResponse;
 import org.waveprotocol.box.search.SearchProto.SearchResponse.Builder;
 import org.waveprotocol.box.server.authentication.SessionManager;
-import org.waveprotocol.box.server.robots.OperationContextImpl;
 import org.waveprotocol.box.server.robots.OperationServiceRegistry;
 import org.waveprotocol.box.server.robots.util.ConversationUtil;
-import org.waveprotocol.box.server.robots.util.OperationUtil;
 import org.waveprotocol.box.server.rpc.ProtoSerializer.SerializationException;
 import org.waveprotocol.box.server.waveserver.WaveletProvider;
 import org.waveprotocol.box.webclient.search.SearchService;
@@ -48,7 +41,6 @@ import org.waveprotocol.wave.util.loggin
 import java.io.IOException;
 import java.util.List;
 
-import javax.servlet.http.HttpServlet;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 
@@ -64,97 +56,64 @@ import javax.servlet.http.HttpServletRes
  */
 @SuppressWarnings("serial")
 @Singleton
-public final class SearchServlet extends HttpServlet {
+public final class SearchServlet extends AbstractSearchServlet {
 
   private static final Log LOG = Log.get(SearchServlet.class);
 
-  public static class SearchResponseUtils {
-
-    /**
-     * Extracts search query params from request.
-     *
-     * @param req the request.
-     * @param response the response.
-     * @return the SearchRequest with query data.
-     */
-    public static SearchRequest parseSearchRequest(HttpServletRequest req,
-        HttpServletResponse response) {
-
-      String query = req.getParameter("query");
-      String index = req.getParameter("index");
-      String numResults = req.getParameter("numResults");
-      SearchRequest searchRequest =
-          
SearchRequest.newBuilder().setQuery(query).setIndex(Integer.parseInt(index))
-              .setNumResults(Integer.parseInt(numResults)).build();
-      return searchRequest;
-    }
+  private final ProtoSerializer serializer;
 
-    /**
-     * Constructs SearchResponse which is a protobuf generated class from the
-     * output of Data API search service. SearchResponse contains the same
-     * information as searchResult.
-     *
-     * @param searchResult the search results with digests.
-     * @return SearchResponse
-     */
-    public static SearchResponse serializeSearchResult(SearchResult 
searchResult, int total) {
-      Builder searchBuilder = SearchResponse.newBuilder();
-      searchBuilder.setQuery(searchResult.getQuery()).setTotalResults(total);
-      for (SearchResult.Digest searchResultDigest : searchResult.getDigests()) 
{
-        SearchResponse.Digest digest = serializeDigest(searchResultDigest);
-        searchBuilder.addDigests(digest);
-      }
-      SearchResponse searchResponse = searchBuilder.build();
-      return searchResponse;
+  /**
+   * Constructs SearchResponse which is a protobuf generated class from the
+   * output of Data API search service. SearchResponse contains the same
+   * information as searchResult.
+   *
+   * @param searchResult the search results with digests.
+   * @return SearchResponse
+   */
+  public static SearchResponse serializeSearchResult(SearchResult 
searchResult, int total) {
+    Builder searchBuilder = SearchResponse.newBuilder();
+    searchBuilder.setQuery(searchResult.getQuery()).setTotalResults(total);
+    for (SearchResult.Digest searchResultDigest : searchResult.getDigests()) {
+      SearchResponse.Digest digest = serializeDigest(searchResultDigest);
+      searchBuilder.addDigests(digest);
     }
+    SearchResponse searchResponse = searchBuilder.build();
+    return searchResponse;
+  }
 
-    /**
-     * Copies data from {@link Digest} into {@link SearchResponse.Digest}.
-     */
-    private static SearchResponse.Digest serializeDigest(Digest 
searchResultDigest) {
-      SearchResponse.Digest.Builder digestBuilder = 
SearchResponse.Digest.newBuilder();
-      digestBuilder.setBlipCount(searchResultDigest.getBlipCount());
-      digestBuilder.setLastModified(searchResultDigest.getLastModified());
-      digestBuilder.setSnippet(searchResultDigest.getSnippet());
-      digestBuilder.setTitle(searchResultDigest.getTitle());
-      digestBuilder.setUnreadCount(searchResultDigest.getUnreadCount());
-      digestBuilder.setWaveId(searchResultDigest.getWaveId());
-      List<String> participants = searchResultDigest.getParticipants();
-      if (participants.isEmpty()) {
-        // This shouldn't be possible.
-        digestBuilder.setAuthor("[email protected]");
-      } else {
-        digestBuilder.setAuthor(participants.get(0));
-        for (int i = 1; i < participants.size(); i++) {
-          digestBuilder.addParticipants(participants.get(i));
-        }
+  /**
+   * Copies data from {@link Digest} into {@link SearchResponse.Digest}.
+   */
+  private static SearchResponse.Digest serializeDigest(Digest 
searchResultDigest) {
+    SearchResponse.Digest.Builder digestBuilder = 
SearchResponse.Digest.newBuilder();
+    digestBuilder.setBlipCount(searchResultDigest.getBlipCount());
+    digestBuilder.setLastModified(searchResultDigest.getLastModified());
+    digestBuilder.setSnippet(searchResultDigest.getSnippet());
+    digestBuilder.setTitle(searchResultDigest.getTitle());
+    digestBuilder.setUnreadCount(searchResultDigest.getUnreadCount());
+    digestBuilder.setWaveId(searchResultDigest.getWaveId());
+    List<String> participants = searchResultDigest.getParticipants();
+    if (participants.isEmpty()) {
+      // This shouldn't be possible.
+      digestBuilder.setAuthor("[email protected]");
+    } else {
+      digestBuilder.setAuthor(participants.get(0));
+      for (int i = 1; i < participants.size(); i++) {
+        digestBuilder.addParticipants(participants.get(i));
       }
-      SearchResponse.Digest digest = digestBuilder.build();
-      return digest;
     }
+    SearchResponse.Digest digest = digestBuilder.build();
+    return digest;
   }
 
-  private final ConversationUtil conversationUtil;
-  private final EventDataConverterManager converterManager;
-  private final WaveletProvider waveletProvider;
-  private final SessionManager sessionManager;
-  private final OperationServiceRegistry operationRegistry;
-  private final ProtoSerializer serializer;
-
-
   @Inject
   public SearchServlet(SessionManager sessionManager, 
EventDataConverterManager converterManager,
       @Named("DataApiRegistry") OperationServiceRegistry operationRegistry,
       WaveletProvider waveletProvider, ConversationUtil conversationUtil, 
ProtoSerializer serializer) {
-    this.converterManager = converterManager;
-    this.waveletProvider = waveletProvider;
-    this.conversationUtil = conversationUtil;
-    this.sessionManager = sessionManager;
-    this.operationRegistry = operationRegistry;
+    super(conversationUtil, converterManager, waveletProvider, sessionManager, 
operationRegistry);
     this.serializer = serializer;
   }
 
-
   /**
    * Creates HTTP response to the search query. Main entrypoint for this class.
    */
@@ -166,31 +125,16 @@ public final class SearchServlet extends
       response.setStatus(HttpServletResponse.SC_FORBIDDEN);
       return;
     }
-    SearchRequest searchRequest = SearchResponseUtils.parseSearchRequest(req, 
response);
-    SearchResponse searchResponse = performSearch(searchRequest, user);
+    SearchRequest searchRequest = parseSearchRequest(req, response);
+    SearchResult searchResult = performSearch(searchRequest, user);
+
+    int totalGuess = computeTotalResultsNumberGuess(searchRequest, 
searchResult);
+    LOG.fine("Results: " + searchResult.getNumResults() + ", total: " + 
totalGuess);
+    SearchResponse searchResponse = serializeSearchResult(searchResult, 
totalGuess);
     serializeObjectToServlet(searchResponse, response);
   }
 
-  /**
-   * Performs search using Data API.
-   */
-  private SearchResponse performSearch(SearchRequest searchRequest, 
ParticipantId user) {
-    OperationQueue opQueue = new OperationQueue();
-    opQueue.search(searchRequest.getQuery(), searchRequest.getIndex(),
-        searchRequest.getNumResults());
-    OperationContextImpl context =
-        new OperationContextImpl(waveletProvider,
-            converterManager.getEventDataConverter(ProtocolVersion.DEFAULT), 
conversationUtil);
-    LOG.fine(
-        "Performing query: " + searchRequest.getQuery() + " [" + 
searchRequest.getIndex() + ", "
-            + (searchRequest.getIndex() + searchRequest.getNumResults()) + 
"]");
-    OperationRequest operationRequest = opQueue.getPendingOperations().get(0);
-    String opId = operationRequest.getId();
-    OperationUtil.executeOperation(operationRequest, operationRegistry, 
context, user);
-    JsonRpcResponse jsonRpcResponse = context.getResponses().get(opId);
-    SearchResult searchResult =
-        (SearchResult) 
jsonRpcResponse.getData().get(ParamsProperty.SEARCH_RESULTS);
-
+  private int computeTotalResultsNumberGuess(SearchRequest searchRequest, 
SearchResult searchResult) {
     // The Data API does not return the total size of the search result, even
     // though the searcher knows it. The only approximate knowledge that can be
     // gleaned from the Data API is whether there are more search results 
beyond
@@ -203,8 +147,7 @@ public final class SearchServlet extends
     } else {
       totalGuess = searchRequest.getIndex() + searchResult.getNumResults();
     }
-    LOG.fine("Results: " + searchResult.getNumResults() + ", total: " + 
totalGuess);
-    return SearchResponseUtils.serializeSearchResult(searchResult, totalGuess);
+    return totalGuess;
   }
 
   /**
@@ -227,4 +170,4 @@ public final class SearchServlet extends
       }
     }
   }
-}
+}
\ No newline at end of file


Reply via email to