package jetbrains.buildServer.serverSide; import jetbrains.buildServer.controllers.BaseController; import jetbrains.buildServer.serverSide.auth.SecurityContext; import jetbrains.buildServer.users.User; import jetbrains.buildServer.web.openapi.PluginDescriptor; import jetbrains.buildServer.web.openapi.WebControllerManager; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.json.JSONException; import org.json.JSONWriter; import org.springframework.web.servlet.ModelAndView; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.PrintWriter; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; /** * @author Eugene Petrenko * Created: 31.03.2010 12:38:12 */ public class PluginsChatController extends BaseController { private final SecurityContext mySecutiry; private final ChatModel myModel; private final ConcurrentMap myFromOffsetMap = new ConcurrentHashMap(); public PluginsChatController(@NotNull WebControllerManager wcm, SecurityContext secutiry, PluginDescriptor descr, ChatModel model) { mySecutiry = secutiry; myModel = model; wcm.registerController(descr.getPluginResourcesPath("chatty-batty.html"), this); } @Override protected ModelAndView doHandle(HttpServletRequest request, HttpServletResponse response) throws Exception { prepartResponse(response); final String action = request.getParameter("act"); final boolean hasAll = "true".equalsIgnoreCase(request.getParameter("adminMode")); if ("list".equals(action)) { int offset = getOffset(request); if (!hasAll) { return sendCurrentMessages(request, response, offset); } else { final ChatMessagesCollection chatMessages = myModel.getAllMessages(offset); rememberLastId(request, chatMessages); return writeJSONResponce(response, chatMessages); } } if ("start".equals(action)) { final ChatMessagesCollection obj = myModel.initializeChat(getUser(request)); rememberLastId(request, obj); return writeJSONResponce(response, obj); } if ("close".equals(action)) { myFromOffsetMap.remove(getClientHash(request)); return writeJSONResponce(response, TEAMCITY_RULEZ); } if ("say".equals(action)) { return postMessage(request, response); } return writeJSONResponce(response, UNKNOWN_OBJECT_ERROR); } private ModelAndView postMessage(HttpServletRequest request, HttpServletResponse response) throws IOException, JSONException { String message = jetbrains.buildServer.util.StringUtil.truncateStringValueWithDotsAtEnd(request.getParameter("message"), 300); User user = getUser(request); final ChatMessagesCollection post = myModel.postMessage(user, message, getOffset(request)); rememberLastId(request, post); return writeJSONResponce(response, post); } private void rememberLastId(HttpServletRequest request, ChatMessagesCollection post) { myFromOffsetMap.put(getClientHash(request), post.getLastMessageId()); } private ModelAndView sendCurrentMessages(HttpServletRequest request, HttpServletResponse response, int offset) throws IOException, JSONException { final User user = getUser(request); final ChatMessagesCollection chatMessages = myModel.getMessagesToUser(user, offset); rememberLastId(request, chatMessages); return writeJSONResponce(response, chatMessages); } private ModelAndView writeJSONResponce(HttpServletResponse responce, JSONAble obj) throws IOException, JSONException { final PrintWriter writer = responce.getWriter(); JSONWriter w = new JSONWriter(writer); obj.writeJSON(w); writer.flush(); writer.close(); return null; } private void prepartResponse(HttpServletResponse responce) { responce.setContentType("text/x-json"); responce.setCharacterEncoding("utf-8"); responce.setDateHeader("Expires", 1270042079742L); responce.setDateHeader("Last-Modified", 1270042089742L); } /////////////////////////////////////////////////////////////////////////////// @Nullable private User getUser(HttpServletRequest request) { return request.getParameter("all-users") != null ? null : mySecutiry.getAuthorityHolder().getAssociatedUser(); } @NotNull private String getClientHash(HttpServletRequest request) { final User user = getUser(request); return "2" + (user == null ? "" : user.getUsername()) + "#" + String.valueOf(request.getParameter("id")) + "#" + String.valueOf(request.getParameter("all")); } private int getOffset(HttpServletRequest request) { final Integer id = myFromOffsetMap.get(getClientHash(request)); if (id != null) { return id; } int offset; try { offset = Integer.parseInt(request.getParameter("from")); } catch (Exception e) { offset = 0; } return offset; } private final JSONAble TEAMCITY_RULEZ = new JSONAble() { public void writeJSON(JSONWriter w) throws JSONException { w.object().key("teamcity").value("rulezzz!").endObject(); } }; private final JSONAble UNKNOWN_OBJECT_ERROR = new JSONAble() { public void writeJSON(JSONWriter w) throws JSONException { w.object().key("error").value("Unknown action").endObject(); } }; }