Package com.ajjpj.asysmon.datasink.aggregation

Source Code of com.ajjpj.asysmon.datasink.aggregation.AbstractAsysmonReportServlet$TreeNode

package com.ajjpj.asysmon.datasink.aggregation;

import com.ajjpj.asysmon.ASysMon;
import com.ajjpj.asysmon.config.AGlobalConfig;
import com.ajjpj.asysmon.data.AScalarDataPoint;
import com.ajjpj.asysmon.util.AJsonSerHelper;

import javax.servlet.*;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;

/**
* @author arno
*/
public abstract class AbstractAsysmonReportServlet extends HttpServlet {
    private static final AtomicBoolean hasShutdownHook = new AtomicBoolean(false);

    /**
     * Default implementations returns the singleton instance. Override to customize.
     */
    protected ASysMon getSysMon() {
        return ASysMon.get();
    }

    @Override
    public void init(ServletConfig config) throws ServletException {
        super.init(config);

        final boolean wasInitialized = hasShutdownHook.getAndSet(true);
        if(!wasInitialized) {
            try {
                final ServletContext ctx = config.getServletContext();
                ctx.addListener(new ServletContextListener() {
                    @Override public void contextInitialized(ServletContextEvent sce) { }

                    @Override public void contextDestroyed(ServletContextEvent sce) {
                        if(AGlobalConfig.getImplicitlyShutDownWithServlet()) {
                            getSysMon().shutdown();
                        }
                    }
                });
            } catch (IllegalStateException e) {
                // ignore - this only works if init() is called during container startup, i.e. with load-on-startup in web.xml
            }
        }
    }

    @Override protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        if(req.getParameter("res") != null) {
            serveStaticResource(req.getParameter("res"), resp);
            return;
        }

        if(req.getRequestURI().endsWith("/getData")) {
            serveData(resp);
            return;
        }
        if(req.getRequestURI().endsWith("/doStart")) {
            doStartMeasurements();
            serveData(resp);
            return;
        }
        if(req.getRequestURI().endsWith("/doStop")) {
            doStopMeasurements();
            serveData(resp);
            return;
        }
        if(req.getRequestURI().endsWith("/doClear")) {
            doClearMeasurements();
            serveData(resp);
            return;
        }

        if(! req.getRequestURL().toString().endsWith("/")) {
            resp.sendRedirect(req.getRequestURL() + "/");
            return;
        }

        serveStaticResource("asysmon-aggregated.html", resp);
    }

    private void serveData(HttpServletResponse resp) throws IOException {
        final AJsonSerHelper json = new AJsonSerHelper(resp.getOutputStream());

        json.startObject();

        json.writeKey("title");
        json.writeStringLiteral(getTitle());
        json.writeKey("isStarted");
        json.writeBooleanLiteral(isStarted());

        json.writeKey("scalars");
        json.startObject();
        for(AScalarDataPoint scalar: getSysMon().getScalarMeasurements().values()) {
            writeScalar(json, scalar);
        }
        json.endObject();

        json.writeKey("columnDefs");
        json.startArray();
        for(ColDef colDef: getColDefs()) {
            writeColDef(json, colDef);
        }
        json.endArray();

        json.writeKey("traces");
        json.startArray();
        for(TreeNode n: getData()) {
            writeDataNode(json, n);
        }
        json.endArray();

        json.endObject();
    }

    private void writeColDef(AJsonSerHelper json, ColDef colDef) throws IOException {
        json.startObject();

        json.writeKey("name");
        json.writeStringLiteral(colDef.name);

        json.writeKey("isPercentage");
        json.writeBooleanLiteral(colDef.isPercentage);

        json.writeKey("numFracDigits");
        json.writeNumberLiteral(colDef.numFracDigits, 0);

        json.writeKey("width");
        json.writeStringLiteral(colDef.width.name());

        json.endObject();
    }

    private void writeScalar(AJsonSerHelper json, AScalarDataPoint scalar) throws IOException {
        json.writeKey(scalar.getName());
        json.startObject();

        json.writeKey("value");
        json.writeNumberLiteral(scalar.getValueRaw(), scalar.getNumFracDigits());

        json.writeKey("numFracDigits");
        json.writeNumberLiteral(scalar.getNumFracDigits(), 0);

        json.endObject();
    }

    private void writeDataNode(AJsonSerHelper json, TreeNode node) throws IOException {
        json.startObject();

        json.writeKey("name");
        json.writeStringLiteral(node.identifier);

        json.writeKey("isSerial");
        json.writeBooleanLiteral(node.isSerial);

        json.writeKey("data");
        json.startArray();
        for(int i=0; i<node.colDataRaw.length; i++) {
            json.writeNumberLiteral(node.colDataRaw[i], getColDefs().get(i).numFracDigits);
        }
        json.endArray();

        if(! node.children.isEmpty()) {
            json.writeKey("children");
            json.startArray();
            for(TreeNode child: node.children) {
                writeDataNode(json, child);
            }
            json.endArray();
        }

        json.endObject();
    }

    protected abstract boolean isStarted();
    protected abstract void doStartMeasurements();
    protected abstract void doStopMeasurements();
    protected abstract void doClearMeasurements();

    protected abstract List<ColDef> getColDefs();

    protected abstract List<TreeNode> getData();

    protected enum ColWidth {Short, Medium, Long}
    protected static class ColDef {
        public final String name;
        public final boolean isPercentage;
        public final int numFracDigits;
        public final ColWidth width;

        public ColDef(String name, boolean isPercentage, int numFracDigits, ColWidth width) {
            this.name = name;
            this.isPercentage = isPercentage;
            this.numFracDigits = numFracDigits;
            this.width = width;
        }
    }

    protected static class TreeNode {
        public final String identifier;
        public final boolean isSerial;
        public final long[] colDataRaw;
        public final List<TreeNode> children;

        public TreeNode(String identifier, boolean isSerial, long[] colDataRaw, List<TreeNode> children) {
            this.identifier = identifier;
            this.isSerial = isSerial;
            this.colDataRaw = colDataRaw;
            this.children = children;
        }
    }

    private void serveStaticResource(String resName, HttpServletResponse resp) throws IOException {
        if(resName.contains("..") || resName.contains("/")) {
            throw new IllegalArgumentException();
        }

        resp.addHeader("Cache-Control", "max-age=36000");

        final OutputStream out = resp.getOutputStream();
        final InputStream in = Thread.currentThread().getContextClassLoader().getResourceAsStream("asysmon-res/" + resName);

        final byte[] buf = new byte[4096];
        int numRead=0;
        while((numRead = in.read(buf)) > 0) {
            out.write(buf, 0, numRead);
        }
    }

    protected abstract String getTitle();

}
TOP

Related Classes of com.ajjpj.asysmon.datasink.aggregation.AbstractAsysmonReportServlet$TreeNode

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.