edu.fullerton.ldvw.LdvDispatcher.java Source code

Java tutorial

Introduction

Here is the source code for edu.fullerton.ldvw.LdvDispatcher.java

Source

/*
 * Copyright (C) 2012 Joseph Areeda<joseph.areeda@ligo.org>
 *
 * This program 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.
 *
 * 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, see <http://www.gnu.org/licenses/>.
 */
package edu.fullerton.ldvw;

import com.areeda.jaDatabaseSupport.Database;
import edu.fullerton.jspWebUtils.*;
import edu.fullerton.ldvjutils.ChanInfo;

import edu.fullerton.ldvjutils.LdvTableException;
import edu.fullerton.ldvjutils.TimeAndDate;
import edu.fullerton.ldvplugin.DBManager;
import edu.fullerton.ldvplugin.HelpManager;
import edu.fullerton.ldvservlet.ServletSupport;
import edu.fullerton.ldvtables.ChannelTable;
import edu.fullerton.ldvtables.ImageTable;
import edu.fullerton.ldvtables.ViewUser;
import edu.fullerton.viewerplugin.GUISupport;
import edu.fullerton.viewerplugin.GWpyInfo;
import java.io.IOException;
import java.sql.SQLException;
import java.util.HashSet;
import java.util.TreeSet;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import ndsmonitor.NdsMonitor;
import org.apache.commons.fileupload.servlet.ServletFileUpload;

/**
 *
 * @author Joseph Areeda<joseph.areeda@ligo.org>
    
*/
public class LdvDispatcher extends GUISupport {
    private final long startTime;
    private String mainHelpUrl;

    private HelpManager helpManager;
    private final HttpServletRequest request;
    private final HttpServletResponse response;
    private ServletSupport servletSupport;

    public LdvDispatcher(HttpServletRequest request, HttpServletResponse response, Database db, Page vpage,
            ViewUser vuser) {
        super(db, vpage, vuser);
        startTime = System.currentTimeMillis();
        setParamMap(request.getParameterMap());
        this.request = request;
        this.response = response;
    }

    public void setServletSupport(ServletSupport servletSupport) {
        this.servletSupport = servletSupport;
    }

    /**
     * Calls the appropriate module to handle the action requested by the user.
     * Note: most actions build the output in the vpage variable passed to pretty much everybody 
     *       However some module send data directly to the browser such as data or image downloads.
     *       That's what the return value specifies
     * @return true if our caller is responsible for sending html to the client.  False if we already did it
     * @throws WebUtilException we repackage any exceptions for consistent error handling.
     * @throws java.sql.SQLException
     * @throws edu.fullerton.ldvjutils.LdvTableException
     */
    public boolean dispatchCommand() throws WebUtilException, SQLException, LdvTableException {
        boolean ret = true;

        helpManager = new HelpManager(db, vpage, vuser);
        helpManager.setContextPath(contextPath);
        helpManager.setServletPath(servletPath);
        helpManager.setParamMap(paramMap);

        addNavBar();

        if (request.getMethod().equalsIgnoreCase("post") && ServletFileUpload.isMultipartContent(request)) {

        } else {
            String act;
            act = request.getParameter("act");
            act = act == null ? "basechan" : act;
            act = act.toLowerCase();
            switch (act) {
            case "basechan":
                baseChan();
                break;
            case "chanlist":
                chanList();
                break;
            case "channelstats":
                channelStats();
                break;
            case "contactus":
                contactForm();
                break;
            case "contactsubmit":
                sendRpt();
                break;
            case "dbstats":
                if (vuser.isAdmin()) {
                    dbStats();
                }
                break;
            case "defineplugin":
                definePlugin();
                break;
            case "doplot":
                ret = doPlot();
                break;
            case "edithelp":
                if (vuser.isAdmin()) {
                    ret = editHelp();
                }
                break;
            case "getimg":
                ret = getImg();
                break;
            case "getjson":
                ret = getJson();
                break;
            case "gwpy-info":
                ret = gwpyInfo();
                break;
            case "imagehistory":
                imageHistory();
                break;
            case "singlechan":
                singleChan();
                break;
            case "ndshistory":
                ndsHistory();
                break;
            case "ndsstatus":
                ndsStatus();
                break;
            case "procsrvfrm":
                if (vuser.isAdmin()) {
                    serverManager();
                }
                break;
            case "referenceplot":
                referencePlot();
                break;
            case "savehelptext":
                saveHelpText();
                break;
            case "servermanager":
                if (vuser.isAdmin()) {
                    serverManager();
                }
                break;
            case "specialplot":
                vpage.setTitle("Special Plots");
                PluginManager pmanage = new PluginManager(db, vpage, vuser, paramMap);
                pmanage.setContextPath(contextPath);
                pmanage.setServletPath(servletPath);
                ret = pmanage.specialPlot();
                break;
            case "stats":
                if (vuser.isAdmin()) {
                    userStats();
                }
                break;
            case "upload":
                uploadFiles();
                break;
            default:
                vpage.addLine(String.format("Unknow action requested: [%1$s]", act));
                break; // just in case somebody adds something after this
            }
        }
        return ret; // NB: ret is a boolean that says content is in vpage to be sent
        // otherwise we already sent a different mime type, like an image or pdf
    }

    /**
     * Add a table of links to our main pages.
     *
     * @param imgCnt total number of records in selection
     */
    private void addNavBar() throws WebUtilException {
        if (paramMap.get("embed") == null) {
            servletSupport.addNavBar();
        }
    }

    /**
     * An external request for a plot.  
     * Depending on how much information they provided, we will go to different places:
     * Nothing: main page
     * Channel name: if not unique select channels, else specify times
     * Add server: better chance of being unique
     * time, type of plot and unique channel display plot.
     */
    private void referencePlot() throws WebUtilException {
        try {
            String chanName = request.getParameter("channelName");
            String server = request.getParameter("server");
            String plot = request.getParameter("plot");
            String start = request.getParameter("start");
            String duration = request.getParameter("duration");
            if (server == null) {
                server = "";
            }

            vpage.setTitle("Reference Plot");

            if (chanName == null || chanName.isEmpty()) { // nothing specified means go to main page
                vpage.setTitle("Ligodv-web");

                PageItem hlpBtn = helpManager.getHelpButton("chanNameFilter");
                ChannelSelector cs = new ChannelSelector(request, response, db, vpage, vuser);
                cs.setServletPath(servletPath);
                PageForm chanSel = cs.addChanSelector(true, vuser.isAdmin(), hlpBtn);
                vpage.add(chanSel);
                vpage.add("Start by narrowing down the list of channels.");
            } else {
                ChannelSelector clf = new ChannelSelector(request, response, db, vpage, vuser);
                clf.setContextPath(contextPath);
                clf.setServletPath(servletPath);
                int nmatch = clf.getMatchCount("referenceplot");
                if (nmatch == 0) {
                    vpage.add("No channel matches specifier: " + chanName);
                    singleChan();
                } else {
                    ChannelTable ct = new ChannelTable(db);
                    TreeSet<ChanInfo> sel = ct.getAsSet(server, chanName, "raw", 1);
                    HashSet<Integer> selint = new HashSet<>();
                    for (ChanInfo ci : sel) {
                        Integer i = ci.getId();
                        selint.add(i);
                    }
                    if (nmatch > 1) { // non-unique channel specified go to channel selection
                        vpage.setTitle("liogdv-web - select channels");
                        PageItem hlpBtn = helpManager.getHelpButton("chanNameFilter");
                        ChannelSelector cs = new ChannelSelector(request, response, db, vpage, vuser);
                        cs.setServletPath(servletPath);
                        PageForm chanSel = cs.addChanSelector(false, vuser.isAdmin(), hlpBtn);
                        vpage.add(chanSel);
                        vpage.addBlankLines(2);
                        clf.doFormFilter("referencePlot");
                    } else {
                        // one and only one match let's see what else they specified

                        vpage.setTitle("ligodv-web - specify times");
                        TimeAndPlotSelector tps = new TimeAndPlotSelector(db, vpage, vuser);
                        tps.setContextPath(contextPath);
                        tps.setParamMap(paramMap);
                        tps.addSelections(selint);
                        tps.showForm("selchan");
                    }
                }
            }
        } catch (SQLException | LdvTableException | WebUtilException ex) {
            throw new WebUtilException("Reference plot", ex);
        }
    }

    /**
     * Channels have been selected individually, next step is time and plots
     * @throws WebUtilException 
     */
    private void specifyTimesAndPlots(String selType) throws WebUtilException {
        try {
            vpage.setTitle("LigoDV-web - Specify times");
            TimeAndPlotSelector tps = new TimeAndPlotSelector(db, vpage, vuser);
            tps.setParamMap(paramMap);
            tps.setContextPath(contextPath);
            tps.setServletPath(servletPath);
            tps.showForm(selType);
        } catch (SQLException | WebUtilException | LdvTableException ex) {
            throw new WebUtilException("Specify times", ex);
        }
    }

    private void definePlugin() throws WebUtilException {
        vpage.setTitle("Plugin Setup");
        PluginDescriptor pd = new PluginDescriptor(request, db, vpage, vuser);
        pd.makeNew();
    }

    /**
     * Process the plot request, generating as many images as necessary
     * @return true if output is to be sent by our caller, false if we already sent another mime type
     * @throws WebUtilException 
     */
    private boolean doPlot() throws WebUtilException {
        boolean ret = true;
        String isDownload = request.getParameter("download");

        if (request.getParameter("selMore") != null) {
            if (request.getParameter("baseSelector") != null) {
                try {
                    baseChan();
                } catch (SQLException ex) {
                    throw new WebUtilException("Attempting to select more base channels", ex);
                } catch (LdvTableException ex) {
                    Logger.getLogger(LdvDispatcher.class.getName()).log(Level.SEVERE, null, ex);
                }
            } else {
                ChannelSelector clf = new ChannelSelector(request, response, db, vpage, vuser);
                clf.setContextPath(contextPath);
                clf.setServletPath(servletPath);
                clf.selectChannels("selMore", false);
            }
        } else {
            if (isDownload == null) {
                vpage.setTitle("Ligodv-web results");
            } else {
                vpage.setTitle("Data download");
            }
            try {
                PluginManager pmanage = new PluginManager(db, vpage, vuser, paramMap);
                pmanage.setContextPath(contextPath);
                pmanage.setServletPath(servletPath);
                pmanage.setResponse(response);
                ret = pmanage.doPlots();
            } catch (SQLException | WebUtilException ex) {
                String ermsg = "Calling PluginManager to create plots or send other mime: "
                        + ex.getClass().getSimpleName() + " - " + ex.getLocalizedMessage();
                throw new WebUtilException(ermsg);
            }
        }
        return ret;
    }

    private boolean getImg() throws WebUtilException {
        boolean ret = true;
        try {
            String imgIdStr = request.getParameter("imgId");
            String widthStr = request.getParameter("width");
            int width = 0;
            if (widthStr != null && !widthStr.isEmpty()) {
                if (widthStr.matches("^\\d+$")) {
                    width = Integer.parseInt(widthStr);
                }
            }

            if (imgIdStr != null && !imgIdStr.isEmpty()) {
                if (imgIdStr.toLowerCase().matches("^\\d+$")) {
                    int imgId = Integer.parseInt(imgIdStr);
                    ImageTable itbl = new ImageTable(db);
                    itbl.sendImg(response, imgId, width);
                    ret = false;
                    Long timeMs = System.currentTimeMillis() - startTime;
                    vuser.logPage(String.format("Sent image #%1$d", imgId), itbl.getLastImageSize(),
                            timeMs.intValue());
                } else {
                    vpage.add("getImg has an invalid id.");
                }
            } else {
                vpage.add("getImg has no image id.");
            }
        } catch (NumberFormatException | SQLException | IOException ex) {
            throw new WebUtilException("Get saved image", ex);
        }
        return ret;
    }

    private void imageHistory() throws WebUtilException {
        try {
            vpage.setTitle("Image History");
            ImageHistory ih = new ImageHistory(request, response, db, vpage, vuser);
            ih.setContextPath(contextPath);
            ih.setServletPath(servletPath);
            ih.show();
        } catch (SQLException | WebUtilException | LdvTableException ex) {
            throw new WebUtilException("Display image history", ex);
        }
    }

    /**
     * Home page for the website
     * 
     * @throws WebUtilException probably a programming bug defining html
     */
    private void singleChan() throws WebUtilException, SQLException, LdvTableException {
        vpage.setTitle("Ligodv-web");

        PageItemString genPlotIntro = new PageItemString("Start by narrowing down the list of channels.  "
                + "All fields are optional but they speed the search and reduce the number of matches.  "
                + "Then hit then \"Retrieve Channel List\" button.<br/>", false);
        vpage.add(genPlotIntro);
        PageItem hlpBtn = helpManager.getHelpButton("chanNameFilter");

        vpage.addBlankLines(2);
        ChannelSelector cs = new ChannelSelector(request, response, db, vpage, vuser);
        cs.setServletPath(servletPath);
        PageForm chanSel = cs.addChanSelector(true, vuser.isAdmin(), hlpBtn);
        vpage.add(chanSel);
        vpage.addBlankLines(1);

        PageItemTextLink useBaseClass = new PageItemTextLink(servletPath + "?act=baseChan", "Use Base Channels");
        useBaseClass.setClassName("buttonLink");
        vpage.add(useBaseClass);
        vpage.addBlankLines(2);

        vpage.addHorizontalRule();

        //        PluginManager pmanage = new PluginManager( db, vpage, vuser, paramMap);
        //        pmanage.setContextPath(contextPath);
        //        pmanage.setServletPath(servletPath);
        //        pmanage.specialPlotSelector(vpage);
    }

    private void userStats() throws WebUtilException {
        vpage.setTitle("Stats");
        SiteStats ss = new SiteStats(request, db);
        String imgHistBaseUrl = getServletPath() + "?act=ImageHistory&amp;size=med&amp;usrSel=";
        vpage.add(ss.getStats(imgHistBaseUrl));
    }

    private void channelStats() throws WebUtilException {
        try {
            vpage.setTitle("LigoDv-web - Channel Table Stats");
            SiteStats ss = new SiteStats(request, db);
            vpage.add(ss.getChanStats());
        } catch (WebUtilException | SQLException ex) {
            throw new WebUtilException("Display stats page", ex);
        }

    }

    private void uploadFiles() throws WebUtilException {
        String submitAct = request.getParameter("submitAct");
        if (submitAct == null || !submitAct.equalsIgnoreCase("doupload")) {
            vpage.setTitle("LigoDV-web - Upload Image(s)");
            ImageUploader iu = new ImageUploader(db, vpage, vuser);
            iu.setServletPath(servletPath);
            iu.setContextPath(contextPath);
            iu.addForm();

        } else {

            vpage.setTitle("Image Upload Error");
            vpage.add("Old style uri used for upload images.");
        }
    }

    /**
     * Summarize the nds monitor stats
     * @throws WebUtilException error formatting results
     * @throws SQLException database problems
     */
    private void ndsStatus() throws WebUtilException, SQLException {
        vpage.setTitle("LigoDV-web - NDS Status");
        NdsMonitor nm = new NdsMonitor(db);
        nm.timeCounts();
        String sTitle = String.format("Status of NDS servers on %1$s UTC:", TimeAndDate.nowAsUtcString(0));
        PageItemString secTitle = new PageItemString(sTitle);
        secTitle.setId("secTitle");
        vpage.add(secTitle);
        vpage.addBlankLines(2);
        String baseUrl = "/viewer/?act=ndsHistory";
        vpage.add(nm.getStatsAsTable(baseUrl));
        vpage.addBlankLines(2);
        vpage.add(nm.getSummary());
    }

    private void ndsHistory() throws LdvTableException, WebUtilException {
        String site = request.getParameter("site");
        if (site == null || site.isEmpty()) {
            vpage.setTitle("LigoDV-web - NDS Stats request error");
            vpage.add("Invalid request to ndsHistory");
        } else {
            vpage.setTitle("LigoDV-web - NDS Server History");
            NdsMonitor nm = new NdsMonitor(db);
            vpage.add(nm.getHistory(site));
        }
    }

    /**
     * General routine to format something as JSON and return it
     * @return true if we are to display the error message in out page, false if json data is already sent
     */
    private boolean getJson() {
        boolean ret = false;

        AjaxHelper ah = new AjaxHelper();
        String ermsg = ah.processRequest(request, response);
        if (!ermsg.isEmpty()) {
            vpage.add("Error: " + ermsg);
            ret = true;
        }
        return ret;
    }

    /**
     * Present a bug report form
     */
    private void contactForm() throws WebUtilException {
        BugReportForm brf = new BugReportForm(db, vpage, vuser, request);
        brf.setServletPath(servletPath);
        brf.addForm();
    }

    /**
     * Add their bug report to the ticket system
     */
    private void sendRpt() throws WebUtilException {
        BugReportForm brf = new BugReportForm(db, vpage, vuser, request);
        brf.setServletPath(servletPath);
        brf.sendRpt();
    }

    /**
     * Add new or edit existing help text
     * @return flag to send created page 
     * @throws WebUtilException 
     */
    private boolean editHelp() throws WebUtilException, LdvTableException {
        vpage.setTitle("Help Text Editor");
        helpManager.editHelp();

        return true;
    }

    private void saveHelpText() throws WebUtilException {
        vpage.setTitle("Help Text Editor");
        try {
            String saveit = request.getParameter("save");
            if (saveit != null) {
                helpManager.saveHelpText();
                editHelp();
            } else {
                helpManager.editHelp(request.getParameter("helpName"));
            }
        } catch (WebUtilException | LdvTableException ex) {
            throw new WebUtilException("SaveHelpText command", ex);
        }

    }

    private void dbStats() throws WebUtilException {
        vpage.setTitle("Database statistic");
        DBManager dbm = new DBManager(db, request, vpage, vuser);
        dbm.addStats();
    }

    /**
     * handle V2 of the channel filter/selection process
     */
    private void baseChan() throws WebUtilException, SQLException, LdvTableException {
        BaseChannelSelector bsc = new BaseChannelSelector(db, vpage, vuser, contextPath);
        bsc.setServletPath(servletPath);
        bsc.setParamMap(paramMap);
        String submitAct = getParameter("submitAct");
        if (submitAct == null || submitAct.isEmpty()) {
            submitAct = getParameter("submit");
        }
        submitAct = submitAct == null ? "" : submitAct;

        if (submitAct.isEmpty()) {
            vpage.setTitle("LigoDV-web base channel selection");

            // Give them a hint what to do.
            PageItemList intro = new PageItemList();
            intro.setClassName("processStep");
            intro.add("Use the optional fields below to narrow down the list of base channels ");
            PageItem hlpBtn = helpManager.getHelpButton("baseChan");
            intro.add(hlpBtn);
            intro.add(", ");
            intro.addBlankLines(1);
            intro.add("then hit the Retrieve Channel List button.");
            intro.addBlankLines(2);
            vpage.add(intro);

            PageForm chanSel = bsc.addSelector(true);
            vpage.add(chanSel);
            vpage.addBlankLines(1);
            vpage.add("If you prefer the old way, click ");

            PageItemTextLink singleChan = new PageItemTextLink(servletPath + "?act=singlechan", "here.");
            vpage.add(singleChan);
            vpage.addBlankLines(2);
        } else if (submitAct.toLowerCase().contains("retrieve")) {
            vpage.setTitle("LigoDV-web Select Base Channels");
            PageForm chanSel = bsc.addSelector(false);
            vpage.add(chanSel);
            vpage.addBlankLines(1);

            bsc.processFilterRequest();
        } else if (submitAct.toLowerCase().contains("continue")) {
            specifyTimesAndPlots("selbchan");
        } else {
            vpage.setTitle("LigoDV-web select  base channels");
            bsc.processFilterRequest();
        }

    }

    /**
     * Individual channel selection (v1)
     * submitAct = null or "" -> specify channels 
     * submitAct = "continue" -> pass selected channels to select times and plots.
     * @throws WebUtilException 
     */
    private void chanList() throws WebUtilException {
        String submitAct = request.getParameter("submitAct");
        submitAct = submitAct == null ? "" : submitAct;

        if (submitAct.toLowerCase().contains("continue")) {
            specifyTimesAndPlots("selchan");
        } else {
            ChannelSelector clf = new ChannelSelector(request, response, db, vpage, vuser);
            clf.setContextPath(contextPath);
            clf.setServletPath(servletPath);
            clf.selectChannels(submitAct, false);
        }
    }

    /**
     * The main help URL is part of the global configuration.
     * We put it on our nav bar.
     * 
     * @param helpUrl - usually the full URL to a wiki page
     */
    void setMainHelp(String helpUrl) {
        mainHelpUrl = helpUrl;
    }

    private void serverManager() throws LdvTableException, WebUtilException {
        vpage.setTitle("NDS Server Manager");
        ServerManager sm = new ServerManager(db, vpage, vuser);
        sm.setServletPath(servletPath);
        sm.setContextPath(contextPath);
        sm.setParamMap(paramMap);

        String[] submitActs = paramMap.get("submit");
        String submitAct = submitActs == null || submitActs.length == 0 ? "" : submitActs[0];
        if (submitAct == null || submitAct.isEmpty()) {
            sm.showForm();
        } else {
            sm.procForm();
            sm.showForm();
        }
    }

    private boolean gwpyInfo() throws WebUtilException {
        vpage.addLine("Current GWpy software:");
        vpage.addBlankLines(2);
        GWpyInfo gwpi = new GWpyInfo();
        String gwInfo = gwpi.getGwStatus();
        PageItemString pis = new PageItemString(gwInfo, false);
        vpage.add(pis);
        vpage.addBlankLines(2);
        return true;
    }

}