/** * 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 charliend * @author Ali Salehi * @author Timotee Maret * @author Milos Stojanovic */ package org.openiot.gsn.http; import org.openiot.gsn.Main; import org.openiot.gsn.Mappings; import org.openiot.gsn.beans.DataField; import org.openiot.gsn.beans.VSensorConfig; import org.openiot.gsn.http.ac.DataSource; import org.openiot.gsn.http.ac.User; import org.openiot.gsn.http.datarequest.DataRequestException; import org.openiot.gsn.http.datarequest.DownloadReport; import java.io.IOException; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; import java.util.Hashtable; import java.util.Iterator; import java.util.Map; import java.util.Set; import java.util.Map.Entry; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import org.openiot.gsn.http.datarequest.QueriesBuilder; import org.apache.log4j.Logger; /** * */ public class MultiDataDownload extends HttpServlet { private static final long serialVersionUID = 4249739276150343437L; private static transient Logger logger = Logger.getLogger(MultiDataDownload.class); public void doGet(HttpServletRequest req, HttpServletResponse res) throws IOException { doPost(req, res); } public void doPost(HttpServletRequest req, HttpServletResponse res) throws 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"); // SimpleDateFormat sdfWeb = new SimpleDateFormat ("dd/MM/yyyy HH:mm:ss") ; // 29/10/2008 22:25:07 try { logger.debug("Query string: " + req.getQueryString()); String downloadFormat = req.getParameter("download_format") == null ? "csv" : req.getParameter("download_format"); String downloadMode = req.getParameter("download_mode") == null ? "attachement" : req.getParameter("download_mode"); Map<String, String[]> parameterMap = parseParameters(req, downloadFormat, sdfWeb); if ("csv".equals(downloadFormat)) { org.openiot.gsn.http.datarequest.DownloadData dd = new org.openiot.gsn.http.datarequest.DownloadData(parameterMap); // if (Main.getContainerConfig().isAcEnabled()) { ArrayList<String> noAccess = checkAccessControl(user, dd.getQueryBuilder()); if (noAccess != null && noAccess.size() > 0) { res.sendError(WebConstants.ACCESS_DENIED, "Access Control failed for vsNames:" + noAccess + " and user: " + (user == null ? "not logged in" : user.getUserName())); return; } } // dd.process(); if (! "inline".equals(downloadMode)) { res.setContentType("application/x-download"); res.setHeader("content-disposition","attachment; filename=data.csv"); } else res.setContentType("text"); dd.outputResult(res.getOutputStream()); //res.getOutputStream().flush(); } else if ("xml".equals(downloadFormat)) { org.openiot.gsn.http.datarequest.DownloadData dd = new org.openiot.gsn.http.datarequest.DownloadData(parameterMap); // if (Main.getContainerConfig().isAcEnabled()) { ArrayList<String> noAccess = checkAccessControl(user, dd.getQueryBuilder()); if (noAccess != null && noAccess.size() > 0) { res.sendError(WebConstants.ACCESS_DENIED, "Access Control failed for vsNames:" + noAccess + " and user: " + (user == null ? "not logged in" : user.getUserName())); return; } } // dd.process(); res.setContentType("text/xml"); if (! "inline".equals(downloadMode)) res.setHeader("content-disposition","attachment; filename=data.xml"); dd.outputResult(res.getOutputStream()); //res.getOutputStream().flush(); } else if ("pdf".equals(downloadFormat)) { DownloadReport rpd = new DownloadReport (parameterMap) ; // if (Main.getContainerConfig().isAcEnabled()) { ArrayList<String> noAccess = checkAccessControl(user, rpd.getQueryBuilder()); if (noAccess != null && noAccess.size() > 0) { res.sendError(WebConstants.ACCESS_DENIED, "Access Control failed for vsNames:" + noAccess + " and user: " + (user == null ? "not logged in" : user.getUserName())); return; } } // rpd.process(); res.setContentType("application/pdf"); res.setHeader("content-disposition","attachment; filename=data.pdf"); rpd.outputResult(res.getOutputStream()); res.getOutputStream().flush(); } else { throw new DataRequestException("Unknown download_format >" + downloadFormat + "<"); } } catch (DataRequestException e) { logger.error(e.getMessage()); res.sendError(WebConstants.ERROR_INVALID_VSNAME, e.getMessage()); return; } } public ArrayList<String> checkAccessControl (User user, QueriesBuilder qbuilder) { if(Main.getContainerConfig().isAcEnabled()){ ArrayList<String> noAccess = new ArrayList<String>(); for (String vsname : qbuilder.getSqlQueries().keySet()) { if (DataSource.isVSManaged(vsname)) { if ( (user == null || (! user.isAdmin() && ! user.hasReadAccessRight(vsname)))) { noAccess.add(vsname); } } } return noAccess; } return null; } private Map<String, String[]> parseParameters (HttpServletRequest req, String downloadFormat, SimpleDateFormat sdfWeb) { Map<String, String[]> parameterMap = new Hashtable<String, String[]>(); Hashtable<String, ArrayList<String>> vssfm = buildVirtualSensorsFieldsMapping(req.getParameterMap()); // VS Iterator<Entry <String, ArrayList<String>>> vsAndFields = vssfm.entrySet().iterator(); Iterator<String> fieldsIterator; Entry<String, ArrayList<String>> vsAndFieldsEntry; StringBuilder vsname ; ArrayList<String> vsnames = new ArrayList<String> () ; while (vsAndFields.hasNext()) { vsAndFieldsEntry = vsAndFields.next(); vsname = new StringBuilder(); vsname.append(vsAndFieldsEntry.getKey()); fieldsIterator = vsAndFieldsEntry.getValue().iterator(); boolean hasPk = false; while (fieldsIterator.hasNext()) { vsname.append(":"); String n = fieldsIterator.next(); vsname.append(n); if ("pk".equalsIgnoreCase(n)) hasPk = true; } if (! hasPk) vsname.append(":pk"); vsnames.add(vsname.toString()); } parameterMap.put("vsname", vsnames.toArray(new String[] {})); // TIME FORMAT String req_time_format = req.getParameter("time_format"); if (req_time_format != null) { parameterMap.put("timeformat", new String[] {req_time_format}); } // Download format parameterMap.put("outputtype", new String[] { downloadFormat }); // CRITFIELDS // TIME LIMITS ArrayList<String> critFields = new ArrayList<String> () ; String req_from = req.getParameter("from"); String req_to = req.getParameter("to"); Date timeLimit; try { if (req_from != null) { timeLimit = sdfWeb.parse(req_from); vsAndFields = vssfm.entrySet().iterator(); while (vsAndFields.hasNext()) { vsAndFieldsEntry = vsAndFields.next(); critFields.add("and::" + vsAndFieldsEntry.getKey() + ":timed:ge:" + timeLimit.getTime()); } } } catch (ParseException e1) { logger.debug(e1.getMessage()); } try { if (req_to != null) { timeLimit = sdfWeb.parse(req_to); vsAndFields = vssfm.entrySet().iterator(); while (vsAndFields.hasNext()) { vsAndFieldsEntry = vsAndFields.next(); critFields.add("and::" + vsAndFieldsEntry.getKey() + ":timed:leq:" + timeLimit.getTime()); } } } catch (ParseException e1) { logger.debug(e1.getMessage()); } // CONDITIONS Hashtable<String, String> cVss = buildWebParameterMapping("c_vs[", req.getParameterMap()); Hashtable<String, String> cJoins = buildWebParameterMapping("c_join[", req.getParameterMap()); Hashtable<String, String> cFields = buildWebParameterMapping("c_field[", req.getParameterMap()); Hashtable<String, String> cMins = buildWebParameterMapping("c_min[", req.getParameterMap()); Hashtable<String, String> cMaxs = buildWebParameterMapping("c_max[", req.getParameterMap()); Iterator<Entry <String, String>> iter = cJoins.entrySet().iterator(); Entry<String, String> entry; while (iter.hasNext()) { entry = iter.next(); String cField = cFields.get(entry.getKey()); String cVs = cVss.get(entry.getKey()); String cJoin = cJoins.get(entry.getKey()); String cMin = cMins.get(entry.getKey()); String cMax = cMaxs.get(entry.getKey()); // VS and Fields Hashtable<String, ArrayList<String>> vsAndFieldSelected = new Hashtable<String, ArrayList<String>> (); if (cVs.compareToIgnoreCase("All") == 0) { if (cField.compareToIgnoreCase("All") == 0) { vsAndFieldSelected = vssfm; } else { vsAndFieldSelected = (Hashtable<String, ArrayList<String>>) vssfm.clone(); ArrayList<String> toRetain = new ArrayList<String> () ; toRetain.add(cField); vsAndFieldSelected.values().retainAll(toRetain); } } else { if (cField.compareToIgnoreCase("All") == 0) { vsAndFieldSelected.put(cVs, vssfm.get(cVs)); } else { ArrayList<String> tmp = new ArrayList<String> () ; tmp.add(cField); vsAndFieldSelected.put(cVs, tmp); } } Iterator<Entry <String,ArrayList<String>>> vsAndFieldsIterator = vsAndFieldSelected.entrySet().iterator(); Iterator<String> fieldIterator; Entry<String, ArrayList<String>> entry2 ; String fieldName; String vsName; while (vsAndFieldsIterator.hasNext()) { entry2 = vsAndFieldsIterator.next(); fieldIterator = entry2.getValue().iterator(); while (fieldIterator.hasNext()) { vsName = entry2.getKey(); fieldName = fieldIterator.next(); // Mins if (cMin.compareToIgnoreCase("-inf") != 0) { //criteria.add(cjoins[i] + "::" + vsnames[j] + ":" + cfields[i] + ":ge:" + cmins[i]); critFields.add(cJoin + "::" + vsName + ":" + fieldName + ":ge:" + cMin); } // Maxs if (cMax.compareToIgnoreCase("+inf") != 0) { critFields.add(cJoin + "::" + vsName + ":" + fieldName + ":leq:" + cMax); } } } } // parameterMap.put("critfield", critFields.toArray(new String[] {})); // NB String req_nb = req.getParameter("nb"); if (req_nb != null) { if (req_nb.compareToIgnoreCase("SPECIFIED") == 0) { String req_nb_value = req.getParameter("nb_value"); try { Integer checked_nb = Integer.parseInt(req_nb_value); parameterMap.put("nb", new String[] { "0:" + checked_nb }); } catch (NumberFormatException e1) { logger.debug("The specified nb of data >" + req_nb_value + "< is not a number."); } } } // AGGREGATION String req_agg_function = req.getParameter("agg_function"); if (req_agg_function != null && req_agg_function.compareToIgnoreCase("-1") != 0) { String req_agg_period = req.getParameter("agg_period"); String req_agg_unit = req.getParameter("agg_unit"); try { long timerange = Long.parseLong(req_agg_unit) * Long.parseLong(req_agg_period); parameterMap.put("groupby", new String[] { timerange + ":" + req_agg_function }); } catch (NumberFormatException e2) { logger.debug(e2); } } // REPORT TEMPLATE String req_reportclass = req.getParameter("reportclass"); if (req_reportclass != null) { parameterMap.put("reportclass", new String[] { req_reportclass }); } return parameterMap; } private Hashtable<String, ArrayList<String>> buildVirtualSensorsFieldsMapping (Map<String, String[]> pm) { Hashtable<String, ArrayList<String>> vssfm = new Hashtable<String, ArrayList<String>> () ; // Hashtable<String, ArrayList<String>> allVsAndFieldsMapping = buildAllVirtualSensorsAndFieldsMapping () ; // Hashtable<String, String> vsnames = buildWebParameterMapping("vs[", pm); // key = [x], value = vsname Hashtable<String, String> fields = buildWebParameterMapping("field[", pm); // key = [x], value = fieldname // Iterator<Entry <String, String>> iter2 = vsnames.entrySet().iterator(); String vsname; String field; Set<Entry <String, ArrayList<String>>> entries ; Entry<String, String> en2; ArrayList<String> availableFields; while (iter2.hasNext()) { en2 = iter2.next(); vsname = (String) en2.getValue(); field = fields.get(en2.getKey()); if (vsname.compareToIgnoreCase("All") == 0) { entries = allVsAndFieldsMapping.entrySet(); Iterator<Entry<String, ArrayList<String>>> inneriter = entries.iterator(); Entry<String, ArrayList<String>> innerentry; if (field.compareToIgnoreCase("All") == 0) { while (inneriter.hasNext()) { innerentry = inneriter.next(); updateMapping(vssfm, (String)innerentry.getKey(), (ArrayList<String>)innerentry.getValue()); } } else { while (inneriter.hasNext()) { innerentry = inneriter.next(); availableFields = allVsAndFieldsMapping.get((String)innerentry.getKey()); if (availableFields != null && availableFields.contains(field)) { updateMapping(vssfm, (String)innerentry.getKey(), field); } } } } else { if (field.compareToIgnoreCase("All") == 0) { updateMapping(vssfm, vsname, allVsAndFieldsMapping.get(vsname)); } else { updateMapping(vssfm, vsname, field); } } } return vssfm; } private Hashtable<String, ArrayList<String>> buildAllVirtualSensorsAndFieldsMapping () { // Hashtable<String, ArrayList<String>> allVsAndFieldsMapping = new Hashtable<String, ArrayList<String>>(); Iterator<VSensorConfig> iter = Mappings.getAllVSensorConfigs(); VSensorConfig vsc ; ArrayList<String> allFields; while (iter.hasNext()) { vsc = (VSensorConfig) iter.next(); allFields = new ArrayList<String> () ; DataField[] dfs = vsc.getOutputStructure(); for (int i = 0 ; i < dfs.length ; i++) { allFields.add(dfs[i].getName()); } allVsAndFieldsMapping.put(vsc.getName(), allFields); } return allVsAndFieldsMapping; } private void updateMapping (Hashtable<String, ArrayList<String>> vssfm, String vsname, String field) { ArrayList<String> tmp = new ArrayList<String> () ; tmp.add(field); updateMapping(vssfm, vsname, tmp); } private void updateMapping (Hashtable<String, ArrayList<String>> vssfm, String vsname, ArrayList<String> fields) { if ( ! vssfm.containsKey(vsname)) { vssfm.put(vsname, new ArrayList<String>()); } ArrayList<String> vsnameFields = vssfm.get(vsname); Iterator<String> iter = fields.iterator(); String fieldName ; while (iter.hasNext()) { fieldName = (String) iter.next(); if (! vsnameFields.contains(fieldName)) { vsnameFields.add(fieldName); } } vssfm.put(vsname, vsnameFields); } private Hashtable<String, String> buildWebParameterMapping(String prefix, Map<String, String[]> pm) { Hashtable<String, String> mapping = new Hashtable<String, String> () ; Set<Entry <String,String[]>> sp = pm.entrySet(); Iterator<Entry <String,String[]>> iter = sp.iterator(); Entry<String, String[]> en; String key; while (iter.hasNext()) { en = iter.next(); key = (String) en.getKey() ; if (key.length() > prefix.length() && key.substring(0,prefix.length()).compareToIgnoreCase(prefix) == 0) { // look for "vs[" String[] vals = (String[]) en.getValue(); mapping.put(key.substring(prefix.length() - 1), vals[0]); } } return mapping; } private void plotMapping (Hashtable<String, ArrayList<String>> vssfm) { Iterator<Entry <String, ArrayList<String>>> myiter = vssfm.entrySet().iterator(); Entry<String, ArrayList<String>> myentry; while (myiter.hasNext()) { myentry = myiter.next(); System.out.println("VSNAME: " + myentry.getKey()); Iterator<String> inneriter = myentry.getValue().iterator(); while (inneriter.hasNext()) { System.out.println("FIELD: " + inneriter.next()); } } } }