/** * Copyright (c) 2011-2014, OpenIoT * * This file is part of OpenIoT. * * OpenIoT is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, version 3 of the License. * * OpenIoT 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with OpenIoT. If not, see <http://www.gnu.org/licenses/>. * * Contact: OpenIoT mailto: info@openiot.eu * @author Ali Salehi * @author Timotee Maret * @author Sofiane Sarni * @author Milos Stojanovic */ package org.openiot.gsn.http; import org.openiot.gsn.Main; import org.openiot.gsn.beans.StreamElement; import org.openiot.gsn.http.ac.User; import org.openiot.gsn.storage.DataEnumerator; import java.io.PrintWriter; import java.sql.SQLException; import java.text.SimpleDateFormat; import java.util.Date; import java.util.GregorianCalendar; import java.util.TimeZone; 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.log4j.Logger; public class DataDownload extends HttpServlet { private static transient Logger logger = Logger.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; } 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); logger.error(e.getMessage(), e); logger.error("Query is from " + req.getRemoteAddr() + "- " + req.getRemoteHost()); return; } if (!result.hasMoreElements()) { res.setContentType("text/html"); respond.println("No data corresponds to your request"); return; } line = ""; int nbFields = 0; if (responseCVS) { boolean firstLine = true; respond.println("#" + generated_request_query); while (result.hasMoreElements()) { StreamElement se = result.nextElement(); if (firstLine) { nbFields = se.getFieldNames().length; if (groupByTimed) { nbFields--; } 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 + "timed"; } if (wantTimeStamp) { line += separator + "timed"; } firstLine = false; } respond.println(line.substring(separator.length())); line = ""; 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(); } if (wantTimeStamp) { Date d = new Date(se.getTimeStamp()); line += separator + sdf.format(d); } respond.println(line.substring(separator.length())); } } else { boolean firstLine = true; respond.println("<data>"); while (result.hasMoreElements()) { StreamElement se = result.nextElement(); if (firstLine) { respond.println("\t<line>"); nbFields = se.getFieldNames().length; if (groupByTimed) { nbFields--; } for (int i = 0; i < nbFields; i++) //if (commonReq) { //out.println("\t\t<field>" + se.getFieldNames()[i].toString()+"</field>"); if ((!groupByTimed) || (i != fields.length)) { respond.println("\t\t<field>" + fields[i] + "</field>"); } else { respond.println("\t\t<field>timed</field>"); } //} else { // out.println("\t\t<field>"+expression+"</field>"); //} if (wantTimeStamp) { respond.println("\t\t<field>timed</field>"); } respond.println("\t</line>"); firstLine = false; } line = ""; respond.println("\t<line>"); 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>"); } } if (wantTimeStamp) { Date d = new Date(se.getTimeStamp()); respond.println("\t\t<field>" + sdf.format(d) + "</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(); } } }