architecture.ee.web.spring.controller.SecureMoSKitoController.java Source code

Java tutorial

Introduction

Here is the source code for architecture.ee.web.spring.controller.SecureMoSKitoController.java

Source

/*
 * Copyright 2012, 2013 Donghyuck, Son
 *
 * 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 architecture.ee.web.spring.controller;

import java.io.File;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;

import javax.management.BadAttributeValueExpException;
import javax.management.BadBinaryOpValueExpException;
import javax.management.BadStringOperationException;
import javax.management.InvalidApplicationException;
import javax.management.MBeanServer;
import javax.management.MBeanServerFactory;
import javax.management.ObjectInstance;
import javax.management.ObjectName;
import javax.management.QueryExp;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.context.request.NativeWebRequest;

import architecture.ee.exception.NotFoundException;
import architecture.ee.web.monitoring.moskito.AccumulatedSingleGraphObject;
import architecture.ee.web.monitoring.moskito.AccumulatedValueObject;
import architecture.ee.web.monitoring.moskito.AccumulatorDefinitionObject;
import architecture.ee.web.monitoring.moskito.AccumulatorObject;
import architecture.ee.web.monitoring.moskito.LibraryObject;
import architecture.ee.web.monitoring.moskito.ProducerObject;
import architecture.ee.web.monitoring.moskito.StatLineObject;
import architecture.ee.web.monitoring.moskito.StatValue;
import architecture.ee.web.monitoring.moskito.ThresholdAlertObject;
import architecture.ee.web.monitoring.moskito.ThresholdStatusObject;
import net.anotheria.moskito.core.accumulation.AccumulatedValue;
import net.anotheria.moskito.core.accumulation.Accumulator;
import net.anotheria.moskito.core.accumulation.AccumulatorRepository;
import net.anotheria.moskito.core.predefined.IMemoryPoolStats;
import net.anotheria.moskito.core.predefined.OSStats;
import net.anotheria.moskito.core.predefined.RequestOrientedStats;
import net.anotheria.moskito.core.predefined.RuntimeStats;
import net.anotheria.moskito.core.producers.IStats;
import net.anotheria.moskito.core.producers.IStatsProducer;
import net.anotheria.moskito.core.registry.IProducerFilter;
import net.anotheria.moskito.core.registry.IProducerRegistry;
import net.anotheria.moskito.core.registry.IProducerRegistryAPI;
import net.anotheria.moskito.core.registry.ProducerRegistryAPIFactory;
import net.anotheria.moskito.core.registry.ProducerRegistryFactory;
import net.anotheria.moskito.core.threshold.Threshold;
import net.anotheria.moskito.core.threshold.ThresholdRepository;
import net.anotheria.moskito.core.threshold.alerts.AlertHistory;
import net.anotheria.moskito.core.threshold.alerts.ThresholdAlert;
import net.anotheria.moskito.web.session.SessionCountStats;
import net.anotheria.util.maven.MavenVersionReader;

@Controller("secure-moskito-data-controller")
@RequestMapping("/secure/data")
public class SecureMoSKitoController {

    private static final Log log = LogFactory.getLog(SecureMoSKitoController.class);
    private static final IProducerRegistryAPI producerRegistryAPI = new ProducerRegistryAPIFactory()
            .createProducerRegistryAPI();

    public SecureMoSKitoController() {
    }

    @RequestMapping(value = "/stage/more/list_library.json", method = { RequestMethod.POST, RequestMethod.GET })
    @ResponseBody
    public List<LibraryObject> getLibraries(NativeWebRequest request) throws Exception {
        ArrayList<LibraryObject> aBeans = new ArrayList<LibraryObject>();
        String context = request.getContextPath();
        if (StringUtils.isEmpty(context))
            context = "/";

        List<URL> classpath = getClassPathUrls(context);
        for (URL url : classpath) {
            String fileName = url.getFile();
            if (!fileName.endsWith(".jar"))
                continue;
            File f = new File(fileName);
            LibraryObject bean = new LibraryObject();
            int lastSlash = fileName.lastIndexOf('/');
            try {
                bean.setName(fileName.substring(lastSlash + 1));
                bean.setMavenVersion(MavenVersionReader.readVersionFromJar(f));
                if (bean.getMavenVersion() == null) {
                    bean.setLastModified(new Date(f.lastModified()));
                }
            } catch (Exception e) {
                log.warn("couldn't obtain lib version, skipped this url " + url, e);
            }
            aBeans.add(bean);
        }

        return aBeans;
    }

    private List<URL> getClassPathUrls(final String context) {
        log.debug("context: " + context);
        List<URL> forTomcat7 = getClassPathUrlsForTomcat(context, "context");
        if (forTomcat7 != null && forTomcat7.size() > 0)
            return forTomcat7;
        List<URL> forTomcat6 = getClassPathUrlsForTomcat(context, "path");
        if (forTomcat6 != null && forTomcat6.size() > 0)
            return forTomcat6;
        //add another lookup methods here.
        return new ArrayList<URL>();
    }

    private List<URL> getClassPathUrlsForTomcat(final String context, final String contextPropertyName) {
        List<MBeanServer> servers = MBeanServerFactory.findMBeanServer(null);
        for (MBeanServer s : servers) {
            Set<ObjectInstance> instances = s.queryMBeans(null, new QueryExp() {

                public boolean apply(ObjectName name) throws BadStringOperationException,
                        BadBinaryOpValueExpException, BadAttributeValueExpException, InvalidApplicationException {
                    String type = name.getKeyProperty("type");
                    log.debug(name.getDomain() + " : " + name.getKeyPropertyList());
                    if (!type.equals("WebappClassLoader"))
                        return false;
                    if (!name.getDomain().equals("Catalina"))
                        return false;
                    if (!name.getKeyProperty(contextPropertyName).equals(context))
                        return false;
                    return true;
                }

                public void setMBeanServer(MBeanServer s) {
                }
            });
            if (instances.size() > 0) {
                try {
                    URL[] urls = (URL[]) s.getAttribute(instances.iterator().next().getObjectName(), "URLs");
                    return Arrays.asList(urls);
                } catch (Exception e) {
                }

            }
        }
        return null;
    }

    @RequestMapping(value = "/stage/thresholds/alerts.json", method = { RequestMethod.POST, RequestMethod.GET })
    @ResponseBody
    public List<ThresholdAlertObject> getAlerts(NativeWebRequest request) throws Exception {
        ArrayList<ThresholdAlertObject> aBeans = new ArrayList<ThresholdAlertObject>();
        for (ThresholdAlert alert : AlertHistory.INSTANCE.getAlerts()) {
            ThresholdAlertObject alertBean = new ThresholdAlertObject();
            alertBean.setId(alert.getThreshold().getId());
            alertBean.setName(alert.getThreshold().getName());
            alertBean.setOldColorCode(alert.getOldStatus().toString().toLowerCase());
            alertBean.setOldStatus(alert.getOldStatus().toString());
            alertBean.setOldValue(alert.getOldValue());
            alertBean.setNewColorCode(alert.getNewStatus().toString().toLowerCase());
            alertBean.setNewStatus(alert.getNewStatus().toString());
            alertBean.setNewValue(alert.getNewValue());
            alertBean.setUpdatedDate(new Date(alert.getTimestamp()));
            aBeans.add(alertBean);
        }
        return aBeans;
    }

    @RequestMapping(value = "/stage/thresholds/list.json", method = { RequestMethod.POST, RequestMethod.GET })
    @ResponseBody
    public List<ThresholdStatusObject> getThresholds(NativeWebRequest request) throws Exception {
        List<Threshold> thresholds = ThresholdRepository.getInstance().getThresholds();
        ArrayList<ThresholdStatusObject> ret = new ArrayList<ThresholdStatusObject>();
        for (Threshold t : thresholds) {
            ThresholdStatusObject status = new ThresholdStatusObject();
            status.setName(t.getName());
            status.setColorCode(t.getStatus().toString().toLowerCase());
            status.setStatus(t.getStatus().toString().toLowerCase());
            status.setDescription(t.getDefinition().describe());
            status.setValue(t.getLastValue());
            status.setPreviousColorCode(t.getPreviousStatus().toString().toLowerCase());
            status.setPreviousStatus(t.getPreviousStatus().toString().toLowerCase());
            status.setUpdatedDate(
                    t.getStatusChangeTimestamp() == 0 ? null : new Date(t.getStatusChangeTimestamp()));
            status.setStatusForSorting(t.getStatus());
            status.setId(t.getId());
            status.setFlipCount(t.getFlipCount());
            ret.add(status);
        }
        return ret;
    }

    @RequestMapping(value = "/stage/accumulators/list.json", method = { RequestMethod.POST, RequestMethod.GET })
    @ResponseBody
    public List<AccumulatorDefinitionObject> getAccumulatorDefinitions(NativeWebRequest request) throws Exception {
        List<Accumulator> accumulators = AccumulatorRepository.getInstance().getAccumulators();
        List<AccumulatorDefinitionObject> ret = new ArrayList<AccumulatorDefinitionObject>();
        for (Accumulator a : accumulators) {
            AccumulatorDefinitionObject bean = new AccumulatorDefinitionObject();
            bean.setName(a.getName());
            bean.setPath(a.getDefinition().describe());
            bean.setId(a.getId());
            List<AccumulatedValue> values = a.getValues();
            if (values != null && values.size() > 0) {
                bean.setNumberOfValues(values.size());
                bean.setLastValueDate(new Date(values.get(values.size() - 1).getTimestamp()));
            } else {
                bean.setNumberOfValues(0);
            }
            ret.add(bean);
        }
        return ret;
    }

    @RequestMapping(value = "/stage/accumulators/get.json", method = { RequestMethod.POST, RequestMethod.GET })
    @ResponseBody
    public AccumulatorDefinitionObject getAccumulatorDefinition(
            @RequestParam(value = "accumulator", required = true) String accumulatorId, NativeWebRequest request)
            throws Exception {
        Accumulator a = AccumulatorRepository.getInstance().getById(accumulatorId);
        AccumulatorDefinitionObject bean = new AccumulatorDefinitionObject();
        bean.setName(a.getName());
        bean.setPath(a.getDefinition().describe());
        bean.setId(a.getId());
        List<AccumulatedValue> values = a.getValues();
        if (values != null && values.size() > 0) {
            bean.setNumberOfValues(values.size());
            bean.setLastValueDate(new Date(values.get(values.size() - 1).getTimestamp()));
        } else {
            bean.setNumberOfValues(0);
            //bean.setLastValueDate(new Date(0L));
        }
        return bean;
    }

    @RequestMapping(value = "/stage/accumulators/graph.json", method = { RequestMethod.POST, RequestMethod.GET })
    @ResponseBody
    public AccumulatedSingleGraphObject getAccumulatorGraphData(
            @RequestParam(value = "accumulator", required = true) String accumulatorId, NativeWebRequest request)
            throws Exception {
        Accumulator accumulator = AccumulatorRepository.getInstance().getById(accumulatorId);
        AccumulatedSingleGraphObject singleGraphDataBean = new AccumulatedSingleGraphObject(accumulator.getName());
        singleGraphDataBean.setData(new AccumulatorObject(accumulator).getValues());
        return singleGraphDataBean;
    }

    @RequestMapping(value = "/stage/accumulators/graph_data_only.json", method = { RequestMethod.POST,
            RequestMethod.GET })
    @ResponseBody
    public List<AccumulatedValueObject> getAccumulatorGraphDataOnly(
            @RequestParam(value = "accumulator", required = true) String accumulatorId, NativeWebRequest request)
            throws Exception {
        Accumulator accumulator = AccumulatorRepository.getInstance().getById(accumulatorId);
        List<AccumulatedValueObject> values = new LinkedList<AccumulatedValueObject>();
        for (AccumulatedValue v : accumulator.getValues()) {
            AccumulatedValueObject ao = new AccumulatedValueObject(new Date(v.getTimestamp()));
            ao.setName(accumulator.getName());
            ao.addValue(v.getValue());
            values.add(ao);
        }

        return values;
    }

    @RequestMapping(value = "/stage/producers/list.json", method = { RequestMethod.POST, RequestMethod.GET })
    @ResponseBody
    public List<ProducerObject> getProducers(
            @RequestParam(value = "class", defaultValue = "", required = false) String className,
            @RequestParam(value = "interval", defaultValue = "1m", required = false) String intervalName,
            @RequestParam(value = "unit", defaultValue = "SECONDS", required = false) String unit,
            @RequestParam(value = "createFirstStats", defaultValue = "true", required = false) boolean createFirstStats,
            @RequestParam(value = "createAllStats", defaultValue = "false", required = false) boolean createAllStats,
            @RequestParam(value = "category", defaultValue = "", required = false) String currentCategory,
            @RequestParam(value = "subsystem", defaultValue = "", required = false) String currentSubsystem,
            NativeWebRequest request) throws NotFoundException {
        List<IStatsProducer> producers = producerRegistryAPI.getAllProducers();
        List<ProducerObject> list = new ArrayList<ProducerObject>(producers.size());
        for (IStatsProducer<?> producer : producers) {
            if (StringUtils.isNotEmpty(currentCategory)
                    && !StringUtils.equals(producer.getCategory(), currentCategory)) {
                continue;
            }
            if (StringUtils.isNotEmpty(currentSubsystem)
                    && !StringUtils.equals(producer.getSubsystem(), currentSubsystem)) {
                continue;
            }
            if (StringUtils.isNotEmpty(className)
                    && !StringUtils.equals(producer.getClass().getSimpleName(), className)) {
                continue;
            }
            list.add(convertStatsProducerToPO(producer, intervalName,
                    net.anotheria.moskito.core.stats.TimeUnit.fromString(unit), createFirstStats, createAllStats));
        }
        return list;
    }

    @RequestMapping(value = "/stage/producers/get.json", method = { RequestMethod.POST, RequestMethod.GET })
    @ResponseBody
    public ProducerObject getProducer(
            @RequestParam(value = "producerId", defaultValue = "", required = true) String producerId,
            @RequestParam(value = "interval", defaultValue = "1m", required = false) String intervalName,
            @RequestParam(value = "unit", defaultValue = "SECONDS", required = false) String unit,
            @RequestParam(value = "createFirstStats", defaultValue = "false", required = false) boolean createFirstStats,
            @RequestParam(value = "createAllStats", defaultValue = "true", required = false) boolean createAllStats,
            NativeWebRequest request) throws NotFoundException {
        IStatsProducer producer = producerRegistryAPI.getProducer(producerId); // getIProducerRegistry().getProducer(producerId);
        return convertStatsProducerToPO(producer, intervalName,
                net.anotheria.moskito.core.stats.TimeUnit.fromString(unit), createFirstStats, createAllStats);
    }

    @RequestMapping(value = "/stage/runtime/stats.json", method = { RequestMethod.POST, RequestMethod.GET })
    @ResponseBody
    public ProducerObject getRuntimeStats(
            @RequestParam(value = "interval", defaultValue = "1m", required = false) String intervalName,
            @RequestParam(value = "unit", defaultValue = "SECONDS", required = false) String unit,
            NativeWebRequest request) throws NotFoundException {
        IStatsProducer<RuntimeStats> producer = ProducerRegistryFactory.getProducerRegistryInstance()
                .getProducer("Runtime");
        return convertStatsProducerToPO(producer, intervalName,
                net.anotheria.moskito.core.stats.TimeUnit.fromString(unit), true, false);
    }

    @RequestMapping(value = "/stage/os/stats.json", method = { RequestMethod.POST, RequestMethod.GET })
    @ResponseBody
    public ProducerObject getOSStats(
            @RequestParam(value = "interval", defaultValue = "1m", required = false) String intervalName,
            @RequestParam(value = "unit", defaultValue = "SECONDS", required = false) String unit,
            NativeWebRequest request) throws NotFoundException {
        IStatsProducer<OSStats> producer = ProducerRegistryFactory.getProducerRegistryInstance().getProducer("OS");
        return convertStatsProducerToPO(producer, intervalName,
                net.anotheria.moskito.core.stats.TimeUnit.fromString(unit), true, false);
    }

    @RequestMapping(value = "/stage/memory/stats.json", method = { RequestMethod.POST, RequestMethod.GET })
    @ResponseBody
    public List<ProducerObject> getBuiltInMemoryStats(
            @RequestParam(value = "class", defaultValue = "BuiltInMemoryProducer", required = false) final String className,
            @RequestParam(value = "interval", defaultValue = "1m", required = false) String intervalName,
            @RequestParam(value = "unit", defaultValue = "SECONDS", required = false) String unit,
            NativeWebRequest request) throws NotFoundException {

        List<IStatsProducer> producers = producerRegistryAPI.getProducers(new IProducerFilter() {
            public boolean doesFit(IStatsProducer producer) {
                if (StringUtils.equals(producer.getClass().getSimpleName(), className))
                    return true;
                else
                    return false;
            }
        });
        List<ProducerObject> list = new ArrayList<ProducerObject>(producers.size());
        for (IStatsProducer<?> producer : producers) {
            list.add(convertStatsProducerToPO(producer, intervalName,
                    net.anotheria.moskito.core.stats.TimeUnit.fromString(unit), true, false));
        }
        return list;
    }

    @RequestMapping(value = "/stage/session/stats.json", method = { RequestMethod.POST, RequestMethod.GET })
    @ResponseBody
    public List<ProducerObject> getSessionStats(
            @RequestParam(value = "interval", defaultValue = "1m", required = false) String intervalName,
            @RequestParam(value = "unit", defaultValue = "SECONDS", required = false) String unit,
            NativeWebRequest request) throws NotFoundException {

        List<IStatsProducer> producers = producerRegistryAPI.getProducers(new IProducerFilter() {

            public boolean doesFit(IStatsProducer producer) {
                if (StringUtils.equals(producer.getProducerId(), "SessionCount")
                        || StringUtils.equals(producer.getProducerId(), "SessionCountByTld"))
                    return true;
                else
                    return false;
            }
        });
        List<ProducerObject> list = new ArrayList<ProducerObject>(producers.size());
        for (IStatsProducer producer : producers) {
            list.add(convertStatsProducerToPO(producer, intervalName,
                    net.anotheria.moskito.core.stats.TimeUnit.fromString(unit), true, false));
        }
        return list;
    }

    protected ProducerObject convertStatsProducerToPO(IStatsProducer<? extends IStats> p, String intervalName,
            net.anotheria.moskito.core.stats.TimeUnit timeUnit, boolean createFirstStats, boolean createAllStats) {
        ProducerObject ao = new ProducerObject();
        ao.setProducerId(p.getProducerId());
        ao.setCategory(p.getCategory());
        ao.setSubsystem(p.getSubsystem());
        ao.setProducerClassName(p.getClass().getSimpleName());
        ao.setFullProducerClassName(p.getClass().getName());

        if (createFirstStats) {
            IStats firstStats = p.getStats().get(0);
            ao.setFirstStatsValues(getStatValues(firstStats, intervalName, timeUnit));
        }
        if (createAllStats) {
            List<? extends IStats> allStats = p.getStats();
            for (IStats statObject : allStats) {
                StatLineObject line = new StatLineObject();
                line.setStatName(statObject.getName());
                line.setValues(getStatValues(statObject, intervalName, timeUnit));
                ao.addStatLine(line);
            }
        }
        return ao;
    }

    protected List<StatValue> getStatValues(IStats stat, String intervalName,
            net.anotheria.moskito.core.stats.TimeUnit timeUnit) {

        List<StatValue> row = new ArrayList<StatValue>(stat.getAvailableValueNames().size());

        log.debug("STAT(interval=" + intervalName + ", timeunit=" + timeUnit.name() + ") --- "
                + stat.toStatsString(intervalName, timeUnit));

        if (stat instanceof IMemoryPoolStats) {
            for (String name : stat.getAvailableValueNames()) {
                row.add(getLongStatValue(stat, name, intervalName, timeUnit));
            }
        } else if (stat instanceof OSStats) {
            for (String name : stat.getAvailableValueNames()) {
                row.add(getLongStatValue(stat, name, intervalName, timeUnit));
            }
        } else if (stat instanceof SessionCountStats) {
            for (String name : stat.getAvailableValueNames()) {
                row.add(getLongStatValue(stat, name, intervalName, timeUnit));
            }
        } else if (stat instanceof RequestOrientedStats) {
            for (String name : stat.getAvailableValueNames()) {
                row.add(getLongStatValue(stat, name, intervalName, timeUnit));
            }
        } else if (stat instanceof RuntimeStats) {
            for (String name : stat.getAvailableValueNames()) {
                if (StringUtils.equals(name, "Starttime")) {
                    long value = Long.parseLong(stat.getValueByNameAsString(name, intervalName, timeUnit));
                    row.add(new architecture.ee.web.monitoring.moskito.LongValue(name, value));
                    row.add(new architecture.ee.web.monitoring.moskito.DateValue(name, new Date(value)));
                } else if (StringUtils.equals(name, "Uptime")) {
                    long value = Long.parseLong(stat.getValueByNameAsString(name, intervalName, timeUnit));
                    row.add(new architecture.ee.web.monitoring.moskito.LongValue(name, value));
                    row.add(new architecture.ee.web.monitoring.moskito.LongValue("Uphours",
                            TimeUnit.MILLISECONDS.toHours(value)));
                    row.add(new architecture.ee.web.monitoring.moskito.LongValue("Updays",
                            TimeUnit.MILLISECONDS.toDays(value)));

                } else {
                    row.add(new architecture.ee.web.monitoring.moskito.StringValue(name,
                            stat.getValueByNameAsString(name, intervalName, timeUnit)));
                }
            }
        } else {
            for (String name : stat.getAvailableValueNames()) {
                row.add(new architecture.ee.web.monitoring.moskito.StringValue(name,
                        stat.getValueByNameAsString(name, intervalName, timeUnit)));
            }
        }
        return row;
    }

    protected architecture.ee.web.monitoring.moskito.LongValue getLongStatValue(IStats stat, String name,
            String intervalName, net.anotheria.moskito.core.stats.TimeUnit timeUnit) {
        long value = 0L;
        try {
            String stringValue = stat.getValueByNameAsString(name, intervalName, timeUnit);
            if (StringUtils.isNotEmpty(stringValue) && !StringUtils.isAlpha(stringValue))
                value = Long.parseLong(stringValue);
        } catch (Exception e) {
        }
        return new architecture.ee.web.monitoring.moskito.LongValue(name, value);
    }

    protected IProducerRegistry getIProducerRegistry() {
        return ProducerRegistryFactory.getProducerRegistryInstance();
    }

}