org.hyperic.hq.ui.action.portlet.availsummary.ViewAction.java Source code

Java tutorial

Introduction

Here is the source code for org.hyperic.hq.ui.action.portlet.availsummary.ViewAction.java

Source

/*
 * NOTE: This copyright does *not* cover user programs that use HQ
 * program services by normal system calls through the application
 * program interfaces provided as part of the Hyperic Plug-in Development
 * Kit or the Hyperic Client Development Kit - this is merely considered
 * normal use of the program, and does *not* fall under the heading of
 * "derived work".
 * 
 * Copyright (C) [2004-2008], Hyperic, Inc.
 * This file is part of HQ.
 * 
 * HQ is free software; you can redistribute it and/or modify
 * it under the terms version 2 of the GNU General Public License as
 * published by the Free Software Foundation. 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307
 * USA.
 */

package org.hyperic.hq.ui.action.portlet.availsummary;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.TreeSet;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import net.sf.ehcache.Cache;
import net.sf.ehcache.CacheManager;
import net.sf.ehcache.Element;

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.action.ActionRedirect;
import org.hyperic.hq.appdef.shared.AppdefEntityID;
import org.hyperic.hq.appdef.shared.AppdefEntityNotFoundException;
import org.hyperic.hq.appdef.shared.AppdefResourceTypeValue;
import org.hyperic.hq.appdef.shared.AppdefResourceValue;
import org.hyperic.hq.bizapp.shared.AppdefBoss;
import org.hyperic.hq.bizapp.shared.AuthzBoss;
import org.hyperic.hq.bizapp.shared.MeasurementBoss;
import org.hyperic.hq.measurement.MeasurementConstants;
import org.hyperic.hq.measurement.server.session.Measurement;
import org.hyperic.hq.product.MetricValue;
import org.hyperic.hq.ui.Constants;
import org.hyperic.hq.ui.WebUser;
import org.hyperic.hq.ui.action.BaseAction;
import org.hyperic.hq.ui.exception.ParameterNotFoundException;
import org.hyperic.hq.ui.server.session.DashboardConfig;
import org.hyperic.hq.ui.shared.DashboardManager;
import org.hyperic.hq.ui.util.DashboardUtils;
import org.hyperic.hq.ui.util.RequestUtils;
import org.hyperic.util.config.ConfigResponse;
import org.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;

/**
 * This action class is used by the Availability Summary portlet. It's main use
 * is to generate the JSON objects required for display into the UI.
 */
public class ViewAction extends BaseAction {

    private final Log log = LogFactory.getLog(ViewAction.class.getName());
    private final AuthzBoss authzBoss;
    private final MeasurementBoss measurementBoss;
    private final AppdefBoss appdefBoss;
    private final DashboardManager dashboardManager;

    @Autowired
    public ViewAction(AuthzBoss authzBoss, MeasurementBoss measurementBoss, AppdefBoss appdefBoss,
            DashboardManager dashboardManager) {
        super();
        this.authzBoss = authzBoss;
        this.measurementBoss = measurementBoss;
        this.appdefBoss = appdefBoss;
        this.dashboardManager = dashboardManager;
    }

    @Override
    public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request,
            HttpServletResponse response) throws Exception {

        HttpSession session = request.getSession();
        WebUser user = RequestUtils.getWebUser(session);
        DashboardConfig dashConfig = dashboardManager
                .findDashboard((Integer) session.getAttribute(Constants.SELECTED_DASHBOARD_ID), user, authzBoss);

        if (dashConfig == null) {
            return new ActionRedirect("/Dashboard.do");
        }

        ConfigResponse dashPrefs = dashConfig.getConfig();

        String token;
        long ts = System.currentTimeMillis();

        try {
            token = RequestUtils.getStringParameter(request, "token");
            if (token != null) {
                //token should be alpha-numeric
                if (!token.matches("^[\\w-]*$")) {
                    log.warn("Token cleared by xss filter: " + token);
                    token = null;
                }
            }
        } catch (ParameterNotFoundException e) {
            token = null;
        }

        String resKey = PropertiesForm.RESOURCES;
        String numKey = PropertiesForm.NUM_TO_SHOW;
        String titleKey = PropertiesForm.TITLE;

        if (token != null) {
            resKey += token;
            numKey += token;
            titleKey += token;
        }

        List<AppdefEntityID> entityIds = DashboardUtils.preferencesAsEntityIds(resKey, dashPrefs);

        // Can only do Platforms, Servers, and Services
        for (Iterator<AppdefEntityID> it = entityIds.iterator(); it.hasNext();) {
            AppdefEntityID aeid = it.next();

            if (aeid.isPlatform() || aeid.isServer() || aeid.isService()) {
                continue;
            }

            it.remove();
        }

        AppdefEntityID[] arrayIds = entityIds.toArray(new AppdefEntityID[entityIds.size()]);
        int count = Integer.parseInt(dashPrefs.getValue(numKey, "10"));
        int sessionId = user.getSessionId().intValue();

        CacheEntry[] ents = new CacheEntry[arrayIds.length];
        List<Integer> measurements = new ArrayList<Integer>(arrayIds.length);
        Map<String, AvailSummary> res = new HashMap<String, AvailSummary>();
        long interval = 0;
        ArrayList<String> toRemove = new ArrayList<String>();
        for (int i = 0; i < arrayIds.length; i++) {
            AppdefEntityID id = arrayIds[i];
            try {
                ents[i] = loadData(sessionId, id);
            } catch (AppdefEntityNotFoundException e) {
                toRemove.add(id.getAppdefKey());
            }

            if (ents[i] != null && ents[i].getMeasurement() != null) {
                measurements.add(i, ents[i].getMeasurement().getId());
                if (ents[i].getMeasurement().getInterval() > interval) {
                    interval = ents[i].getMeasurement().getInterval();
                }
            } else {
                measurements.add(i, null);
            }
        }

        MetricValue[] vals = measurementBoss.getLastMetricValue(sessionId, measurements, interval);

        for (int i = 0; i < ents.length; i++) {
            CacheEntry ent = ents[i];
            MetricValue val = vals[i];

            // If no avail measurement is scheduled, skip this resource
            if (ent != null && val != null) {
                if (ent.getType() == null) {
                    AppdefResourceValue resVal = appdefBoss.findById(sessionId, arrayIds[i]);
                    if (resVal == null) {
                        continue;
                    }
                    ent.setType(resVal.getAppdefResourceTypeValue());
                }

                String name = ent.getType().getName();
                AvailSummary summary = res.get(name);
                if (summary == null) {
                    summary = new AvailSummary(ent.getType());
                    res.put(name, summary);
                }
                summary.setAvailability(val.getValue());
            }
        }

        JSONObject availSummary = new JSONObject();
        List<JSONObject> types = new ArrayList<JSONObject>();

        TreeSet<AvailSummary> sortedSet = new TreeSet<AvailSummary>(new AvailSummaryComparator());
        sortedSet.addAll(res.values());

        for (Iterator<AvailSummary> i = sortedSet.iterator(); i.hasNext() && count-- > 0;) {
            AvailSummary summary = i.next();
            JSONObject typeSummary = new JSONObject();
            typeSummary.put("resourceTypeName", summary.getTypeName());
            typeSummary.put("numUp", summary.getNumUp());
            typeSummary.put("numDown", summary.getNumDown());
            typeSummary.put("appdefType", summary.getAppdefType());
            typeSummary.put("appdefTypeId", summary.getAppdefTypeId());

            types.add(typeSummary);
        }

        availSummary.put("availSummary", types);

        if (token != null) {
            availSummary.put("token", token);
        } else {
            availSummary.put("token", JSONObject.NULL);
        }
        availSummary.put("title", dashPrefs.getValue(titleKey, ""));

        response.getWriter().write(availSummary.toString());

        log.debug("Availability summary loaded in " + (System.currentTimeMillis() - ts) + " ms");

        if (toRemove.size() > 0) {
            log.debug("Removing " + toRemove.size() + " missing resources.");
            DashboardUtils.removeResources(toRemove.toArray(new String[toRemove.size()]), resKey, dashPrefs);
        }

        return null;
    }

    private class AvailSummary {
        private final AppdefResourceTypeValue _type;
        private int _numUp = 0;
        private int _numDown = 0;

        public AvailSummary(AppdefResourceTypeValue type) {
            _type = type;
        }

        public void setAvailability(double avail) {
            if (avail == MeasurementConstants.AVAIL_UP) {
                _numUp++;
            } else {
                _numDown++;
            }
        }

        public String getTypeName() {
            return _type.getName();
        }

        public int getAppdefType() {
            return _type.getAppdefType();
        }

        public Integer getAppdefTypeId() {
            return _type.getId();
        }

        public int getNumUp() {
            return _numUp;
        }

        public int getNumDown() {
            return _numDown;
        }

        public double getAvailPercentage() {
            return (double) _numUp / (_numDown + _numUp);
        }
    }

    private class AvailSummaryComparator implements Comparator<AvailSummary> {

        public int compare(AvailSummary s1, AvailSummary s2) {

            if (s1.getAvailPercentage() == s2.getAvailPercentage()) {
                // Sort on the actual number
                if (s1.getNumDown() != s2.getNumDown()) {
                    return s1.getNumDown() < s2.getNumDown() ? 1 : -1;
                }
                // Sort on type name if equal avail percentage
                return s1.getTypeName().compareTo(s2.getTypeName());
            } else if (s1.getAvailPercentage() < s2.getAvailPercentage()) {
                return -1;
            } else {
                return 1;
            }
        }
    }

    private CacheEntry loadData(int sessionId, AppdefEntityID id) throws AppdefEntityNotFoundException {
        Cache cache = CacheManager.getInstance().getCache("AvailabilitySummary");
        Element e = cache.get(id);

        if (e != null) {
            return (CacheEntry) e.getObjectValue();
        }

        // Otherwise, load from the backend

        try {
            Measurement m = measurementBoss.findAvailabilityMetric(sessionId, id);

            CacheEntry res = new CacheEntry(m);
            cache.put(new Element(id, res));
            return res;
        } catch (Exception ex) {
            log.debug("Caught exception loading data: " + ex, ex);
            return null;
        }
    }

    // Classes for caching dashboard data
    private class CacheEntry {
        private AppdefResourceTypeValue _type;
        private final Measurement _m;

        public CacheEntry(Measurement m) {
            _m = m;
        }

        public AppdefResourceTypeValue getType() {
            return _type;
        }

        public void setType(AppdefResourceTypeValue type) {
            _type = type;
        }

        public Measurement getMeasurement() {
            return _m;
        }
    }
}