gsn.http.DataDownload.java Source code

Java tutorial

Introduction

Here is the source code for gsn.http.DataDownload.java

Source

/**
* Global Sensor Networks (GSN) Source Code
* Copyright (c) 2006-2014, Ecole Polytechnique Federale de Lausanne (EPFL)
* 
* This file is part of GSN.
* 
* GSN 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.
* 
* GSN 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 GSN.  If not, see <http://www.gnu.org/licenses/>.
* 
* File: src/gsn/http/DataDownload.java
*
* @author Ali Salehi
* @author Timotee Maret
* @author Sofiane Sarni
* @author Milos Stojanovic
*
*/

package gsn.http;

import gsn.Main;
import gsn.Mappings;
import gsn.beans.DataField;
import gsn.beans.StreamElement;
import gsn.beans.VSensorConfig;
import gsn.http.ac.DataSource;
import gsn.http.ac.User;
import gsn.http.ac.UserUtils;
import gsn.storage.DataEnumerator;

import java.io.PrintWriter;
import java.sql.SQLException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.*;

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

import org.apache.commons.collections.KeyValue;
import org.apache.commons.lang.StringEscapeUtils;
import org.slf4j.LoggerFactory;
import org.slf4j.Logger;

public class DataDownload extends HttpServlet {

    private static transient Logger logger = LoggerFactory.getLogger(DataDownload.class);

    public void doGet(HttpServletRequest req, HttpServletResponse res)
            throws ServletException, java.io.IOException {
        doPost(req, res);
    }

    /**
     * List of the parameters for the requests:
     * url : /data
     * Example: Getting all the data in CSV format => http://localhost:22001/data?vsName=memoryusage4&fields=heap&display=CSV
     * another example: http://localhost:22001/data?vsName=memoryusage4&fields=heap&fields=timed&display=CSV&delimiter=other&otherdelimiter=,
     * <p/>
     * param-name: vsName : the name of the virtual sensor we need.
     * param-name: fields [there can be multiple parameters with this name pointing to different fields in the stream element].
     * param-name: commonReq (always true !)
     * param-name: display , if there is a value it should be CSV.
     * param-name: delimiter, useful for CSV output (can be "tab","space","other")
     * param-name: otherdelimiter useful in the case of having delimiter=other
     * param-name: groupby can point to one of the fields in the stream element. In case groupby=timed then the parameter groupbytimed points to the period for which data should be aggregated [in milliseconds].
     * param-name: nb give the maximum number of elements to be outputed (most recent values first).
     * param-name:
     */
    public void doPost(HttpServletRequest req, HttpServletResponse res)
            throws ServletException, java.io.IOException {

        //
        HttpSession session = req.getSession();
        User user = (User) session.getAttribute("user");

        res.setHeader("Cache-Control", "no-store");
        res.setDateHeader("Expires", 0);
        res.setHeader("Pragma", "no-cache");
        //

        PrintWriter respond = res.getWriter();
        DataEnumerator result = null;
        try {
            SimpleDateFormat sdf = new SimpleDateFormat(Main.getInstance().getContainerConfig().getTimeFormat());
            SimpleDateFormat sdf_from_ui = new SimpleDateFormat("dd/MM/yyyy HH:mm:ss");
            TimeZone timeZone = GregorianCalendar.getInstance().getTimeZone();
            boolean responseCVS = false;
            boolean wantTimeStamp = false;
            boolean wantPk = false;
            boolean commonReq = true;
            boolean groupByTimed = false;

            String vsName = HttpRequestUtils.getStringParameter("vsName", null, req);
            if (vsName == null)
                vsName = HttpRequestUtils.getStringParameter("vsname", null, req);
            if (vsName == null) {
                res.sendError(WebConstants.MISSING_VSNAME_ERROR, "The virtual sensor name is missing");
                return;
            }

            DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd_HH-mm-ss");
            Date currentDate = Calendar.getInstance().getTime();
            String filename = vsName + "_" + dateFormat.format(currentDate);

            if (Main.getContainerConfig().isAcEnabled() == true) {
                if (user != null) // meaning, that a login session is active, otherwise we couldn't get there
                    if (user.hasReadAccessRight(vsName) == false && user.isAdmin() == false) // ACCESS_DENIED
                    {
                        res.sendError(WebConstants.ACCESS_DENIED,
                                "Access denied to the specified virtual sensor .");
                        return;
                    }
            }

            if (req.getParameter("display") != null && req.getParameter("display").equals("CSV")) {
                responseCVS = true;
                res.setContentType("text/csv");
                //res.setContentType("text/html");
            } else {
                res.setContentType("text/xml");
            }
            if (req.getParameter("commonReq") != null && req.getParameter("commonReq").equals("false")) {
                commonReq = false;
            }
            String separator = ";";
            if (req.getParameter("delimiter") != null && !req.getParameter("delimiter").equals("")) {
                String reqSeparator = req.getParameter("delimiter");
                if (reqSeparator.equals("tab")) {
                    separator = "\t";
                } else if (reqSeparator.equals("space")) {
                    separator = " ";
                } else if (reqSeparator.equals("other") && req.getParameter("otherdelimiter") != null
                        && !req.getParameter("otherdelimiter").equals("")) {
                    separator = req.getParameter("otherdelimiter");
                }
            }
            String generated_request_query = "";
            String expression = "";
            String line = "";
            String groupby = "";
            String[] fields = req.getParameterValues("fields");
            if (commonReq) {
                if (req.getParameter("fields") != null) {
                    for (int i = 0; i < fields.length; i++) {
                        if (fields[i].equals("timed")) {
                            wantTimeStamp = true;
                        }
                        if ("pk".equalsIgnoreCase(fields[i]))
                            wantPk = true;
                        generated_request_query += ", " + fields[i];
                    }
                    if (!wantPk)
                        generated_request_query += ", pk";
                }
            } else {
                if (req.getParameter("fields") == null) {
                    respond.println("Request ERROR");
                    return;
                } else {
                    for (int i = 0; i < fields.length; i++) {
                        if (fields[i].equals("timed")) {
                            wantTimeStamp = true;
                        }
                        if ("pk".equalsIgnoreCase(fields[i]))
                            wantPk = true;
                        generated_request_query += ", " + fields[i];
                    }
                    if (!wantPk)
                        generated_request_query += ", pk";
                }
                if (req.getParameter("groupby") != null) {
                    if (req.getParameter("groupby").equals("timed")) {
                        groupByTimed = true;
                        int periodmeasure = 1;
                        if (req.getParameter("groupbytimed") != null) {
                            periodmeasure = new Integer(req.getParameter("groupbytimed"));
                            periodmeasure = java.lang.Math.max(periodmeasure, 1);
                        }
                        generated_request_query += ", Min(timed), FLOOR(timed/" + periodmeasure + ") period ";
                        groupby = "GROUP BY period";
                    } else {
                        groupby = "GROUP BY " + req.getParameter("groupby");
                    }
                }
            }

            String where = "";
            if (req.getParameter("critfield") != null) {
                try {
                    String[] critJoin = req.getParameterValues("critJoin");
                    String[] neg = req.getParameterValues("neg");
                    String[] critfields = req.getParameterValues("critfield");
                    String[] critop = req.getParameterValues("critop");
                    String[] critval = req.getParameterValues("critval");
                    for (int i = 0; i < critfields.length; i++) {
                        if (critop[i].equals("LIKE")) {
                            if (i > 0) {
                                where += " " + critJoin[i - 1] + " " + neg[i] + " " + critfields[i] + " LIKE '%"; // + critval[i] + "%'";
                            } else {
                                where += neg[i] + " " + critfields[i] + " LIKE '%"; // + critval[i] + "%'";
                            }
                            if (critfields[i].equals("timed")) {
                                try {
                                    //Date d = sdf.parse(critval[i]);
                                    Date d = sdf_from_ui.parse(critval[i]);
                                    where += d.getTime();
                                } catch (Exception e) {
                                    where += "0";
                                }
                            } else {
                                where += critval[i];
                            }
                            where += "%'";
                        } else {
                            if (i > 0) {
                                where += " " + critJoin[i - 1] + " " + neg[i] + " " + critfields[i] + " "
                                        + critop[i] + " "; //critval[i];
                            } else {
                                where += neg[i] + " " + critfields[i] + " " + critop[i] + " "; //critval[i];
                            }
                            if (critfields[i].equals("timed")) {
                                try {
                                    //Date d = sdf.parse(critval[i]);
                                    Date d = sdf_from_ui.parse(critval[i]);
                                    where += d.getTime();
                                } catch (Exception e) {
                                    where += "0";
                                }
                            } else {
                                where += critval[i];
                            }
                        }
                    }
                    where = " WHERE " + where;
                } catch (NullPointerException npe) {
                    where = " ";
                }
            }

            if (!generated_request_query.equals("")) {
                generated_request_query = generated_request_query.substring(2);
                if (!commonReq) {
                    expression = generated_request_query;
                }
                generated_request_query = "select " + generated_request_query + " from " + vsName + where
                        + "  order by timed DESC  ";
                if (commonReq)
                    if (req.getParameter("nb") != null && req.getParameter("nb") != "") {
                        int nb = new Integer(req.getParameter("nb"));
                        if (nb < 0)
                            nb = 0;
                        String limit = "";
                        if (Main.getStorage(vsName).isH2() || Main.getStorage(vsName).isMysqlDB()) {
                            if (nb >= 0)
                                limit = "LIMIT " + nb + "  offset 0";
                            generated_request_query += limit;
                        } else if (Main.getStorage(vsName).isOracle()) {
                            generated_request_query = "select * from (" + generated_request_query
                                    + " ) where rownum <" + (nb + 1);
                        }
                    }

                generated_request_query += " " + groupby;
                generated_request_query += ";";

                if (req.getParameter("sql") != null) {
                    res.setContentType("text/html");
                    respond.println("# " + generated_request_query);
                    return;
                }

                try {
                    result = Main.getStorage(vsName).streamedExecuteQuery(generated_request_query, true);
                } catch (SQLException e) {
                    logger.error("ERROR IN EXECUTING, query: " + generated_request_query + " from "
                            + req.getRemoteAddr() + "- " + req.getRemoteHost() + ": " + e.getMessage());
                    return;
                }
                if (!result.hasMoreElements()) {
                    res.setContentType("text/html");
                    respond.println("No data corresponds to your request");
                    return;
                }

                //get units in hash map
                Iterator<VSensorConfig> vsIterator = Mappings.getAllVSensorConfigs();
                HashMap<String, String> fieldToUnitMap = new HashMap<String, String>();
                VSensorConfig sensorConfig = null;
                while (vsIterator.hasNext()) {
                    VSensorConfig senConfig = vsIterator.next();
                    if (vsName.equalsIgnoreCase(senConfig.getName())) {
                        sensorConfig = senConfig;
                        DataField[] dataFieldArray = senConfig.getOutputStructure();
                        for (DataField df : dataFieldArray) {
                            String unit = df.getUnit();
                            if (unit == null || unit.trim().length() == 0)
                                unit = "";

                            fieldToUnitMap.put(df.getName().toLowerCase(), unit);
                        }
                        break;
                    }
                }

                line = "";
                int nbFields = 0;
                if (responseCVS) {
                    boolean firstLine = true;
                    res.setHeader("content-disposition", "attachment; filename=" + filename + ".csv");
                    respond.println("# " + generated_request_query);
                    for (KeyValue df : sensorConfig.getAddressing()) {
                        respond.println(
                                "# " + df.getKey().toString().toLowerCase() + ":" + df.getValue().toString());
                    }
                    respond.println("# description:" + sensorConfig.getDescription());
                    LinkedList<StreamElement> streamElements = new LinkedList<StreamElement>();
                    while (result.hasMoreElements()) {
                        streamElements.add(result.nextElement());
                    }
                    while (!streamElements.isEmpty()) {
                        StreamElement se = streamElements.removeLast();
                        if (firstLine) {
                            nbFields = se.getFieldNames().length;
                            if (groupByTimed) {
                                nbFields--;
                            }
                            if (wantTimeStamp) {
                                line += separator + "time";
                            }
                            for (int i = 0; i < nbFields; i++)
                                //line += delimiter + se.getFieldNames()[i].toString();
                                if ((!groupByTimed) || (i != fields.length)) {
                                    line += separator + fields[i];
                                } else {
                                    line += separator + "time";
                                }

                            firstLine = false;
                            respond.println(line.substring(separator.length()));

                            line = "";

                            //units (second line)
                            if (wantTimeStamp) {
                                line += separator + "";
                            }
                            for (int i = 0; i < nbFields; i++) {
                                if ((!groupByTimed) || (i != fields.length)) {
                                    line += separator + fieldToUnitMap.get(fields[i].toLowerCase());
                                } else {
                                    line += separator + "";
                                }
                            }
                            respond.println(line.substring(separator.length()));
                        }

                        line = "";
                        if (wantTimeStamp) {
                            Date d = new Date(se.getTimeStamp());
                            line += separator + sdf.format(d);
                        }
                        for (int i = 0; i < nbFields; i++)
                            //line += delimiter+se.getData( )[ i ].toString( );

                            if (!commonReq && ((i >= fields.length) || (fields[i].contains("timed")))) {
                                line += separator + sdf.format(se.getData()[i]);
                            } else {
                                line += separator + se.getData()[i].toString();
                            }
                        respond.println(line.substring(separator.length()));
                    }
                } else {
                    boolean firstLine = true;
                    res.setHeader("content-disposition", "attachment; filename=" + filename + ".xml");
                    for (KeyValue df : sensorConfig.getAddressing()) {
                        respond.println(
                                "\t<!-- " + StringEscapeUtils.escapeXml(df.getKey().toString().toLowerCase()) + ":"
                                        + StringEscapeUtils.escapeXml(df.getValue().toString()) + " -->");
                    }
                    respond.println("\t<!-- description:"
                            + StringEscapeUtils.escapeXml(sensorConfig.getDescription()) + " -->");
                    respond.println("<data>");
                    LinkedList<StreamElement> streamElements = new LinkedList<StreamElement>();
                    while (result.hasMoreElements()) {
                        streamElements.add(result.nextElement());
                    }
                    while (!streamElements.isEmpty()) {
                        StreamElement se = streamElements.removeLast();
                        if (firstLine) {
                            respond.println("\t<line>");
                            nbFields = se.getFieldNames().length;
                            if (groupByTimed) {
                                nbFields--;
                            }
                            if (wantTimeStamp) {
                                respond.println("\t\t<field unit=\"\">time</field>");
                            }
                            for (int i = 0; i < nbFields; i++) {
                                if ((!groupByTimed) || (i != fields.length)) {
                                    respond.print(
                                            "\t\t<field unit=\"" + fieldToUnitMap.get(fields[i].toLowerCase()));
                                    respond.println("\">" + fields[i] + "</field>");
                                } else {
                                    respond.println("\t\t<field unit=\"\">time</field>");
                                }
                            }
                            //} else {
                            //    out.println("\t\t<field>"+expression+"</field>");
                            //}
                            respond.println("\t</line>");
                            firstLine = false;
                        }
                        line = "";
                        respond.println("\t<line>");
                        if (wantTimeStamp) {
                            Date d = new Date(se.getTimeStamp());
                            respond.println("\t\t<field>" + sdf.format(d) + "</field>");
                        }
                        for (int i = 0; i < nbFields; i++) {

                            //if ( !commonReq && expression.contains("timed")) {
                            if (!commonReq && ((i >= fields.length) || (fields[i].contains("timed")))) {
                                respond.println("\t\t<field>" + sdf.format(se.getData()[i]) + "</field>");
                            } else {
                                if (se.getData()[i] == null)
                                    respond.println("\t\t<field>Null</field>");
                                else
                                    respond.println("\t\t<field>" + se.getData()[i].toString() + "</field>");
                            }
                        }
                        respond.println("\t</line>");
                    }
                    respond.println("</data>");
                }
            }
            //*/
            else {
                res.setContentType("text/html");
                respond.println("Please select some fields");
            }
        } finally {
            if (result != null)
                result.close();
            respond.flush();
        }
    }
}