/*
* RHQ Management Platform
* Copyright (C) 2005-2008 Red Hat, Inc.
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation version 2 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
package org.rhq.enterprise.gui.legacy.action.resource.common.events;
import java.util.StringTokenizer;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.util.MessageResources;
import org.rhq.core.clientapi.util.TimeUtil;
import org.rhq.core.domain.auth.Subject;
import org.rhq.core.domain.common.EntityContext;
import org.rhq.core.domain.event.EventSeverity;
import org.rhq.core.domain.event.composite.EventComposite;
import org.rhq.core.domain.util.PageControl;
import org.rhq.core.domain.util.PageList;
import org.rhq.core.util.StringUtil;
import org.rhq.enterprise.gui.legacy.AttrConstants;
import org.rhq.enterprise.gui.legacy.DefaultConstants;
import org.rhq.enterprise.gui.legacy.ParamConstants;
import org.rhq.enterprise.gui.legacy.RetCodeConstants;
import org.rhq.enterprise.gui.legacy.StringConstants;
import org.rhq.enterprise.gui.legacy.WebUser;
import org.rhq.enterprise.gui.legacy.action.BaseAction;
import org.rhq.enterprise.gui.legacy.util.SessionUtils;
import org.rhq.enterprise.gui.util.WebUtility;
import org.rhq.enterprise.server.event.EventManagerLocal;
import org.rhq.enterprise.server.measurement.MeasurementPreferences;
import org.rhq.enterprise.server.measurement.MeasurementPreferences.MetricRangePreferences;
import org.rhq.enterprise.server.util.LookupUtil;
/**
* Set an array for the timeline display in EventLogs.jsp, showEventDetails().
* The JavaScript function showEventDetails() is actually defined in Indicators.jsp
*
* @author Heiko W. Rupp
*/
public class EventDetailsAction extends BaseAction {
/** How many chars of a detail do we show at most */
private static final int DETAIL_MAX_LEN = 100;
/** How many events do we show at most per dot */
private static final int MAX_EVENTS_PER_DOT = 30;
Log log = LogFactory.getLog(EventDetailsAction.class);
@Override
public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request,
HttpServletResponse response) throws Exception {
try {
WebUser user = SessionUtils.getWebUser(request.getSession());
MeasurementPreferences preferences = user.getMeasurementPreferences();
MetricRangePreferences rangePreferences = preferences.getMetricRangePreferences();
long begin = rangePreferences.begin;
long end = rangePreferences.end;
long interval = TimeUtil.getInterval(begin, end, DefaultConstants.DEFAULT_CHART_POINTS);
begin = Long.parseLong(WebUtility.getOptionalRequestParameter(request, "begin", "0"));
int resourceId = WebUtility.getOptionalIntRequestParameter(request, ParamConstants.RESOURCE_ID_PARAM, -1);
int groupId = WebUtility.getOptionalIntRequestParameter(request, ParamConstants.GROUP_ID_PARAM, -1);
int parent = WebUtility.getOptionalIntRequestParameter(request, "parent", -1);
int type = WebUtility.getOptionalIntRequestParameter(request, "type", -1);
String mode = WebUtility.getOptionalRequestParameter(request, "mode", "normal");
EventManagerLocal eventManager = LookupUtil.getEventManager();
Subject subject = user.getSubject();
EntityContext context = new EntityContext(resourceId, groupId, parent, type);
PageList<EventComposite> events = eventManager.findEventComposites(subject, context, begin, begin
+ interval, null, null, null, new PageControl(0, MAX_EVENTS_PER_DOT));
MessageResources res = getResources(request);
StringBuffer html;
if (events.isEmpty()) {
html = new StringBuffer(res.getMessage("resource.common.monitor.text.events.None"));
} else {
html = new StringBuffer("<ul class=\"boxy\">");
for (EventComposite event : events) {
html.append("<li> ");
EventSeverity severity = event.getSeverity();
switch (severity) {
case FATAL:
html.append("<img src=\"/images/event_fatal.gif\"/>");
break;
case ERROR:
html.append("<img src=\"/images/event_error.gif\"/>");
break;
case WARN:
html.append("<img src=\"/images/event_warn.gif\"/>");
break;
case INFO:
html.append("<img src=\"/images/event_info.gif\"/>");
break;
case DEBUG:
html.append("<img src=\"/images/event_debug.gif\"/>");
break;
}
html.append(" ");
createLinkForResource(mode, resourceId, groupId, parent, type, html, event, ridBadChars(event
.getEventDetail()));
html.append("</li>");
}
html.append("</ul>");
if (events.getTotalSize() > MAX_EVENTS_PER_DOT) {
EventComposite event = events.get(events.size() - 1); // take the last one to initialize the list
html.append("<p/>");
createLinkForResource(mode, resourceId, groupId, parent, type, html, event, res
.getMessage("resource.common.monitor.text.events.MoreEvents"));
html.append("<p/>");
}
}
request.setAttribute(AttrConstants.AJAX_TYPE, StringConstants.AJAX_ELEMENT);
request.setAttribute(AttrConstants.AJAX_ID, "eventsSummary");
request.setAttribute(AttrConstants.AJAX_HTML, html);
} catch (Exception e) {
log.error("Error getting AJAX-style event details", e);
}
return mapping.findForward(RetCodeConstants.SUCCESS_URL);
}
private void createLinkForResource(String mode, int resourceId, int groupId, int parent, int type,
StringBuffer html, EventComposite event, String text) {
log.info("mode = " + mode);
if (mode.equals("plain")) {
String context = (resourceId > -1) ? "Resource/" : "ResourceGroup/";
int contextId = (resourceId > -1) ? resourceId : groupId;
html.append("<a target=\"_top\" href=\"/coregui/CoreGUI.html#").append(context).append(contextId);
html.append("/Events/History/").append(event.getEventId()).append("\">");
html.append(text);
html.append("</a> ");
} else {
//html.append("<a href=\"/resource/common/Events.do?mode=events&eventId=");
html.append("<a href=\"/rhq/resource/events/history.xhtml?eventId=");
html.append(event.getEventId());
if (resourceId > -1) {
html.append("&id=").append(event.getResourceId());
} else if (groupId > -1) {
html.append("&groupId=").append(groupId);
} else {
html.append("&parent=").append(parent).append("&type=").append(type);
}
html.append("\">");
//html.append(event.getEventId());
if (text.contains("\n")) {
text = text.substring(0, text.indexOf("\n"));
}
if (text.length() > DETAIL_MAX_LEN) {
text = text.substring(0, DETAIL_MAX_LEN - 1);
}
html.append(text);
html.append("</a>");
html.append(" ");
}
}
// In our Javascript, we are enclosing the whole string in single-quotes.
// However, just escaping it does not seem to work because we are setting
// the innerHTML. So, just to be safe, we're getting rid of all single
// quotes, double quotes, whitespace characters, and carat
private String ridBadChars(String source) {
int sourceLen = source.length();
if (sourceLen == 0) {
return source;
}
StringTokenizer st = new StringTokenizer(source);
StringBuffer buffer = new StringBuffer();
while (st.hasMoreElements()) {
String tok = st.nextToken();
tok = tok.replaceAll("['\"]", " ");
if (tok.indexOf('<') > -1) {
tok = StringUtil.replace(tok, "<", "<");
}
buffer.append(tok).append(" ");
}
return buffer.toString();
}
}