/*******************************************************************************
* This file is part of OpenNMS(R).
*
* Copyright (C) 2006-2011 The OpenNMS Group, Inc.
* OpenNMS(R) is Copyright (C) 1999-2011 The OpenNMS Group, Inc.
*
* OpenNMS(R) is a registered trademark of The OpenNMS Group, Inc.
*
* OpenNMS(R) 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, either version 3 of the License,
* or (at your option) any later version.
*
* OpenNMS(R) 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 OpenNMS(R). If not, see:
* http://www.gnu.org/licenses/
*
* For more information contact:
* OpenNMS(R) Licensing <license@opennms.org>
* http://www.opennms.org/
* http://www.opennms.com/
*******************************************************************************/
package org.opennms.web.controller;
import java.io.InputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.jrobin.core.RrdException;
import org.jrobin.core.timespec.TimeParser;
import org.jrobin.core.timespec.TimeSpec;
import org.opennms.core.utils.StreamUtils;
import org.opennms.web.servlet.MissingParameterException;
import org.opennms.web.svclayer.RrdGraphService;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.AbstractController;
/**
* <p>RrdGraphController class.</p>
*
* Is the front end handler of graph requests.
*
* Accepts start/end parameters that conform to the "specification" used by rrdfetch,
* as defined in it's manpage, or at http://oss.oetiker.ch/rrdtool/doc/rrdfetch.en.html
*
* Or at least, it should. If it doesn't, write a test and fix the code.
*
* NB; If the start/end are integers, they'll be interpreted as an epoch based timestamp
* This precludes some of the more compact forms available to rrdtool (e.g. just specifying
* an hour of the day without am/pm designator. But there are ways and means of working
* around that (specifying the time with hh:mm where mm is 00, or using am/pm; either will
* not parse as integers, resulting in evaluation by the rrdtool-alike parser.
* @author ranger
* @version $Id: $
* @since 1.8.1
*/
public class RrdGraphController extends AbstractController {
private RrdGraphService m_rrdGraphService;
/** {@inheritDoc} */
@Override
protected ModelAndView handleRequestInternal(HttpServletRequest request,
HttpServletResponse response) throws Exception {
String[] requiredParameters = new String[] {
"resourceId",
"start",
"end"
};
for (String requiredParameter : requiredParameters) {
if (request.getParameter(requiredParameter) == null) {
throw new MissingParameterException(requiredParameter,
requiredParameters);
}
}
String resourceId = request.getParameter("resourceId");
long times[] = this.parseTimes(request);
long startTime = times[0];
long endTime = times[1];
InputStream tempIn;
if ("true".equals(request.getParameter("adhoc"))) {
String[] adhocRequiredParameters = new String[] {
"title",
"ds",
"agfunction",
"color",
"dstitle",
"style"
};
for (String requiredParameter : adhocRequiredParameters) {
if (request.getParameter(requiredParameter) == null) {
throw new MissingParameterException(requiredParameter,
adhocRequiredParameters);
}
}
String title = request.getParameter("title");
String[] dataSources = request.getParameterValues("ds");
String[] aggregateFunctions = request.getParameterValues("agfunction");
String[] colors = request.getParameterValues("color");
String[] dataSourceTitles = request.getParameterValues("dstitle");
String[] styles = request.getParameterValues("style");
tempIn = m_rrdGraphService.getAdhocGraph(resourceId,
title,
dataSources,
aggregateFunctions,
colors,
dataSourceTitles,
styles,
startTime, endTime);
} else {
String report = request.getParameter("report");
if (report == null) {
throw new MissingParameterException("report");
}
tempIn = m_rrdGraphService.getPrefabGraph(resourceId,
report, startTime, endTime);
}
response.setContentType("image/png");
StreamUtils.streamToStream(tempIn, response.getOutputStream());
tempIn.close();
return null;
}
public long[] parseTimes(HttpServletRequest request) {
String startTime = request.getParameter("start");
String endTime = request.getParameter("end");
if(startTime == null || "".equals(startTime)) {
startTime = "now - 1day";
}
if(endTime == null || "".equals(endTime)) {
endTime = "now";
}
boolean startIsInteger = false;
boolean endIsInteger = false;
long start = 0, end = 0;
try {
start = Long.valueOf(startTime);
startIsInteger = true;
} catch (NumberFormatException e) {
}
try {
end = Long.valueOf(endTime);
endIsInteger = true;
} catch (NumberFormatException e) {
}
if(endIsInteger && startIsInteger) {
return new long[] {start, end};
}
//One or both of start/end aren't integers, so we need to do full parsing using TimeParser
//But, if one of them *is* an integer, convert from incoming milliseconds to seconds that
// is expected for epoch times by TimeParser
if(startIsInteger) {
//Convert to seconds
startTime = ""+(start/1000);
}
if(endIsInteger) {
endTime = "" +(end/1000);
}
TimeParser startParser = new TimeParser(startTime);
TimeParser endParser = new TimeParser(endTime);
try {
TimeSpec specStart = startParser.parse();
TimeSpec specEnd = endParser.parse();
long results[] = TimeSpec.getTimestamps(specStart, specEnd);
//Multiply by 1000. TimeSpec returns timestamps in Seconds, not Milliseconds. Gah.
results[0] = results[0]*1000;
results[1] = results[1]*1000;
return results;
} catch (RrdException e) {
throw new IllegalArgumentException("Could not parse start '"+ startTime+"' and end '"+endTime+"' as valid time specifications", e);
}
}
/**
* <p>getRrdGraphService</p>
*
* @return a {@link org.opennms.web.svclayer.RrdGraphService} object.
*/
public RrdGraphService getRrdGraphService() {
return m_rrdGraphService;
}
/**
* <p>setRrdGraphService</p>
*
* @param rrdGraphService a {@link org.opennms.web.svclayer.RrdGraphService} object.
*/
public void setRrdGraphService(RrdGraphService rrdGraphService) {
m_rrdGraphService = rrdGraphService;
}
}