/** * Copyright 2012 Comcast Corporation * * 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 com.comcast.cqs.controller; import java.io.IOException; import java.io.PrintWriter; import java.util.ArrayList; import java.util.Arrays; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.log4j.Logger; import org.w3c.dom.Element; import com.amazonaws.auth.AWSCredentials; import com.amazonaws.auth.BasicAWSCredentials; import com.amazonaws.services.sqs.model.DeleteMessageRequest; import com.amazonaws.services.sqs.model.GetQueueAttributesRequest; import com.amazonaws.services.sqs.model.GetQueueAttributesResult; import com.amazonaws.services.sqs.model.Message; import com.amazonaws.services.sqs.model.ReceiveMessageRequest; import com.amazonaws.services.sqs.model.ReceiveMessageResult; import com.amazonaws.services.sqs.model.SendMessageRequest; import com.comcast.cmb.common.controller.AdminServletBase; import com.comcast.cmb.common.controller.CMBControllerServlet; import com.comcast.cmb.common.util.XmlUtil; import com.comcast.cqs.model.CQSMessage; import com.comcast.cqs.model.CQSMessageAttribute; import com.comcast.cqs.util.Util; /** * Admin page for showing messages in a queue * @author aseem, vvenkatraman, bwolf, baosen * */ public class CQSQueueMessagesPageServlet extends AdminServletBase { private static final long serialVersionUID = 1L; private static Logger logger = Logger.getLogger(CQSQueueMessagesPageServlet.class); public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { if (redirectUnauthenticatedUser(request, response)) { return; } CMBControllerServlet.valueAccumulator.initializeAllCounters(); response.setContentType("text/html"); PrintWriter out = response.getWriter(); String userId = request.getParameter("userId"); String queueName = request.getParameter("queueName"); String msgStr = request.getParameter("message"); String prevHandle = request.getParameter("prevHandle"); String nextHandle = request.getParameter("nextHandle"); String receiptHandle = request.getParameter("receiptHandle"); Map<?, ?> parameters = request.getParameterMap(); Message receivedMessage=null; int shard = 0; if (request.getParameter("shard") != null) { shard = Integer.parseInt(request.getParameter("shard")); } String queueUrl = Util.getAbsoluteQueueUrlForName(queueName, userId); connect(request); if (parameters.containsKey("Send")) { try { SendMessageRequest sendMessageRequest = new SendMessageRequest(queueUrl, msgStr); sqs.sendMessage(sendMessageRequest); logger.debug("event=send_message queue_url= " + queueUrl + " user_id=" + userId); } catch (Exception ex) { logger.error("event=send_message queue_url= " + queueUrl + " user_id=" + userId, ex); throw new ServletException(ex); } } else if (parameters.containsKey("Delete")) { try { DeleteMessageRequest deleteMessageRequest = new DeleteMessageRequest(queueUrl, receiptHandle); sqs.deleteMessage(deleteMessageRequest); logger.debug("event=delete_message queue_url= " + queueUrl + " receipt_handle=" + receiptHandle); } catch (Exception ex) { logger.error("event=delete_message queue_url= " + queueUrl + " receipt_handle=" + receiptHandle, ex); throw new ServletException(ex); } } else if (parameters.containsKey("Receive")) { try { ReceiveMessageRequest receiveMessageRequest = new ReceiveMessageRequest(queueUrl); receiveMessageRequest.setMessageAttributeNames(new ArrayList<String>(Arrays.asList("All"))); ReceiveMessageResult result = sqs.receiveMessage(receiveMessageRequest); logger.debug("event=receive_message queue_url= " + queueUrl + " user_id=" + userId); List<Message> receivedMessages=null; if (result!=null){ receivedMessages=result.getMessages(); if(receivedMessages!=null&&receivedMessages.size()>0){ receivedMessage=receivedMessages.get(0); } } } catch (Exception ex) { logger.error("event=receive_message queue_url= " + queueUrl + " user_id=" + userId, ex); throw new ServletException(ex); } } int numberOfShards = 1; try { GetQueueAttributesRequest getQueueAttributesRequest = new GetQueueAttributesRequest(queueUrl); getQueueAttributesRequest.setAttributeNames(Arrays.asList("NumberOfShards")); GetQueueAttributesResult getQueueAttributesResult = sqs.getQueueAttributes(getQueueAttributesRequest); Map<String, String> attributes = getQueueAttributesResult.getAttributes(); numberOfShards = Integer.parseInt(attributes.get("NumberOfShards")); } catch (Exception ex) { logger.error("event=get_queue_attributes url=" + queueUrl); } out.println("<html>"); out.println("<script type='text/javascript' language='javascript'>"); out.println("function setVisibility(id, buttonid) {"); out.println("if(document.getElementById(buttonid).value=='Less'){"); out.println("document.getElementById(buttonid).value = 'More';"); out.println("document.getElementById(id).style.display = 'none';"); out.println("}else{"); out.println("document.getElementById(buttonid).value = 'Less';"); out.println("document.getElementById(id).style.display = 'inline';"); out.println("}"); out.println("}"); out.println("</script>"); header(request, out, "Peek Messages for Queue " + queueName); out.println("<body>"); out.println("<h2>Peek Messages for Queue " + queueName + "</h2>"); if (user != null) { out.println("<table><tr><td><b>User Name:</b></td><td>"+ user.getUserName()+"</td></tr>"); out.println("<tr><td><b>User ID:</b></td><td>"+ user.getUserId()+"</td></tr>"); out.println("<tr><td><b>Access Key:</b></td><td>"+user.getAccessKey()+"</td></tr>"); out.println("<tr><td><b>Access Secret:</b></td><td>"+user.getAccessSecret()+"</td></tr>"); out.println("<tr><td><b>Queue Name:</b></td><td>"+queueName+"</td></tr></table>"); } out.println("<p><table><tr><td><b>Send message:</b></td><td></td></tr>"); out.println("<form id='frm1' action=\"/webui/cqsuser/message/?userId="+userId+"&queueName="+queueName+"\" method=POST>"); out.println("<tr><td><textarea rows='3' cols='50' name='message'></textarea><input type='hidden' name='userId' value='"+ userId + "'></td><td valign='bottom'><input type='submit' value='Send' name='Send' /></td></tr></form>"); out.println("<tr><td> </td></tr>"); if (numberOfShards > 1) { out.println("<form id='frm2' action=\"/webui/cqsuser/message/?userId="+userId+"&queueName="+queueName+"\" method=POST>"); out.println("<tr><td>Shard: <select name='shard' onChange='document.getElementById(\"frm2\").submit();'>"); for (int i=0; i<numberOfShards; i++) { out.print("<option value='" + i + "'"); if (shard == i) { out.print(" selected"); } out.println(">" + i + "</option>"); } out.println("</form></select></td></tr></table></p>"); } else { out.println("</table></p>"); } // for receive message out.println("<form id='formsendmessage' action=\"/webui/cqsuser/message/?userId="+userId+"&queueName="+queueName+"\" method=POST>"); out.println("<table><tr><td><b>Receive Message:</b></td>"); out.println("<td><input type='hidden' name='userId' value='"+ userId + "'></td><td valign='bottom'><input type='submit' value='Receive Message' name='Receive' /></td>"); out.println("</form></tr></table>"); // showing received message out.println("<p><hr width='100%' align='left' /><p>"); out.println("<h3>Received Messages</h3>"); if (receivedMessage!=null) { Map<String, String> attributes = receivedMessage.getAttributes(); String timeSent = ""; if (attributes.get("SentTimestamp") != null) { try { timeSent = new Date(Long.parseLong(attributes.get("SentTimestamp"))).toString(); } catch (Exception ex) {} } String timeReceived = ""; if (attributes.get("ApproximateFirstReceiveTimestamp") != null) { try { timeReceived = new Date(Long.parseLong(attributes.get("ApproximateFirstReceiveTimestamp"))).toString(); } catch (Exception ex) {} } out.println("<table class = 'alternatecolortable'>"); out.println("<tr><th></th><th>Receipt Handle</th><th>MD5</th><th>Body</th><th>Num Msg Attributes</th><th>Time Sent</th><th>Time First Received (Appr.)</th><th>Receive Count (Appr.)</th><th>Sender</th><th> </th></tr>"); out.println("<tr>"); out.println("<td>0</td>"); out.println("<td>" + receivedMessage.getReceiptHandle() + "</td>"); out.println("<td>" + receivedMessage.getMD5OfBody() + "</td>"); String messageBody=receivedMessage.getBody(); String messageBodyPart1=null; String messageBodyPart2=null; if ((messageBody!=null) && (messageBody.length()>300)) { messageBodyPart1=messageBody.substring(0, 299); messageBodyPart2=messageBody.substring(299); out.println("<td>"); out.println(messageBodyPart1); out.println("<div id='rdetail' style=\"display: none;\">"+messageBodyPart2+"</div>"); out.println("<input type=button name=type id='rbt' value='More' onclick=\"setVisibility('rdetail', 'rbt');\";> "); out.println("</td>"); } else { out.println("<td>"+ receivedMessage.getBody() + "</td>"); } out.println("<td>"+ receivedMessage.getMessageAttributes().size() + "</td>"); out.println("<td>"+ timeSent + "</td>"); out.println("<td>"+ timeReceived + "</td>"); out.println("<td>"+ attributes.get("ApproximateReceiveCount") + "</td>"); out.println("<td>"+ attributes.get("SenderId") + "</td>"); out.println("<td><form action=\"/webui/cqsuser/message/?userId="+user.getUserId()+"&queueName="+queueName+"&receiptHandle="+receivedMessage.getReceiptHandle()+"\" method=POST><input type='submit' value='Delete' name='Delete'/><input type='hidden' name='queueUrl' value='"+ queueUrl+ "' /></form></td></tr>"); out.println("</table>"); } else { out.println("<p><i>no messages</i></p>"); } List<CQSMessage> availableMessages = null; String queueFirstMessageHandle = null; try { if (queueUrl != null) { String peekRequestUrl = cqsServiceBaseUrl + user.getUserId() + "/" + queueName + "?Action=PeekMessage&AWSAccessKeyId=" + user.getAccessKey() + "&MaxNumberOfMessages=10&Shard=" + shard + "&MessageAttributeName.1=All"; if (prevHandle != null) { peekRequestUrl += "&PreviousReceiptHandle=" + prevHandle; } else if (nextHandle != null) { peekRequestUrl += "&NextReceiptHandle=" + nextHandle; } AWSCredentials awsCredentials=new BasicAWSCredentials(user.getAccessKey(),user.getAccessSecret()); String peekXml = httpPOST(cqsServiceBaseUrl, peekRequestUrl,awsCredentials); Element root = XmlUtil.buildDoc(peekXml); List<Element> messageElements = XmlUtil.getCurrentLevelChildNodes(XmlUtil.getCurrentLevelChildNodes(root, "ReceiveMessageResult").get(0), "Message"); for (Element messageElement : messageElements) { if (availableMessages == null) { availableMessages = new ArrayList<CQSMessage>(); } String body = XmlUtil.getCurrentLevelTextValue(messageElement, "Body"); String id = XmlUtil.getCurrentLevelTextValue(messageElement, "MessageId").trim(); String handle = XmlUtil.getCurrentLevelTextValue(messageElement, "ReceiptHandle").trim(); CQSMessage msg = new CQSMessage(id, body); msg.setReceiptHandle(handle); List<Element> attributeElements = XmlUtil.getCurrentLevelChildNodes(messageElement, "Attribute"); Map<String, String> attributes = new HashMap<String, String>(); for (Element attribute : attributeElements) { String name = XmlUtil.getCurrentLevelTextValue(attribute, "Name"); String value = XmlUtil.getCurrentLevelTextValue(attribute, "Value"); if (name != null && value != null) { attributes.put(name, value); } } msg.setAttributes(attributes); List<Element> messageAttributeElements = XmlUtil.getCurrentLevelChildNodes(messageElement, "MessageAttribute"); Map<String, CQSMessageAttribute> messageAttributes = new HashMap<String, CQSMessageAttribute>(); for (Element attribute : messageAttributeElements) { String name = XmlUtil.getCurrentLevelTextValue(attribute, "Name"); messageAttributes.put(name, new CQSMessageAttribute(name, name)); } msg.setMessageAttributes(messageAttributes); availableMessages.add(msg); } //retrieve first messageId from queue. this is for pagination String peekRequestFirstMessageUrl = cqsServiceBaseUrl + user.getUserId() + "/" + queueName + "?Action=PeekMessage&AWSAccessKeyId=" + user.getAccessKey() + "&MaxNumberOfMessages=1&Shard=" + shard; String peekFirstMessageXml = httpPOST(cqsServiceBaseUrl, peekRequestFirstMessageUrl,awsCredentials); Element rootFirstMessage = XmlUtil.buildDoc(peekFirstMessageXml); List<Element> messageElementsForFirstMessage = XmlUtil.getCurrentLevelChildNodes(XmlUtil.getCurrentLevelChildNodes(rootFirstMessage, "ReceiveMessageResult").get(0), "Message"); if (messageElementsForFirstMessage.size() == 1){ queueFirstMessageHandle = XmlUtil.getCurrentLevelTextValue(messageElementsForFirstMessage.get(0), "ReceiptHandle").trim(); } } } catch (Exception ex) { logger.error("event=peek_message queue_url=" + queueUrl, ex); throw new ServletException(ex); } String previousHandle = null; nextHandle = null; out.println("<p><hr width='100%' align='left' /><p>"); out.println("<h3>Available Messages</h3>"); if ((availableMessages==null) || (availableMessages.size()==0)) { out.println("<p><i>no messages</i></p>"); } for (int i = 0; availableMessages != null && i < availableMessages.size(); i++) { CQSMessage message = availableMessages.get(i); Map<String, String> attributes = message.getAttributes(); String timeSent = ""; if (attributes.get("SentTimestamp") != null) { try { timeSent = new Date(Long.parseLong(attributes.get("SentTimestamp"))).toString(); } catch (Exception ex) {} } String timeReceived = ""; if (attributes.get("ApproximateFirstReceiveTimestamp") != null) { try { timeReceived = new Date(Long.parseLong(attributes.get("ApproximateFirstReceiveTimestamp"))).toString(); } catch (Exception ex) {} } if (i == 0) { out.println("<table class = 'alternatecolortable'>"); out.println("<tr><th></th><th>Receipt Handle</th><th>MD5</th><th>Body</th><th>Num Msg Attributes</th><th>Time Sent</th><th>Time First Received (Appr.)</th><th>Receive Count (Appr.)</th><th>Sender</th><th> </th></tr>"); previousHandle = message.getReceiptHandle(); } out.println("<tr>"); out.println("<td>" + i + "</td>"); out.println("<td>" + message.getReceiptHandle() + "</td>"); out.println("<td>" + message.getMD5OfBody() + "</td>"); String messageBody=message.getBody(); String messageBodyPart1=null; String messageBodyPart2=null; if ((messageBody!=null) && (messageBody.length()>300)) { messageBodyPart1=messageBody.substring(0, 299); messageBodyPart2=messageBody.substring(299); out.println("<td>"); out.println(messageBodyPart1); out.println("<div id='detail"+i+"' style=\"display: none;\">"+messageBodyPart2+"</div>"); out.println("<input type=button name=type id='bt"+i+"' value='More' onclick=\"setVisibility('detail"+ i+"', 'bt"+i+"');\";> "); out.println("</td>"); } else { out.println("<td>"+ message.getBody() + "</td>"); } out.println("<td>"+ (message.getMessageAttributes() == null ? 0 : message.getMessageAttributes().size()) + "</td>"); out.println("<td>"+ timeSent + "</td>"); out.println("<td>"+ timeReceived + "</td>"); out.println("<td>"+ attributes.get("ApproximateReceiveCount") + "</td>"); out.println("<td>"+ attributes.get("SenderId") + "</td>"); out.println("<td></td></tr>"); if (i == availableMessages.size() - 1) { nextHandle = message.getReceiptHandle(); } } out.println("</table>"); //This case is for click on "Next" button of the previous page if (prevHandle != null) { if ((previousHandle) != null) { out.println("<a style='float:left;' href='/webui/cqsuser/message/?userId="+user.getUserId()+"&queueName="+queueName+"&nextHandle="+previousHandle+"'>Prev</a>"); } else { out.println("<a style='float:left;' href='javascript:history.back()'>Prev</a>"); } } else if ( (previousHandle != null) && (!previousHandle.equals(queueFirstMessageHandle))){ //this is for all other cases out.println("<a style='float:left;' href='/webui/cqsuser/message/?userId="+user.getUserId()+"&queueName="+queueName+"&nextHandle="+previousHandle+"'>Prev</a>"); } if (availableMessages != null && availableMessages.size() > 0) { out.println("<a style='float:right;' href='/webui/cqsuser/message/?userId="+user.getUserId()+"&queueName="+queueName+"&prevHandle="+nextHandle+"'>Next</a>"); } out.println("<h5 style='text-align:center;'><a href='/webui'>ADMIN HOME</a>"); out.println("<a href='/webui/cqsuser?userId="+userId+"'>BACK TO QUEUE</a></h5>"); out.println("</body></html>"); CMBControllerServlet.valueAccumulator.deleteAllCounters(); } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }