extensions/net.sf.basedb.reggie/trunk/src/net/sf/basedb/reggie/servlet/DeliveryServlet.java

Code
Comments
Other
Rev Date Author Line
3997 14 Jun 16 nicklas 1 package net.sf.basedb.reggie.servlet;
3997 14 Jun 16 nicklas 2
3997 14 Jun 16 nicklas 3
3997 14 Jun 16 nicklas 4 import java.io.IOException;
4004 20 Jun 16 nicklas 5 import java.io.InputStream;
4004 20 Jun 16 nicklas 6 import java.io.OutputStream;
4008 22 Jun 16 nicklas 7 import java.util.Date;
4034 29 Jul 16 nicklas 8 import java.util.HashSet;
4000 17 Jun 16 nicklas 9 import java.util.List;
4034 29 Jul 16 nicklas 10 import java.util.Set;
3997 14 Jun 16 nicklas 11
3997 14 Jun 16 nicklas 12 import javax.servlet.ServletException;
3997 14 Jun 16 nicklas 13 import javax.servlet.http.HttpServlet;
3997 14 Jun 16 nicklas 14 import javax.servlet.http.HttpServletRequest;
3997 14 Jun 16 nicklas 15 import javax.servlet.http.HttpServletResponse;
3997 14 Jun 16 nicklas 16
3997 14 Jun 16 nicklas 17 import org.json.simple.JSONArray;
3997 14 Jun 16 nicklas 18 import org.json.simple.JSONObject;
3997 14 Jun 16 nicklas 19
4031 26 Jul 16 nicklas 20 import net.sf.basedb.core.AnyToAny;
4007 21 Jun 16 nicklas 21 import net.sf.basedb.core.Application;
4004 20 Jun 16 nicklas 22 import net.sf.basedb.core.ChangeHistory;
3997 14 Jun 16 nicklas 23 import net.sf.basedb.core.DbControl;
4028 26 Jul 16 nicklas 24 import net.sf.basedb.core.Directory;
4000 17 Jun 16 nicklas 25 import net.sf.basedb.core.File;
4000 17 Jun 16 nicklas 26 import net.sf.basedb.core.Item;
4031 26 Jul 16 nicklas 27 import net.sf.basedb.core.ItemNotFoundException;
4000 17 Jun 16 nicklas 28 import net.sf.basedb.core.ItemQuery;
4004 20 Jun 16 nicklas 29 import net.sf.basedb.core.ItemResultIterator;
4028 26 Jul 16 nicklas 30 import net.sf.basedb.core.Path;
4000 17 Jun 16 nicklas 31 import net.sf.basedb.core.Sample;
3997 14 Jun 16 nicklas 32 import net.sf.basedb.core.SessionControl;
4034 29 Jul 16 nicklas 33 import net.sf.basedb.core.SharedItem;
4000 17 Jun 16 nicklas 34 import net.sf.basedb.core.Type;
4007 21 Jun 16 nicklas 35 import net.sf.basedb.core.User;
3997 14 Jun 16 nicklas 36 import net.sf.basedb.core.authentication.LoginRequest;
4004 20 Jun 16 nicklas 37 import net.sf.basedb.core.log.ChangeType;
4004 20 Jun 16 nicklas 38 import net.sf.basedb.core.log.ManualLogEntry;
4000 17 Jun 16 nicklas 39 import net.sf.basedb.core.query.Annotations;
4000 17 Jun 16 nicklas 40 import net.sf.basedb.core.query.Expressions;
4000 17 Jun 16 nicklas 41 import net.sf.basedb.core.query.Hql;
4000 17 Jun 16 nicklas 42 import net.sf.basedb.core.query.Orders;
4000 17 Jun 16 nicklas 43 import net.sf.basedb.core.query.Restrictions;
4000 17 Jun 16 nicklas 44 import net.sf.basedb.core.snapshot.SnapshotManager;
3997 14 Jun 16 nicklas 45 import net.sf.basedb.reggie.JsonUtil;
3997 14 Jun 16 nicklas 46 import net.sf.basedb.reggie.Reggie;
4000 17 Jun 16 nicklas 47 import net.sf.basedb.reggie.XmlConfig;
4000 17 Jun 16 nicklas 48 import net.sf.basedb.reggie.dao.Annotationtype;
3997 14 Jun 16 nicklas 49 import net.sf.basedb.reggie.dao.ClientApp;
4000 17 Jun 16 nicklas 50 import net.sf.basedb.reggie.dao.Patient;
4000 17 Jun 16 nicklas 51 import net.sf.basedb.reggie.dao.SpecimenTube;
4000 17 Jun 16 nicklas 52 import net.sf.basedb.reggie.dao.Subtype;
4000 17 Jun 16 nicklas 53 import net.sf.basedb.reggie.json.LoadMoreJson;
4028 26 Jul 16 nicklas 54 import net.sf.basedb.reggie.pdf.PdfReportTemplate;
4028 26 Jul 16 nicklas 55 import net.sf.basedb.reggie.pdf.PdfToBaseFileCombiner;
4000 17 Jun 16 nicklas 56 import net.sf.basedb.reggie.pdf.PilotReportWorker;
4004 20 Jun 16 nicklas 57 import net.sf.basedb.util.FileUtil;
4004 20 Jun 16 nicklas 58 import net.sf.basedb.util.Values;
3997 14 Jun 16 nicklas 59 import net.sf.basedb.util.error.ThrowableUtil;
3997 14 Jun 16 nicklas 60
3997 14 Jun 16 nicklas 61 /**
3997 14 Jun 16 nicklas 62   Servlet handling requests for the report delivery.
3997 14 Jun 16 nicklas 63   
3997 14 Jun 16 nicklas 64   @author nicklas
3997 14 Jun 16 nicklas 65    @since 4.6
3997 14 Jun 16 nicklas 66 */
3997 14 Jun 16 nicklas 67 public class DeliveryServlet 
3997 14 Jun 16 nicklas 68   extends HttpServlet 
3997 14 Jun 16 nicklas 69 {
3997 14 Jun 16 nicklas 70
4028 26 Jul 16 nicklas 71   
4028 26 Jul 16 nicklas 72   /**
4028 26 Jul 16 nicklas 73     Get the subfolder in the delivery folder structure for an item with the
4028 26 Jul 16 nicklas 74     given name.
4028 26 Jul 16 nicklas 75     
4028 26 Jul 16 nicklas 76     The name can be the name of any item in the SCAN-B data model that
4028 26 Jul 16 nicklas 77     is a specimen or descendent of a specimen. Delivery is assumed to be
4028 26 Jul 16 nicklas 78     on a per-specimen basis and only the specimen name information is used 
4028 26 Jul 16 nicklas 79     to create the subfolder name. Example:
4028 26 Jul 16 nicklas 80     
4028 26 Jul 16 nicklas 81     1234567.1 --> /12/1234567.1
4028 26 Jul 16 nicklas 82     1234567.1.l.r.m.c.lib.g.k.a.t --> /12/1234567.1
4028 26 Jul 16 nicklas 83     
4028 26 Jul 16 nicklas 84   */
4028 26 Jul 16 nicklas 85   public static String generateDeliveryFolder(String itemName)
4028 26 Jul 16 nicklas 86   {
4028 26 Jul 16 nicklas 87     return itemName.replaceFirst("^((\\d{2})\\d+\\.\\d+).*", "/$2/$1");
4028 26 Jul 16 nicklas 88   }
4028 26 Jul 16 nicklas 89   
4141 30 Sep 16 nicklas 90   // Milliseconds in one day
4141 30 Sep 16 nicklas 91   private static long MILLIS_PER_DAY = 24L*3600L*1000L;
4141 30 Sep 16 nicklas 92   
3997 14 Jun 16 nicklas 93   private static final long serialVersionUID = -5722246375117117921L;
3997 14 Jun 16 nicklas 94
3997 14 Jun 16 nicklas 95   public DeliveryServlet()
3997 14 Jun 16 nicklas 96   {}
4000 17 Jun 16 nicklas 97   
4000 17 Jun 16 nicklas 98   @Override
4000 17 Jun 16 nicklas 99   protected void doGet(HttpServletRequest req, HttpServletResponse resp)
4000 17 Jun 16 nicklas 100     throws ServletException, IOException 
4000 17 Jun 16 nicklas 101   {
4000 17 Jun 16 nicklas 102     JSONObject json = new JSONObject();
4009 23 Jun 16 nicklas 103     JSONArray jsonMessages = new JSONArray();
4000 17 Jun 16 nicklas 104     json.put("status", "ok");
4000 17 Jun 16 nicklas 105   
4000 17 Jun 16 nicklas 106     DbControl dc = null;
4000 17 Jun 16 nicklas 107     try
4000 17 Jun 16 nicklas 108     {
4009 23 Jun 16 nicklas 109       JsonUtil.setJsonResponseHeaders(resp);
4009 23 Jun 16 nicklas 110       String cmd = req.getParameter("cmd");
4009 23 Jun 16 nicklas 111       
4009 23 Jun 16 nicklas 112       final SessionControl sc = Reggie.getSessionControl(req, ClientApp.SCANB_DELIVERY, true);
4000 17 Jun 16 nicklas 113       if ("LoadYellowSpecimen".equals(cmd))
4000 17 Jun 16 nicklas 114       {
4006 21 Jun 16 nicklas 115         String search = Values.getStringOrNull(req.getParameter("query"));
4006 21 Jun 16 nicklas 116         
4008 22 Jun 16 nicklas 117         int month = Values.getInt(req.getParameter("month"))+1;
4008 22 Jun 16 nicklas 118         int year = Values.getInt(req.getParameter("year"));
4008 22 Jun 16 nicklas 119         
4009 23 Jun 16 nicklas 120         /*
4037 29 Jul 16 nicklas 121         // For debugging the error handling code on the web client
4009 23 Jun 16 nicklas 122         if (month == 2 && year == 2016)
4009 23 Jun 16 nicklas 123         {
4009 23 Jun 16 nicklas 124           throw new RuntimeException("An internal server error...");
4009 23 Jun 16 nicklas 125         }
4009 23 Jun 16 nicklas 126         */
4009 23 Jun 16 nicklas 127         
6337 16 Jun 21 nicklas 128         dc = sc.newDbControl(":List YellowLabel specimen");
4009 23 Jun 16 nicklas 129         
4009 23 Jun 16 nicklas 130         // Preload annotation types to make sure they are accessible
4009 23 Jun 16 nicklas 131         // and get predictable error handling
4009 23 Jun 16 nicklas 132         Annotationtype.YELLOW_LABEL.load(dc);
4009 23 Jun 16 nicklas 133         Annotationtype.ARRIVAL_DATE.load(dc);
4009 23 Jun 16 nicklas 134         Annotationtype.PERSONAL_NUMBER.load(dc);
4009 23 Jun 16 nicklas 135         Annotationtype.ALL_FIRST_NAMES.load(dc);
4009 23 Jun 16 nicklas 136         Annotationtype.FAMILY_NAME.load(dc);
4037 29 Jul 16 nicklas 137         Annotationtype.PAD.load(dc);
4040 29 Jul 16 nicklas 138         Annotationtype.COMPLETED_DATE.load(dc);
4009 23 Jun 16 nicklas 139
4000 17 Jun 16 nicklas 140         ItemQuery<Sample> query = Sample.getQuery();
4000 17 Jun 16 nicklas 141         Subtype.SPECIMEN.addFilter(dc, query);
4000 17 Jun 16 nicklas 142         query.setIncludes(Reggie.INCLUDE_SHARED_TO_ME);
4000 17 Jun 16 nicklas 143         query.join(Annotations.innerJoin(Annotationtype.YELLOW_LABEL.get(dc), "yl"));
4000 17 Jun 16 nicklas 144         query.join(Annotations.innerJoin(Annotationtype.ARRIVAL_DATE.get(dc), "ad"));
4000 17 Jun 16 nicklas 145         query.join(Hql.innerJoin("parent", "p"));
4000 17 Jun 16 nicklas 146         query.order(Orders.asc(Hql.alias("ad")));
4000 17 Jun 16 nicklas 147         query.order(Orders.asc(Hql.property("name")));
4000 17 Jun 16 nicklas 148         
4006 21 Jun 16 nicklas 149         if (search != null)
4006 21 Jun 16 nicklas 150         {
4006 21 Jun 16 nicklas 151           query.join(Hql.innerJoin("parent", "c")); // Joins the case
4006 21 Jun 16 nicklas 152           query.join(Hql.innerJoin("c", "parent", "pat")); // Joins the patient
4037 29 Jul 16 nicklas 153           query.join(Annotations.leftJoin("pat", Annotationtype.PERSONAL_NUMBER.get(dc), "pnr")); // Joins the personal number
4037 29 Jul 16 nicklas 154           query.join(Annotations.leftJoin(Annotationtype.PAD.get(dc), "pad")); // Joins the PAD
4006 21 Jun 16 nicklas 155           
4037 29 Jul 16 nicklas 156           // Exact match on Personal number/PAD or wildcard match on SCAN-B ID
4006 21 Jun 16 nicklas 157           query.restrict(
4006 21 Jun 16 nicklas 158             Restrictions.or(
4006 21 Jun 16 nicklas 159               Restrictions.eq(Hql.alias("pnr"), Expressions.string(search)),
4037 29 Jul 16 nicklas 160               Restrictions.eq(Hql.alias("pad"), Expressions.string(search)),
4006 21 Jun 16 nicklas 161               Restrictions.like(Hql.property("name"), Expressions.string(search + "%"))
4006 21 Jun 16 nicklas 162           ));
4006 21 Jun 16 nicklas 163         }
4008 22 Jun 16 nicklas 164         else if (year >= 2010)
4008 22 Jun 16 nicklas 165         {
4008 22 Jun 16 nicklas 166           query.restrict(
4008 22 Jun 16 nicklas 167             Restrictions.between(
4008 22 Jun 16 nicklas 168               Hql.alias("ad"),
4008 22 Jun 16 nicklas 169               Expressions.parameter("startDate"), Expressions.parameter("endDate")
4008 22 Jun 16 nicklas 170             ));
4008 22 Jun 16 nicklas 171           
4008 22 Jun 16 nicklas 172           Date startDate = Reggie.CONVERTER_STRING_TO_DATE.convert(year+zeroPad(month)+"01");
4008 22 Jun 16 nicklas 173           month++;
4008 22 Jun 16 nicklas 174           if (month > 12)
4008 22 Jun 16 nicklas 175           {
4008 22 Jun 16 nicklas 176             month = 1;
4008 22 Jun 16 nicklas 177             year++;
4008 22 Jun 16 nicklas 178           }
4008 22 Jun 16 nicklas 179           Date endDate = Reggie.CONVERTER_STRING_TO_DATE.convert(year+zeroPad(month)+"01");;
4008 22 Jun 16 nicklas 180           query.setParameter("startDate", startDate, Type.DATE);
4008 22 Jun 16 nicklas 181           query.setParameter("endDate", endDate, Type.DATE);
4008 22 Jun 16 nicklas 182         }
4008 22 Jun 16 nicklas 183         else
4008 22 Jun 16 nicklas 184         {
4008 22 Jun 16 nicklas 185           // Last 30 days
4008 22 Jun 16 nicklas 186           query.restrict(
4008 22 Jun 16 nicklas 187             Restrictions.gteq(Hql.alias("ad"), Expressions.parameter("startDate"))
4008 22 Jun 16 nicklas 188           );
4141 30 Sep 16 nicklas 189           Date startDate = new Date(System.currentTimeMillis() - 30 * MILLIS_PER_DAY);
4008 22 Jun 16 nicklas 190           query.setParameter("startDate", startDate, Type.DATE);
4008 22 Jun 16 nicklas 191         }
4006 21 Jun 16 nicklas 192         
4000 17 Jun 16 nicklas 193         SnapshotManager manager = new SnapshotManager();
4000 17 Jun 16 nicklas 194         List<SpecimenTube> result = SpecimenTube.toList(query.list(dc));
3997 14 Jun 16 nicklas 195
4000 17 Jun 16 nicklas 196         // We devide the specimen into 3 categories:
4000 17 Jun 16 nicklas 197         // - those with reports that are not downloaded
4000 17 Jun 16 nicklas 198         // - those with no report (ongoing work)
4000 17 Jun 16 nicklas 199         // - those with reports that has been downloaded
4000 17 Jun 16 nicklas 200         JSONArray jsonNewReports = new JSONArray();
4000 17 Jun 16 nicklas 201         JSONArray jsonWorkInProgress = new JSONArray();
4000 17 Jun 16 nicklas 202         JSONArray jsonArchive = new JSONArray();
4000 17 Jun 16 nicklas 203         
4040 29 Jul 16 nicklas 204         // Limit for new->old specimen that has been completed without report
4141 30 Sep 16 nicklas 205         Date sevenDaysAgo = new Date(System.currentTimeMillis() - 7 * MILLIS_PER_DAY);
4040 29 Jul 16 nicklas 206         
4000 17 Jun 16 nicklas 207         for (SpecimenTube sp : result)
4000 17 Jun 16 nicklas 208         {
4000 17 Jun 16 nicklas 209           JSONArray jsonC = jsonWorkInProgress;
4000 17 Jun 16 nicklas 210           sp.loadAnnotations(dc, manager, "ArrivalDate", Annotationtype.ARRIVAL_DATE, Reggie.CONVERTER_DATE_TO_STRING);
4037 29 Jul 16 nicklas 211           sp.loadAnnotations(dc, manager, "PAD", Annotationtype.PAD, null);
4040 29 Jul 16 nicklas 212           sp.loadAnnotations(dc, manager, "CompletedDate", Annotationtype.COMPLETED_DATE, Reggie.CONVERTER_DATE_TO_STRING);
4040 29 Jul 16 nicklas 213           Date completed = (Date)Annotationtype.COMPLETED_DATE.getAnnotationValue(dc, sp.getItem());
4000 17 Jun 16 nicklas 214           
4000 17 Jun 16 nicklas 215           Patient pat = Patient.findByCase(dc, sp.getCase());
4040 29 Jul 16 nicklas 216           pat.loadAnnotations(dc, manager, "PersonalNo", Annotationtype.PERSONAL_NUMBER, null);
4040 29 Jul 16 nicklas 217           pat.loadAnnotations(dc, manager, "AllFirstNames", Annotationtype.ALL_FIRST_NAMES, null);
4040 29 Jul 16 nicklas 218           pat.loadAnnotations(dc, manager, "FamilyName", Annotationtype.FAMILY_NAME, null);
4000 17 Jun 16 nicklas 219           sp.setAnnotation("patient", pat.asJSONObject());
4000 17 Jun 16 nicklas 220
4031 26 Jul 16 nicklas 221           XmlConfig cfg = Reggie.getConfig();
4031 26 Jul 16 nicklas 222           String pdfName = cfg.getConfig("rscript/pilot-report/pdf-name", null, PilotReportWorker.DEFAULT_PDF_NAME);
4031 26 Jul 16 nicklas 223           JSONObject jsonPilot = JsonUtil.loadLinkedItem(dc, sp.getItem(), pdfName, Item.FILE, 
4031 26 Jul 16 nicklas 224             new LoadMoreJson<File>()
4000 17 Jun 16 nicklas 225             {
4031 26 Jul 16 nicklas 226               @Override
4031 26 Jul 16 nicklas 227               public void addMore(DbControl dc, JSONObject json, File file) 
4000 17 Jun 16 nicklas 228               {
4031 26 Jul 16 nicklas 229                 json.put("lastUpdatedDate", Reggie.CONVERTER_DATE_TO_STRING.convert(file.getLastUpdate()));
4000 17 Jun 16 nicklas 230               }
4031 26 Jul 16 nicklas 231             });
4031 26 Jul 16 nicklas 232           if (jsonPilot != null) 
4031 26 Jul 16 nicklas 233           {
4031 26 Jul 16 nicklas 234             sp.setAnnotation("pilotReport", jsonPilot);
4031 26 Jul 16 nicklas 235             jsonC = jsonNewReports;
4031 26 Jul 16 nicklas 236             
4031 26 Jul 16 nicklas 237             ItemQuery<ChangeHistory> historyQuery = ChangeHistory.getHistoryOf(sp.getItem());
4031 26 Jul 16 nicklas 238             historyQuery.restrict(Restrictions.eq(Hql.property("changeType"), Expressions.integer(ChangeType.DOWNLOAD.getValue())));
4031 26 Jul 16 nicklas 239             historyQuery.order(Orders.desc(Hql.property("changeHistory.time")));
4031 26 Jul 16 nicklas 240             historyQuery.setCacheResult(true);
4031 26 Jul 16 nicklas 241             historyQuery.setReturnTotalCount(true);
4031 26 Jul 16 nicklas 242             historyQuery.setMaxResults(1);
4031 26 Jul 16 nicklas 243             
4031 26 Jul 16 nicklas 244             ItemResultIterator<ChangeHistory> it = historyQuery.iterate(dc);
4031 26 Jul 16 nicklas 245             
4031 26 Jul 16 nicklas 246             long downloadCount = it.getTotalCount();
4031 26 Jul 16 nicklas 247             jsonPilot.put("downloadCount", downloadCount);
4031 26 Jul 16 nicklas 248             jsonC = jsonNewReports;
4031 26 Jul 16 nicklas 249             if (downloadCount > 0) 
4031 26 Jul 16 nicklas 250             {
4031 26 Jul 16 nicklas 251               ChangeHistory ch = it.next();
4031 26 Jul 16 nicklas 252               jsonPilot.put("downloadedDate", Reggie.CONVERTER_DATE_TO_STRING.convert(ch.getTime()));
4031 26 Jul 16 nicklas 253               jsonC = jsonArchive;
4000 17 Jun 16 nicklas 254             }
4031 26 Jul 16 nicklas 255             it.close();
4000 17 Jun 16 nicklas 256           }
4040 29 Jul 16 nicklas 257           else if (completed != null)
4040 29 Jul 16 nicklas 258           {
4040 29 Jul 16 nicklas 259             // Marked as completed but there is not published report
4040 29 Jul 16 nicklas 260             // Typically an indication of some kind of problem (eg. Flagged RNA, etc)
4040 29 Jul 16 nicklas 261             if (completed.before(sevenDaysAgo))
4040 29 Jul 16 nicklas 262             {
4040 29 Jul 16 nicklas 263               // More than 7 days old
4040 29 Jul 16 nicklas 264               jsonC = jsonArchive;
4040 29 Jul 16 nicklas 265             }
4040 29 Jul 16 nicklas 266             else
4040 29 Jul 16 nicklas 267             {
4040 29 Jul 16 nicklas 268               jsonC = jsonNewReports;
4040 29 Jul 16 nicklas 269             }
4040 29 Jul 16 nicklas 270           }
4000 17 Jun 16 nicklas 271
4000 17 Jun 16 nicklas 272           jsonC.add(sp.asJSONObject());
4000 17 Jun 16 nicklas 273         }
4009 23 Jun 16 nicklas 274         // Thread.sleep(2500);
4006 21 Jun 16 nicklas 275         
4000 17 Jun 16 nicklas 276         json.put("newReports", jsonNewReports);
4000 17 Jun 16 nicklas 277         json.put("workInProgress", jsonWorkInProgress);
4000 17 Jun 16 nicklas 278         json.put("archived", jsonArchive);
4007 21 Jun 16 nicklas 279         json.put("user", loadCurrentUserInformation(dc));
4006 21 Jun 16 nicklas 280         
4000 17 Jun 16 nicklas 281       }
4004 20 Jun 16 nicklas 282       else if ("DownloadReport".equals(cmd))
4004 20 Jun 16 nicklas 283       {
4004 20 Jun 16 nicklas 284         json = null; // No JSON output
6337 16 Jun 21 nicklas 285         dc = sc.newDbControl(":Download report");
4004 20 Jun 16 nicklas 286         
4004 20 Jun 16 nicklas 287         int fileId = Values.getInt(req.getParameter("fileId"));
4004 20 Jun 16 nicklas 288         File pdf = File.getById(dc, fileId);
4004 20 Jun 16 nicklas 289         String pdfPath = pdf.getPath().toString();
4004 20 Jun 16 nicklas 290         
4004 20 Jun 16 nicklas 291         int specimenId = Values.getInt(req.getParameter("specimenId"));
4004 20 Jun 16 nicklas 292         Sample specimen = Sample.getById(dc, specimenId);
4004 20 Jun 16 nicklas 293
4009 23 Jun 16 nicklas 294         // We create one DOWNLOAD log entry on the file and one on the specimen
4009 23 Jun 16 nicklas 295         dc.logEntry(new ManualLogEntry(pdf, ChangeType.DOWNLOAD, null));
4009 23 Jun 16 nicklas 296         dc.logEntry(new ManualLogEntry(specimen, ChangeType.DOWNLOAD, pdfPath));
4009 23 Jun 16 nicklas 297
4038 29 Jul 16 nicklas 298         resp.setHeader("Content-Disposition", "attachment; filename=" + Path.makeSafeFilename(specimen.getName(), "")+".pdf");
4004 20 Jun 16 nicklas 299         resp.setContentType(pdf.getMimeType());
4004 20 Jun 16 nicklas 300         resp.setContentLengthLong(pdf.getSize());
4004 20 Jun 16 nicklas 301         
4038 29 Jul 16 nicklas 302         OutputStream out = null;
4038 29 Jul 16 nicklas 303         InputStream in = null;
4038 29 Jul 16 nicklas 304         try
4038 29 Jul 16 nicklas 305         {
4038 29 Jul 16 nicklas 306           out = resp.getOutputStream();
4038 29 Jul 16 nicklas 307           in = pdf.getDownloadStream(0);
4038 29 Jul 16 nicklas 308           
4038 29 Jul 16 nicklas 309           // For debugging
4038 29 Jul 16 nicklas 310           // if (fileId == 807879) throw new RuntimeException("Download failed");
4038 29 Jul 16 nicklas 311           
4038 29 Jul 16 nicklas 312           FileUtil.copy(in, out);
4038 29 Jul 16 nicklas 313           out.flush();
4038 29 Jul 16 nicklas 314           dc.commit();
4038 29 Jul 16 nicklas 315         }
4038 29 Jul 16 nicklas 316         finally
4038 29 Jul 16 nicklas 317         {
4038 29 Jul 16 nicklas 318           FileUtil.close(out);
4038 29 Jul 16 nicklas 319           FileUtil.close(in);
4038 29 Jul 16 nicklas 320         }
4009 23 Jun 16 nicklas 321
4004 20 Jun 16 nicklas 322       }
4007 21 Jun 16 nicklas 323       else if ("Logout".equals(cmd))
4007 21 Jun 16 nicklas 324       {
4007 21 Jun 16 nicklas 325         Thread.sleep(2500);
4007 21 Jun 16 nicklas 326         sc.logout();
4010 23 Jun 16 nicklas 327         sc.close();
4007 21 Jun 16 nicklas 328       }
4000 17 Jun 16 nicklas 329     }
4000 17 Jun 16 nicklas 330     catch (Throwable t)
4000 17 Jun 16 nicklas 331     {
4000 17 Jun 16 nicklas 332       t.printStackTrace();
4004 20 Jun 16 nicklas 333       if (json != null)
4004 20 Jun 16 nicklas 334       {
4004 20 Jun 16 nicklas 335         json.clear();
4004 20 Jun 16 nicklas 336         json.put("status", "error");
4004 20 Jun 16 nicklas 337         json.put("message", t.getMessage());
4004 20 Jun 16 nicklas 338         json.put("stacktrace", ThrowableUtil.stackTraceToString(t));
4004 20 Jun 16 nicklas 339       }
4004 20 Jun 16 nicklas 340       else
4004 20 Jun 16 nicklas 341       {
4009 23 Jun 16 nicklas 342         resp.reset();
4004 20 Jun 16 nicklas 343         resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, t.getMessage());
4004 20 Jun 16 nicklas 344       }
4000 17 Jun 16 nicklas 345     }
4000 17 Jun 16 nicklas 346     finally
4000 17 Jun 16 nicklas 347     {
4000 17 Jun 16 nicklas 348       if (dc != null) dc.close();
4004 20 Jun 16 nicklas 349       if (json != null) json.writeJSONString(resp.getWriter());
4000 17 Jun 16 nicklas 350     }
4000 17 Jun 16 nicklas 351     
4000 17 Jun 16 nicklas 352   }
5320 28 Feb 19 nicklas 353   
3997 14 Jun 16 nicklas 354   @Override
3997 14 Jun 16 nicklas 355   protected void doPost(HttpServletRequest req, HttpServletResponse resp)
3997 14 Jun 16 nicklas 356     throws ServletException, IOException 
3997 14 Jun 16 nicklas 357   {
3997 14 Jun 16 nicklas 358     JSONObject json = new JSONObject();
4009 23 Jun 16 nicklas 359     JSONArray jsonMessages = new JSONArray();
3997 14 Jun 16 nicklas 360     json.put("status", "ok");
3998 15 Jun 16 nicklas 361     
3997 14 Jun 16 nicklas 362     DbControl dc = null;
4010 23 Jun 16 nicklas 363     SessionControl sc = null;
3997 14 Jun 16 nicklas 364     try
3997 14 Jun 16 nicklas 365     {
3998 15 Jun 16 nicklas 366       JsonUtil.setJsonResponseHeaders(resp);
3998 15 Jun 16 nicklas 367       String cmd = req.getParameter("cmd");
3998 15 Jun 16 nicklas 368       
3997 14 Jun 16 nicklas 369       if ("Login".equals(cmd))
3997 14 Jun 16 nicklas 370       {
3997 14 Jun 16 nicklas 371         JSONObject jsonReq = JsonUtil.parseRequest(req);
3997 14 Jun 16 nicklas 372         String username = (String)jsonReq.get("username");
3997 14 Jun 16 nicklas 373         String password = (String)jsonReq.get("password");
3997 14 Jun 16 nicklas 374         String yubikey = (String)jsonReq.get("yubikey");
3997 14 Jun 16 nicklas 375         
3997 14 Jun 16 nicklas 376         LoginRequest login = new LoginRequest(yubikey, password);
3997 14 Jun 16 nicklas 377         login.setAttribute("username", username);
5163 03 Dec 18 nicklas 378         login.setAttribute("login-form", "net.sf.basedb.yubikey.login-form");
3997 14 Jun 16 nicklas 379         
4010 23 Jun 16 nicklas 380         sc = Application.newSessionControl(ClientApp.SCANB_DELIVERY.getExternalId(), req.getRemoteAddr(), null);
3997 14 Jun 16 nicklas 381         sc.login(login);
4010 23 Jun 16 nicklas 382         json.put("ID", sc.getId());
3997 14 Jun 16 nicklas 383       }
3997 14 Jun 16 nicklas 384       
3997 14 Jun 16 nicklas 385       json.put("messages", jsonMessages);
3997 14 Jun 16 nicklas 386     }
3997 14 Jun 16 nicklas 387     catch (Throwable t)
3997 14 Jun 16 nicklas 388     {
4010 23 Jun 16 nicklas 389       // Cleanup after failed login attempt
4010 23 Jun 16 nicklas 390       if (sc != null) sc.close();
3997 14 Jun 16 nicklas 391       t.printStackTrace();
3997 14 Jun 16 nicklas 392       json.clear();
3997 14 Jun 16 nicklas 393       json.put("status", "error");
3997 14 Jun 16 nicklas 394       json.put("message", t.getMessage());
3997 14 Jun 16 nicklas 395       json.put("stacktrace", ThrowableUtil.stackTraceToString(t));
3997 14 Jun 16 nicklas 396     }
3997 14 Jun 16 nicklas 397     finally
3997 14 Jun 16 nicklas 398     {
3997 14 Jun 16 nicklas 399       if (dc != null) dc.close();
3997 14 Jun 16 nicklas 400       json.writeJSONString(resp.getWriter());
3997 14 Jun 16 nicklas 401     }
3997 14 Jun 16 nicklas 402   }
4000 17 Jun 16 nicklas 403   
4007 21 Jun 16 nicklas 404   public static JSONObject loadCurrentUserInformation(DbControl dc)
4007 21 Jun 16 nicklas 405   {
4007 21 Jun 16 nicklas 406     SessionControl sc = dc.getSessionControl();
4007 21 Jun 16 nicklas 407     User u = User.getById(dc, sc.getLoggedInUserId());
4007 21 Jun 16 nicklas 408
4007 21 Jun 16 nicklas 409     JSONObject json = new JSONObject();
4007 21 Jun 16 nicklas 410     json.put("id", u.getId());
4007 21 Jun 16 nicklas 411     json.put("username", u.getLogin());
4007 21 Jun 16 nicklas 412     json.put("name", u.getName());
4007 21 Jun 16 nicklas 413     
4007 21 Jun 16 nicklas 414     // Calculate timeout from last access
4007 21 Jun 16 nicklas 415     // Use 1 minute less to allow user to react before it is too late
4007 21 Jun 16 nicklas 416     long timeout = sc.getLastAccess() + (Application.sessionCacheTimeout()-1) * 60000;
4007 21 Jun 16 nicklas 417 //    long timeout = sc.getLastAccess() + 2 * 60000;
4007 21 Jun 16 nicklas 418     json.put("timeout", timeout);
4007 21 Jun 16 nicklas 419     
4007 21 Jun 16 nicklas 420     return json;
4007 21 Jun 16 nicklas 421   }
4008 22 Jun 16 nicklas 422   
4008 22 Jun 16 nicklas 423   private String zeroPad(int month)
4008 22 Jun 16 nicklas 424   {
4008 22 Jun 16 nicklas 425     return (month < 10 ? "0" : "") +  month;
4008 22 Jun 16 nicklas 426   }
4008 22 Jun 16 nicklas 427   
4028 26 Jul 16 nicklas 428   /**
4028 26 Jul 16 nicklas 429     Extends the copy pdf file combiner with support for
4028 26 Jul 16 nicklas 430     saving files in the correct subfolder inside the
4028 26 Jul 16 nicklas 431     {@link Reggie#DELIVERY_DIR}. 
4028 26 Jul 16 nicklas 432   */
4028 26 Jul 16 nicklas 433   public static class CombineForDelivery
4028 26 Jul 16 nicklas 434     extends PdfToBaseFileCombiner
4028 26 Jul 16 nicklas 435   {
4028 26 Jul 16 nicklas 436     
4028 26 Jul 16 nicklas 437     private final PdfReportTemplate report;
4028 26 Jul 16 nicklas 438     private final String rootPath;
4034 29 Jul 16 nicklas 439     
4141 30 Sep 16 nicklas 440     private Set<SharedItem> itemsToPublish;
4028 26 Jul 16 nicklas 441
4028 26 Jul 16 nicklas 442     public CombineForDelivery(DbControl dc, Directory rootDir, PdfReportTemplate report) 
4028 26 Jul 16 nicklas 443     {
4028 26 Jul 16 nicklas 444       super(dc, rootDir);
4028 26 Jul 16 nicklas 445       this.report = report;
4028 26 Jul 16 nicklas 446       this.rootPath = rootDir.getPath().toString();
4141 30 Sep 16 nicklas 447       this.itemsToPublish = new HashSet<>();
4028 26 Jul 16 nicklas 448     }
4028 26 Jul 16 nicklas 449     
4028 26 Jul 16 nicklas 450     @Override
4028 26 Jul 16 nicklas 451     protected File createOrGetFile(DbControl dc, String pdfName) 
4028 26 Jul 16 nicklas 452     {
4028 26 Jul 16 nicklas 453       String folder = DeliveryServlet.generateDeliveryFolder(pdfName);
4028 26 Jul 16 nicklas 454       Path p = new Path(rootPath + folder, Path.Type.DIRECTORY);
4028 26 Jul 16 nicklas 455       
4028 26 Jul 16 nicklas 456       Directory d = Directory.getNew(dc, p);
4028 26 Jul 16 nicklas 457       File f = File.getFile(dc, d, report.getDefaultFilename(), true);
4031 26 Jul 16 nicklas 458       // The immediate parent directory has the same name as the specimen
4141 30 Sep 16 nicklas 459       String specimenName = d.getName();
4141 30 Sep 16 nicklas 460       if (!f.isInDatabase()) 
4034 29 Jul 16 nicklas 461       {
4141 30 Sep 16 nicklas 462         // Make sure new items are not shared to default project, etc.
4141 30 Sep 16 nicklas 463         // Collect the PDF file and parent directories up to /home/Delivery
4141 30 Sep 16 nicklas 464         // Permissions will be updated by the SetPermissionsForDelivery plug-in later
4141 30 Sep 16 nicklas 465         f.setItemKey(null);
4141 30 Sep 16 nicklas 466         f.setProjectKey(null);
4141 30 Sep 16 nicklas 467         dc.saveItem(f);
4141 30 Sep 16 nicklas 468         
4141 30 Sep 16 nicklas 469         while (d != null && !d.isInDatabase())
4141 30 Sep 16 nicklas 470         {
4141 30 Sep 16 nicklas 471           d.setItemKey(null);
4141 30 Sep 16 nicklas 472           d.setProjectKey(null);
4141 30 Sep 16 nicklas 473           d = d.getParent();
4141 30 Sep 16 nicklas 474         }
4034 29 Jul 16 nicklas 475       }
4141 30 Sep 16 nicklas 476
4141 30 Sep 16 nicklas 477       // Link the file to the specimen item
4141 30 Sep 16 nicklas 478       SpecimenTube sp = SpecimenTube.findByTubeName(dc, specimenName);
4141 30 Sep 16 nicklas 479       if (sp == null) throw new ItemNotFoundException("Specimen tube: " + specimenName);
4034 29 Jul 16 nicklas 480       
4034 29 Jul 16 nicklas 481       AnyToAny link = AnyToAny.getNewOrExisting(dc, sp.getItem(), f.getName(), f, false);
4031 26 Jul 16 nicklas 482       if (!link.isInDatabase()) dc.saveItem(link);
4031 26 Jul 16 nicklas 483       link.setDescription("Pilot report for delivery to site");
4031 26 Jul 16 nicklas 484       
4141 30 Sep 16 nicklas 485       itemsToPublish.add(f);
4028 26 Jul 16 nicklas 486       
4028 26 Jul 16 nicklas 487       return f;
4028 26 Jul 16 nicklas 488     }
4028 26 Jul 16 nicklas 489
4034 29 Jul 16 nicklas 490     public int numberOfItemsToPublish()
4034 29 Jul 16 nicklas 491     {
4141 30 Sep 16 nicklas 492       return itemsToPublish.size();
4034 29 Jul 16 nicklas 493     }
4028 26 Jul 16 nicklas 494     
4141 30 Sep 16 nicklas 495     public Set<SharedItem> getItemsToPublish()
4034 29 Jul 16 nicklas 496     {
4034 29 Jul 16 nicklas 497       return itemsToPublish;
4034 29 Jul 16 nicklas 498     }
4034 29 Jul 16 nicklas 499     
4028 26 Jul 16 nicklas 500   }
3997 14 Jun 16 nicklas 501 }