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