/******************************************************************************* * This file is part of OpenNMS(R). * * Copyright (C) 2007-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.ksc; import java.util.ArrayList; import java.util.Arrays; import java.util.Calendar; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Set; import java.util.TreeSet; import java.util.concurrent.Executor; import java.util.concurrent.Executors; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.opennms.core.concurrent.LogPreservingThreadFactory; import org.opennms.core.utils.ThreadCategory; import org.opennms.core.utils.WebSecurityUtils; import org.opennms.netmgt.config.KSC_PerformanceReportFactory; import org.opennms.netmgt.config.kscReports.Graph; import org.opennms.netmgt.config.kscReports.Report; import org.opennms.netmgt.model.OnmsResource; import org.opennms.netmgt.model.PrefabGraph; import org.opennms.web.graph.KscResultSet; import org.opennms.web.servlet.MissingParameterException; import org.opennms.web.springframework.security.Authentication; import org.opennms.web.svclayer.KscReportService; import org.opennms.web.svclayer.ResourceService; import org.springframework.beans.factory.InitializingBean; import org.springframework.orm.ObjectRetrievalFailureException; import org.springframework.util.Assert; import org.springframework.web.servlet.ModelAndView; import org.springframework.web.servlet.mvc.AbstractController; /** * <p>CustomViewController class.</p> * * @author ranger * @version $Id: $ * @since 1.8.1 */ public class CustomViewController extends AbstractController implements InitializingBean { public enum Parameters { report, type, timespan, graphtype } private KSC_PerformanceReportFactory m_kscReportFactory; private KscReportService m_kscReportService; private ResourceService m_resourceService; private int m_defaultGraphsPerLine = 0; private Executor m_executor; private Set<String> m_resourcesPendingPromotion = Collections.synchronizedSet(new HashSet<String>()); /** {@inheritDoc} */ @Override protected ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response) throws Exception { String[] requiredParameters = new String[] { "report", "type" }; // Get Form Variable int reportId = -1; String reportType = WebSecurityUtils.sanitizeString(request.getParameter(Parameters.type.toString())); String reportIdString = WebSecurityUtils.sanitizeString(request.getParameter(Parameters.report.toString())); if (reportType == null) { throw new MissingParameterException(Parameters.type.toString(), requiredParameters); } if (reportIdString == null) { throw new MissingParameterException(Parameters.report.toString(), requiredParameters); } if (reportType.equals("node") || reportType.equals("custom")) { reportId = WebSecurityUtils.safeParseInt(reportIdString); } String overrideTimespan = WebSecurityUtils.sanitizeString(request.getParameter(Parameters.timespan.toString())); if ("null".equals(overrideTimespan) || "none".equals(overrideTimespan)) { overrideTimespan = null; } String overrideGraphType = WebSecurityUtils.sanitizeString(request.getParameter(Parameters.graphtype.toString())); if ("null".equals(overrideGraphType) || "none".equals(overrideGraphType)) { overrideGraphType = null; } // Load report to view Report report = null; if ("node".equals(reportType)) { log().debug("handleRequestInternal: buildNodeReport(reportId) " + reportId); report = getKscReportService().buildNodeReport(reportId); } else if ("domain".equals(reportType)) { log().debug("handleRequestInternal: buildDomainReport(reportIdString) " + reportIdString); report = getKscReportService().buildDomainReport(reportIdString); } else if ("custom".equals(reportType)) { log().debug("handleRequestInternal: getReportByIndex(reportId) " + reportId); report = m_kscReportFactory.getReportByIndex(reportId); if (report == null) { throw new ServletException("Report could not be found in config file for index '" + reportId + "'"); } } else { throw new IllegalArgumentException("value to 'type' parameter of '" + reportType + "' is not supported. Must be one of: node, domain, or custom"); } // Get the list of available prefabricated graph options Map<String, OnmsResource> resourceMap = new HashMap<String, OnmsResource>(); Set<PrefabGraph> prefabGraphs = new TreeSet<PrefabGraph>(); removeBrokenGraphsFromReport(report); List<Graph> graphCollection = report.getGraphCollection(); if (!graphCollection.isEmpty()) { List<OnmsResource> resources = getKscReportService().getResourcesFromGraphs(graphCollection); for (int i = 0; i < graphCollection.size(); i++) { Graph graph = graphCollection.get(i); OnmsResource resource = null; try { resource = resources.get(i); }catch(IndexOutOfBoundsException e) { log().debug("Resource List Index Out Of Bounds Caught ", e); } resourceMap.put(graph.toString(), resource); if (resource == null) { log().debug("Could not get resource for graph " + graph + " in report " + report.getTitle()); } else { prefabGraphs.addAll(Arrays.asList(getResourceService().findPrefabGraphsForResource(resource))); } } // Get default graph type from first element of graph_options // XXX Do we care about the tests on reportType? if (("node".equals(reportType) || "domain".equals(reportType)) && overrideGraphType == null && !prefabGraphs.isEmpty()) { // Get the name of the first item. prefabGraphs is sorted. overrideGraphType = prefabGraphs.iterator().next().getName(); if (log().isDebugEnabled()) { log().debug("custom_view: setting default graph type to " + overrideGraphType); } } } List<KscResultSet> resultSets = new ArrayList<KscResultSet>(report.getGraphCount()); for (Graph graph : graphCollection) { OnmsResource resource = resourceMap.get(graph.toString()); if (resource != null) { promoteResourceAttributesIfNecessary(resource); } String displayGraphType; if (overrideGraphType == null) { displayGraphType = graph.getGraphtype(); } else { displayGraphType = overrideGraphType; } PrefabGraph displayGraph; try { displayGraph = getResourceService().getPrefabGraph(displayGraphType); } catch (ObjectRetrievalFailureException e) { if (log().isDebugEnabled()) { log().debug("The prefabricated graph '" + displayGraphType + "' does not exist: " + e, e); } displayGraph = null; } boolean foundGraph = false; if (resource != null) { for (PrefabGraph availableGraph : getResourceService().findPrefabGraphsForResource(resource)) { if (availableGraph.equals(displayGraph)) { foundGraph = true; break; } } } if (!foundGraph) { displayGraph = null; } // gather start/stop time information String displayTimespan = null; if (overrideTimespan == null) { displayTimespan = graph.getTimespan(); } else { displayTimespan = overrideTimespan; } Calendar beginTime = Calendar.getInstance(); Calendar endTime = Calendar.getInstance(); KSC_PerformanceReportFactory.getBeginEndTime(displayTimespan, beginTime, endTime); KscResultSet resultSet = new KscResultSet(graph.getTitle(), beginTime.getTime(), endTime.getTime(), resource, displayGraph); resultSets.add(resultSet); } ModelAndView modelAndView = new ModelAndView("KSC/customView"); modelAndView.addObject("loggedIn", request.getRemoteUser() != null); modelAndView.addObject("reportType", reportType); if (report != null) { modelAndView.addObject("report", reportIdString); } modelAndView.addObject("title", report.getTitle()); modelAndView.addObject("resultSets", resultSets); if (report.getShow_timespan_button()) { if (overrideTimespan == null || !getKscReportService().getTimeSpans(true).containsKey(overrideTimespan)) { modelAndView.addObject("timeSpan", "none"); } else { modelAndView.addObject("timeSpan", overrideTimespan); } modelAndView.addObject("timeSpans", getKscReportService().getTimeSpans(true)); } else { // Make sure it's null so the pulldown list isn't shown modelAndView.addObject("timeSpan", null); } if (report.getShow_graphtype_button()) { LinkedHashMap<String, String> graphTypes = new LinkedHashMap<String, String>(); graphTypes.put("none", "none"); for (PrefabGraph graphOption : prefabGraphs) { graphTypes.put(graphOption.getName(), graphOption.getName()); } if (overrideGraphType == null || !graphTypes.containsKey(overrideGraphType)) { modelAndView.addObject("graphType", "none"); } else { modelAndView.addObject("graphType", overrideGraphType); } modelAndView.addObject("graphTypes", graphTypes); } else { // Make sure it's null so the pulldown list isn't shown modelAndView.addObject("graphType", null); } modelAndView.addObject("showCustomizeButton", ( request.isUserInRole( Authentication.ROLE_ADMIN ) || !request.isUserInRole(Authentication.ROLE_READONLY) ) && (request.getRemoteUser() != null)); if (report.getGraphs_per_line() > 0) { modelAndView.addObject("graphsPerLine", report.getGraphs_per_line()); } else { modelAndView.addObject("graphsPerLine", getDefaultGraphsPerLine()); } return modelAndView; } private void removeBrokenGraphsFromReport(Report report) { for (Iterator<Graph> itr = report.getGraphCollection().iterator(); itr.hasNext();) { Graph graph = itr.next(); try { getKscReportService().getResourceFromGraph(graph); } catch (ObjectRetrievalFailureException orfe) { log().error("Removing graph '" + graph.getTitle() + "' in KSC report '" + report.getTitle() + "' because the resource it refers to could not be found. Perhaps resource '"+ graph.getResourceId() + "' (or its ancestor) referenced by this graph no longer exists?"); itr.remove(); } catch (Throwable e) { log().error("Unexpected error while scanning through graphs in report: " + e.getMessage(), e); itr.remove(); } } } private void promoteResourceAttributesIfNecessary(final OnmsResource resource) { boolean needToSchedule = false; if(resource != null && resource.getId() != null) { needToSchedule = m_resourcesPendingPromotion.add(resource.getId()); } if (needToSchedule) { m_executor.execute(new Runnable() { public void run() { getResourceService().promoteGraphAttributesForResource(resource); m_resourcesPendingPromotion.remove(resource.getId()); } }); } } private static ThreadCategory log() { return ThreadCategory.getInstance(CustomViewController.class); } /** * <p>getKscReportFactory</p> * * @return a {@link org.opennms.netmgt.config.KSC_PerformanceReportFactory} object. */ public KSC_PerformanceReportFactory getKscReportFactory() { return m_kscReportFactory; } /** * <p>setKscReportFactory</p> * * @param kscReportFactory a {@link org.opennms.netmgt.config.KSC_PerformanceReportFactory} object. */ public void setKscReportFactory(KSC_PerformanceReportFactory kscReportFactory) { m_kscReportFactory = kscReportFactory; } /** * <p>getDefaultGraphsPerLine</p> * * @return a int. */ public int getDefaultGraphsPerLine() { return m_defaultGraphsPerLine; } /** * <p>setDefaultGraphsPerLine</p> * * @param defaultGraphsPerLine a int. */ public void setDefaultGraphsPerLine(int defaultGraphsPerLine) { Assert.isTrue(defaultGraphsPerLine > 0, "property defaultGraphsPerLine must be greater than zero"); m_defaultGraphsPerLine = defaultGraphsPerLine; } /** * <p>getKscReportService</p> * * @return a {@link org.opennms.web.svclayer.KscReportService} object. */ public KscReportService getKscReportService() { return m_kscReportService; } /** * <p>setKscReportService</p> * * @param kscReportService a {@link org.opennms.web.svclayer.KscReportService} object. */ public void setKscReportService(KscReportService kscReportService) { m_kscReportService = kscReportService; } /** * <p>getResourceService</p> * * @return a {@link org.opennms.web.svclayer.ResourceService} object. */ public ResourceService getResourceService() { return m_resourceService; } /** * <p>setResourceService</p> * * @param resourceService a {@link org.opennms.web.svclayer.ResourceService} object. */ public void setResourceService(ResourceService resourceService) { m_resourceService = resourceService; } /** * <p>afterPropertiesSet</p> * * @throws java.lang.Exception if any. */ @Override public void afterPropertiesSet() throws Exception { Assert.state(m_kscReportFactory != null, "property kscReportFactory must be set"); Assert.state(m_kscReportService != null, "property kscReportService must be set"); Assert.state(m_resourceService != null, "property resourceService must be set"); Assert.state(m_defaultGraphsPerLine != 0, "property defaultGraphsPerLine must be set"); m_executor = Executors.newSingleThreadExecutor( new LogPreservingThreadFactory(getClass().getSimpleName(), 1, false) ); } }