extensions/net.sf.basedb.relax/trunk/src/net/sf/basedb/relax/servlet/ExportServlet.java

Code
Comments
Other
Rev Date Author Line
4631 21 Nov 17 nicklas 1 package net.sf.basedb.relax.servlet;
4631 21 Nov 17 nicklas 2
4634 22 Nov 17 nicklas 3 import java.io.BufferedReader;
4634 22 Nov 17 nicklas 4 import java.io.FileNotFoundException;
4631 21 Nov 17 nicklas 5 import java.io.IOException;
4634 22 Nov 17 nicklas 6 import java.io.InputStream;
4634 22 Nov 17 nicklas 7 import java.io.InputStreamReader;
4634 22 Nov 17 nicklas 8 import java.io.OutputStream;
4634 22 Nov 17 nicklas 9 import java.io.OutputStreamWriter;
4631 21 Nov 17 nicklas 10
5512 19 Jun 19 nicklas 11 import javax.crypto.Cipher;
5512 19 Jun 19 nicklas 12 import javax.crypto.CipherInputStream;
5512 19 Jun 19 nicklas 13 import javax.crypto.CipherOutputStream;
4631 21 Nov 17 nicklas 14 import javax.servlet.ServletException;
4631 21 Nov 17 nicklas 15 import javax.servlet.http.HttpServlet;
4631 21 Nov 17 nicklas 16 import javax.servlet.http.HttpServletRequest;
4631 21 Nov 17 nicklas 17 import javax.servlet.http.HttpServletResponse;
4631 21 Nov 17 nicklas 18
4631 21 Nov 17 nicklas 19 import org.json.simple.JSONArray;
4631 21 Nov 17 nicklas 20 import org.json.simple.JSONObject;
4631 21 Nov 17 nicklas 21
4634 22 Nov 17 nicklas 22 import net.sf.basedb.clients.web.fileupload.FileUpload;
4634 22 Nov 17 nicklas 23 import net.sf.basedb.clients.web.fileupload.FileUploadProgress;
4634 22 Nov 17 nicklas 24 import net.sf.basedb.clients.web.fileupload.UploadedFile;
4634 22 Nov 17 nicklas 25 import net.sf.basedb.core.Application;
5511 19 Jun 19 nicklas 26 import net.sf.basedb.core.BioSource;
4631 21 Nov 17 nicklas 27 import net.sf.basedb.core.DbControl;
4634 22 Nov 17 nicklas 28 import net.sf.basedb.core.ItemQuery;
4634 22 Nov 17 nicklas 29 import net.sf.basedb.core.Path;
4634 22 Nov 17 nicklas 30 import net.sf.basedb.core.Project;
4631 21 Nov 17 nicklas 31 import net.sf.basedb.core.SessionControl;
4631 21 Nov 17 nicklas 32 import net.sf.basedb.core.SimpleProgressReporter;
4634 22 Nov 17 nicklas 33 import net.sf.basedb.core.Type;
4634 22 Nov 17 nicklas 34 import net.sf.basedb.core.query.Expressions;
4634 22 Nov 17 nicklas 35 import net.sf.basedb.core.query.Hql;
4634 22 Nov 17 nicklas 36 import net.sf.basedb.core.query.Restrictions;
4631 21 Nov 17 nicklas 37 import net.sf.basedb.relax.JsonUtil;
4631 21 Nov 17 nicklas 38 import net.sf.basedb.relax.Relax;
5512 19 Jun 19 nicklas 39 import net.sf.basedb.relax.crypto.CryptoUtil;
4634 22 Nov 17 nicklas 40 import net.sf.basedb.relax.dao.Subtype;
4634 22 Nov 17 nicklas 41 import net.sf.basedb.util.FileUtil;
5512 19 Jun 19 nicklas 42 import net.sf.basedb.util.MD5;
5512 19 Jun 19 nicklas 43 import net.sf.basedb.util.StaticCache;
4634 22 Nov 17 nicklas 44 import net.sf.basedb.util.Values;
4631 21 Nov 17 nicklas 45 import net.sf.basedb.util.error.ThrowableUtil;
4634 22 Nov 17 nicklas 46 import net.sf.basedb.util.export.TableWriter;
4631 21 Nov 17 nicklas 47
4631 21 Nov 17 nicklas 48
4631 21 Nov 17 nicklas 49 public class ExportServlet 
4631 21 Nov 17 nicklas 50   extends HttpServlet 
4631 21 Nov 17 nicklas 51 {
4631 21 Nov 17 nicklas 52
4631 21 Nov 17 nicklas 53   private static final long serialVersionUID = 5134386187393673271L;
4631 21 Nov 17 nicklas 54
4631 21 Nov 17 nicklas 55   public ExportServlet()
4631 21 Nov 17 nicklas 56   {}
4631 21 Nov 17 nicklas 57
4631 21 Nov 17 nicklas 58   @Override
4631 21 Nov 17 nicklas 59   protected void doGet(HttpServletRequest req, HttpServletResponse resp)
4631 21 Nov 17 nicklas 60     throws ServletException, IOException 
4631 21 Nov 17 nicklas 61   {
4631 21 Nov 17 nicklas 62     String cmd = req.getParameter("cmd");
4631 21 Nov 17 nicklas 63     boolean useJsonForError = false;
4631 21 Nov 17 nicklas 64   
4631 21 Nov 17 nicklas 65     final SessionControl sc = Relax.getSessionControl(req);
4631 21 Nov 17 nicklas 66     DbControl dc = null;
4631 21 Nov 17 nicklas 67     try
4631 21 Nov 17 nicklas 68     {
4631 21 Nov 17 nicklas 69       if ("DownloadMappedData".equals(cmd))
4631 21 Nov 17 nicklas 70       {
4634 22 Nov 17 nicklas 71         Relax.checkIsAdmin(sc, "'" + cmd + "' wizard");
4631 21 Nov 17 nicklas 72         
6779 17 Jun 22 nicklas 73         dc = sc.newDbControl("Relax: download mapped data");
5512 19 Jun 19 nicklas 74         StaticCache cache = Application.getStaticCache();
4634 22 Nov 17 nicklas 75         String originalFilename = (String)sc.getSessionSetting("mapped-data-filename");
5512 19 Jun 19 nicklas 76         String tmpFilePath = getTmpFileCacheKey(sc, originalFilename);        
5512 19 Jun 19 nicklas 77         if (originalFilename == null || !cache.exists(tmpFilePath))
4634 22 Nov 17 nicklas 78         {
4634 22 Nov 17 nicklas 79           throw new FileNotFoundException(originalFilename);
4634 22 Nov 17 nicklas 80         }
5512 19 Jun 19 nicklas 81
4634 22 Nov 17 nicklas 82         String suffix = "";
4634 22 Nov 17 nicklas 83         if (sc.getActiveProjectId() != 0)
4634 22 Nov 17 nicklas 84         {
4634 22 Nov 17 nicklas 85           Project p = Project.getById(dc, sc.getActiveProjectId());
4634 22 Nov 17 nicklas 86           suffix += "-" + Path.makeSafeFilename(p.getName(), "").replace(' ', '-');
4634 22 Nov 17 nicklas 87         }
4634 22 Nov 17 nicklas 88         int lastDot = originalFilename.lastIndexOf('.');
4634 22 Nov 17 nicklas 89         String filename = lastDot > 0 ? originalFilename.substring(0, lastDot) +  suffix + originalFilename.substring(lastDot) : originalFilename + suffix;
4634 22 Nov 17 nicklas 90
4634 22 Nov 17 nicklas 91         OutputStream out = null;
4634 22 Nov 17 nicklas 92         InputStream in = null;
4634 22 Nov 17 nicklas 93         try
4634 22 Nov 17 nicklas 94         {
5512 19 Jun 19 nicklas 95           in = cache.read(tmpFilePath, 5);
5512 19 Jun 19 nicklas 96           Cipher c = CryptoUtil.createSessionCipher(sc, Cipher.DECRYPT_MODE, originalFilename);
5512 19 Jun 19 nicklas 97           in = new CipherInputStream(in, c);
5512 19 Jun 19 nicklas 98           
4634 22 Nov 17 nicklas 99           resp.setHeader("Content-Disposition", "attachment; filename=" + filename);
4634 22 Nov 17 nicklas 100           resp.setContentType("text/plain");
4634 22 Nov 17 nicklas 101           resp.setCharacterEncoding("UTF-8");
4634 22 Nov 17 nicklas 102           out = resp.getOutputStream();
4634 22 Nov 17 nicklas 103           FileUtil.copy(in, out);
4634 22 Nov 17 nicklas 104         }
4634 22 Nov 17 nicklas 105         finally
4634 22 Nov 17 nicklas 106         {
4634 22 Nov 17 nicklas 107           FileUtil.close(in);
4634 22 Nov 17 nicklas 108           FileUtil.close(out);
4634 22 Nov 17 nicklas 109         }
4631 21 Nov 17 nicklas 110       }
4631 21 Nov 17 nicklas 111     }
4631 21 Nov 17 nicklas 112     catch (Throwable t)
4631 21 Nov 17 nicklas 113     {
4631 21 Nov 17 nicklas 114       t.printStackTrace();
4631 21 Nov 17 nicklas 115       if (useJsonForError)
4631 21 Nov 17 nicklas 116       {
4631 21 Nov 17 nicklas 117         JsonUtil.setJsonResponseHeaders(resp);
4631 21 Nov 17 nicklas 118         JSONObject json = new JSONObject();
4631 21 Nov 17 nicklas 119         json.put("status", "error");
4631 21 Nov 17 nicklas 120         json.put("message", t.getMessage());
4631 21 Nov 17 nicklas 121         json.put("stacktrace", ThrowableUtil.stackTraceToString(t));
4631 21 Nov 17 nicklas 122         json.writeJSONString(resp.getWriter());
4631 21 Nov 17 nicklas 123       }
4631 21 Nov 17 nicklas 124       else
4631 21 Nov 17 nicklas 125       {
4631 21 Nov 17 nicklas 126         resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, t.getClass().getName() + ": " + t.getMessage());
4631 21 Nov 17 nicklas 127       }
4631 21 Nov 17 nicklas 128     }
4631 21 Nov 17 nicklas 129     finally
4631 21 Nov 17 nicklas 130     {
4631 21 Nov 17 nicklas 131       if (dc != null) dc.close();
4631 21 Nov 17 nicklas 132     }
4631 21 Nov 17 nicklas 133   }
4631 21 Nov 17 nicklas 134   
4631 21 Nov 17 nicklas 135   @Override
4631 21 Nov 17 nicklas 136   protected void doPost(HttpServletRequest req, HttpServletResponse resp)
4631 21 Nov 17 nicklas 137     throws ServletException, IOException 
4631 21 Nov 17 nicklas 138   {
4631 21 Nov 17 nicklas 139     String cmd = req.getParameter("cmd");
4631 21 Nov 17 nicklas 140     JsonUtil.setJsonResponseHeaders(resp);
4631 21 Nov 17 nicklas 141     
4631 21 Nov 17 nicklas 142     JSONObject json = new JSONObject();
4631 21 Nov 17 nicklas 143     json.put("status", "ok");
4631 21 Nov 17 nicklas 144     
4631 21 Nov 17 nicklas 145     JSONArray jsonMessages = new JSONArray();
4631 21 Nov 17 nicklas 146
4631 21 Nov 17 nicklas 147     final SessionControl sc = Relax.getSessionControl(req);
4631 21 Nov 17 nicklas 148     DbControl dc = null;
4631 21 Nov 17 nicklas 149     String progressId = "";
4631 21 Nov 17 nicklas 150     try
4631 21 Nov 17 nicklas 151     {
4631 21 Nov 17 nicklas 152       if ("MapDataToReleases".equals(cmd))
4631 21 Nov 17 nicklas 153       {
4634 22 Nov 17 nicklas 154         Relax.checkIsAdmin(sc, "'" + cmd + "' wizard");
4634 22 Nov 17 nicklas 155         
6779 17 Jun 22 nicklas 156         dc = sc.newDbControl("Relax: map data to releases");
5511 19 Jun 19 nicklas 157         ItemQuery<BioSource> findPatient = BioSource.getQuery();
5511 19 Jun 19 nicklas 158         Subtype.PATIENT.addFilter(dc, findPatient);
5511 19 Jun 19 nicklas 159         findPatient.setIncludes(Relax.INCLUDE_IN_CURRENT_PROJECT);
5511 19 Jun 19 nicklas 160         findPatient.restrict(Restrictions.eq(Hql.property("name"), Expressions.parameter("patientId")));
4634 22 Nov 17 nicklas 161
4634 22 Nov 17 nicklas 162         InputStream uploadIn = null;
4634 22 Nov 17 nicklas 163         BufferedReader uploadReader = null;
4634 22 Nov 17 nicklas 164         OutputStream tmpOut = null;
4634 22 Nov 17 nicklas 165         TableWriter tmpWriter = null;
5512 19 Jun 19 nicklas 166         
4634 22 Nov 17 nicklas 167         boolean mapCompleted = false;
4631 21 Nov 17 nicklas 168         SimpleProgressReporter progress = new SimpleProgressReporter(null);
4631 21 Nov 17 nicklas 169         progressId = "map-data-progress";
4631 21 Nov 17 nicklas 170         sc.setSessionSetting(progressId, progress);
4631 21 Nov 17 nicklas 171         
4634 22 Nov 17 nicklas 172         try
4634 22 Nov 17 nicklas 173         {
4634 22 Nov 17 nicklas 174           FileUpload uploader = new FileUpload(req);
4634 22 Nov 17 nicklas 175           FileUploadProgress uploadProgress = uploader.getProgress();
4634 22 Nov 17 nicklas 176           UploadedFile file = uploader.next();
4634 22 Nov 17 nicklas 177           long totalBytes = uploadProgress.getTotalBytes();
4634 22 Nov 17 nicklas 178           
4634 22 Nov 17 nicklas 179           // Prepare for reading the uploaded file
4634 22 Nov 17 nicklas 180           uploadIn = file.getInputStream();
4634 22 Nov 17 nicklas 181           uploadReader = new BufferedReader(new InputStreamReader(uploadIn, "UTF-8"));
4631 21 Nov 17 nicklas 182
4634 22 Nov 17 nicklas 183           // Prepare for writing to a temporary file
5512 19 Jun 19 nicklas 184           String outputFilePath = getTmpFileCacheKey(sc, file.getFilename());
5512 19 Jun 19 nicklas 185           Cipher cipher = CryptoUtil.createSessionCipher(sc, Cipher.ENCRYPT_MODE, file.getFilename());
5512 19 Jun 19 nicklas 186           tmpOut = new CipherOutputStream(Application.getStaticCache().write(outputFilePath, 5), cipher);
4634 22 Nov 17 nicklas 187           tmpWriter = new TableWriter(new OutputStreamWriter(tmpOut, "UTF-8"));
4634 22 Nov 17 nicklas 188         
4634 22 Nov 17 nicklas 189           // Read the header line, check that it has at least two columns and write the new header
4634 22 Nov 17 nicklas 190           String header = uploadReader.readLine();
4634 22 Nov 17 nicklas 191           long parsedCharacters = header.length()+1;
5511 19 Jun 19 nicklas 192           String[] dataIn = header.split("\t", 2);
5511 19 Jun 19 nicklas 193           if (dataIn.length != 2) 
4634 22 Nov 17 nicklas 194           {
5511 19 Jun 19 nicklas 195             throw new IOException("The file need at least 2 header columns");
4634 22 Nov 17 nicklas 196           }
4634 22 Nov 17 nicklas 197         
4634 22 Nov 17 nicklas 198           tmpWriter.tablePrintData(header);
4634 22 Nov 17 nicklas 199         
4634 22 Nov 17 nicklas 200           int lineIn = 0;
4634 22 Nov 17 nicklas 201           int lineOut = 0;
4634 22 Nov 17 nicklas 202           int linesSkipped = 0;
4634 22 Nov 17 nicklas 203           
4634 22 Nov 17 nicklas 204           String data = uploadReader.readLine();
4634 22 Nov 17 nicklas 205           while (data != null)
4634 22 Nov 17 nicklas 206           {
4634 22 Nov 17 nicklas 207             parsedCharacters += data.length() + 1;
4634 22 Nov 17 nicklas 208             lineIn++;
4634 22 Nov 17 nicklas 209             progress.display((int)(100*parsedCharacters / totalBytes), "Working... " + lineIn + " lines parsed so far...");
4634 22 Nov 17 nicklas 210             
5511 19 Jun 19 nicklas 211             dataIn = data.split("\t", 2);
5511 19 Jun 19 nicklas 212             if (dataIn.length != 2) 
4634 22 Nov 17 nicklas 213             {
5511 19 Jun 19 nicklas 214               throw new IOException("On line " + lineIn + ": The file need at least 2 data columns");
4634 22 Nov 17 nicklas 215             }
5511 19 Jun 19 nicklas 216             
5511 19 Jun 19 nicklas 217             String patientId = Values.getStringOrNull(dataIn[0]);
5511 19 Jun 19 nicklas 218             if (patientId == null)
4634 22 Nov 17 nicklas 219             {
5511 19 Jun 19 nicklas 220               throw new IOException("On line " + lineIn + ": Patient id is missing");
4634 22 Nov 17 nicklas 221             }
5511 19 Jun 19 nicklas 222             findPatient.setParameter("patientId", patientId, Type.STRING);
5511 19 Jun 19 nicklas 223             long numPatient = findPatient.count(dc);
5511 19 Jun 19 nicklas 224             if (numPatient == 0)
4634 22 Nov 17 nicklas 225             {
4634 22 Nov 17 nicklas 226               linesSkipped++;
4634 22 Nov 17 nicklas 227             }
4634 22 Nov 17 nicklas 228             else
4634 22 Nov 17 nicklas 229             {
4634 22 Nov 17 nicklas 230               tmpWriter.tablePrintData(data);
4634 22 Nov 17 nicklas 231               lineOut++;
4634 22 Nov 17 nicklas 232             }
4634 22 Nov 17 nicklas 233             data = uploadReader.readLine();
4634 22 Nov 17 nicklas 234           }
4634 22 Nov 17 nicklas 235           
4634 22 Nov 17 nicklas 236           if (lineOut == 0)
4634 22 Nov 17 nicklas 237           {
5511 19 Jun 19 nicklas 238             throw new IOException("On line " + lineIn + ": No patients found. Is this the correct file?");
4634 22 Nov 17 nicklas 239           }
4634 22 Nov 17 nicklas 240         
4634 22 Nov 17 nicklas 241           tmpWriter.flush();
4634 22 Nov 17 nicklas 242           tmpOut.flush();
4634 22 Nov 17 nicklas 243           jsonMessages.add("Parsed " + lineIn + " lines from input file");
4634 22 Nov 17 nicklas 244           jsonMessages.add("Wrote " + lineOut + " lines to output file");
4634 22 Nov 17 nicklas 245           if (linesSkipped > 0)
4634 22 Nov 17 nicklas 246           {
5511 19 Jun 19 nicklas 247             jsonMessages.add("Skipped " + linesSkipped + " lines from input file (no patient found)");
4634 22 Nov 17 nicklas 248           }
4634 22 Nov 17 nicklas 249           else
4634 22 Nov 17 nicklas 250           {
5511 19 Jun 19 nicklas 251             jsonMessages.add("All pateients was found");
4634 22 Nov 17 nicklas 252           }
4634 22 Nov 17 nicklas 253           json.put("numLinesIn", lineIn);
4634 22 Nov 17 nicklas 254           json.put("numLinesOut", lineOut);
4634 22 Nov 17 nicklas 255           json.put("numNotFound", linesSkipped);
4634 22 Nov 17 nicklas 256           sc.setSessionSetting("mapped-data-filename", file.getFilename());
4634 22 Nov 17 nicklas 257           mapCompleted = true;
4634 22 Nov 17 nicklas 258         }
4634 22 Nov 17 nicklas 259         finally
4634 22 Nov 17 nicklas 260         {
4634 22 Nov 17 nicklas 261           FileUtil.close(uploadReader);
4634 22 Nov 17 nicklas 262           FileUtil.close(uploadIn);
4634 22 Nov 17 nicklas 263           FileUtil.close(tmpWriter);
4634 22 Nov 17 nicklas 264           FileUtil.close(tmpOut);
4634 22 Nov 17 nicklas 265         }
4631 21 Nov 17 nicklas 266       }
4631 21 Nov 17 nicklas 267       
4631 21 Nov 17 nicklas 268       json.put("messages", jsonMessages);
4631 21 Nov 17 nicklas 269     }
4631 21 Nov 17 nicklas 270     catch (Throwable t)
4631 21 Nov 17 nicklas 271     {
4631 21 Nov 17 nicklas 272       t.printStackTrace();
4631 21 Nov 17 nicklas 273       json.clear();
4631 21 Nov 17 nicklas 274       json.put("status", "error");
4631 21 Nov 17 nicklas 275       json.put("message", t.getMessage());
4631 21 Nov 17 nicklas 276       json.put("stacktrace", ThrowableUtil.stackTraceToString(t));
4631 21 Nov 17 nicklas 277     }
4631 21 Nov 17 nicklas 278     finally
4631 21 Nov 17 nicklas 279     {
4631 21 Nov 17 nicklas 280       if (dc != null) dc.close();
4631 21 Nov 17 nicklas 281       if (sc != null) sc.setSessionSetting(progressId, null);
4631 21 Nov 17 nicklas 282       json.writeJSONString(resp.getWriter());
4631 21 Nov 17 nicklas 283     }    
4631 21 Nov 17 nicklas 284   }
4631 21 Nov 17 nicklas 285
5512 19 Jun 19 nicklas 286   /**
5512 19 Jun 19 nicklas 287     Get the cache key to use for storing the temporary mapped file.
5512 19 Jun 19 nicklas 288     The path is a MD5 value calculated from the current session 
5512 19 Jun 19 nicklas 289     and user id.
5512 19 Jun 19 nicklas 290   */
5512 19 Jun 19 nicklas 291   private String getTmpFileCacheKey(SessionControl sc, String filename)
4631 21 Nov 17 nicklas 292   {
5512 19 Jun 19 nicklas 293     return "/relax/map-data/" + MD5.getHashString(sc.getId()+"-"+sc.getLoggedInUserId()+"-"+filename)+".tmp";
4631 21 Nov 17 nicklas 294   }
5512 19 Jun 19 nicklas 295
4631 21 Nov 17 nicklas 296 }