X-Git-Url: http://git.argeo.org/?a=blobdiff_plain;f=org.argeo.app.servlet.odk%2Fsrc%2Forg%2Fargeo%2Fapp%2Fservlet%2Fodk%2FOdkSubmissionServlet.java;h=68e701d5fc4ed7250692fcced41c35c39d40680e;hb=616a062e9d061ce91589556624ed622298a21ac7;hp=3740805f1216a7aff661f559f10a7cdd15e8b1d1;hpb=d6c9d33b61e475914d3f8d7534374ed30eca8150;p=gpl%2Fargeo-suite.git diff --git a/org.argeo.app.servlet.odk/src/org/argeo/app/servlet/odk/OdkSubmissionServlet.java b/org.argeo.app.servlet.odk/src/org/argeo/app/servlet/odk/OdkSubmissionServlet.java index 3740805..68e701d 100644 --- a/org.argeo.app.servlet.odk/src/org/argeo/app/servlet/odk/OdkSubmissionServlet.java +++ b/org.argeo.app.servlet.odk/src/org/argeo/app/servlet/odk/OdkSubmissionServlet.java @@ -13,8 +13,6 @@ import java.util.Set; import javax.jcr.ImportUUIDBehavior; import javax.jcr.Node; import javax.jcr.Property; -import javax.jcr.Repository; -import javax.jcr.Session; import javax.jcr.nodetype.NodeType; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; @@ -22,18 +20,17 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.Part; +import org.argeo.api.acr.Content; +import org.argeo.api.app.AppUserState; import org.argeo.api.cms.CmsLog; import org.argeo.api.cms.CmsSession; import org.argeo.app.image.ImageProcessor; -import org.argeo.app.jcr.SuiteJcrUtils; import org.argeo.app.odk.OrxType; import org.argeo.app.xforms.FormSubmissionListener; import org.argeo.cms.auth.RemoteAuthRequest; import org.argeo.cms.auth.RemoteAuthUtils; -import org.argeo.cms.jcr.CmsJcrUtils; import org.argeo.cms.jcr.acr.JcrContent; import org.argeo.cms.servlet.ServletHttpRequest; -import org.argeo.jcr.Jcr; import org.argeo.jcr.JcrUtils; /** Receives a form submission. */ @@ -42,50 +39,44 @@ public class OdkSubmissionServlet extends HttpServlet { private final static CmsLog log = CmsLog.getLog(OdkSubmissionServlet.class); private final static String XML_SUBMISSION_FILE = "xml_submission_file"; + private final static String IS_INCOMPLETE = "*isIncomplete*"; private DateTimeFormatter submissionNameFormatter = DateTimeFormatter.ofPattern("YYYY-MM-dd-HHmmssSSS") .withZone(ZoneId.from(ZoneOffset.UTC)); - private Repository repository; - private Set submissionListeners = new HashSet<>(); + private AppUserState appUserState; + @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { resp.setContentType("text/xml; charset=utf-8"); resp.setHeader("X-OpenRosa-Version", "1.0"); resp.setDateHeader("Date", System.currentTimeMillis()); - // should be set in HEAD? Let's rather use defaults. - // resp.setIntHeader("X-OpenRosa-Accept-Content-Length", 1024 * 1024); - RemoteAuthRequest request = new ServletHttpRequest(req); - Session session = RemoteAuthUtils.doAs(() -> Jcr.login(repository, null), request); - CmsSession cmsSession = RemoteAuthUtils.getCmsSession(request); - Session adminSession = null; - try { - // TODO centralise at a deeper level - adminSession = CmsJcrUtils.openDataAdminSession(repository, null); - SuiteJcrUtils.getOrCreateCmsSessionNode(adminSession, cmsSession); - } finally { - Jcr.logout(adminSession); - } - + boolean isIncomplete = false; try { - Node cmsSessionNode = SuiteJcrUtils.getCmsSessionNode(session, cmsSession); - Node submission = cmsSessionNode.addNode(submissionNameFormatter.format(Instant.now()), - OrxType.submission.get()); + Content sessionDir = appUserState.getOrCreateSessionDir(cmsSession); + Node cmsSessionNode = sessionDir.adapt(Node.class); + String submissionName = submissionNameFormatter.format(Instant.now()); + Node submission = cmsSessionNode.addNode(submissionName, OrxType.submission.get()); + String submissionPath = submission.getPath(); for (Part part : req.getParts()) { + String partNameSane = JcrUtils.replaceInvalidChars(part.getName()); if (log.isTraceEnabled()) log.trace("Part: " + part.getName() + ", " + part.getContentType()); if (part.getName().equals(XML_SUBMISSION_FILE)) { Node xml = submission.addNode(XML_SUBMISSION_FILE, NodeType.NT_UNSTRUCTURED); - session.importXML(xml.getPath(), part.getInputStream(), + cmsSessionNode.getSession().importXML(xml.getPath(), part.getInputStream(), ImportUUIDBehavior.IMPORT_UUID_COLLISION_REPLACE_EXISTING); + } else if (part.getName().equals(IS_INCOMPLETE)) { + isIncomplete = true; + log.debug("Form submission " + submissionPath + " is incomplete, expecting more to be uploaded..."); } else { Node fileNode; if (part.getName().endsWith(".jpg")) { @@ -95,19 +86,17 @@ public class OdkSubmissionServlet extends HttpServlet { ImageProcessor imageProcessor = new ImageProcessor(() -> part.getInputStream(), () -> Files.newOutputStream(temp)); imageProcessor.process(); - fileNode = JcrUtils.copyStreamAsFile(submission, part.getName(), - Files.newInputStream(temp)); + fileNode = JcrUtils.copyStreamAsFile(submission, partNameSane, Files.newInputStream(temp)); } finally { Files.deleteIfExists(temp); } } else { - fileNode = JcrUtils.copyStreamAsFile(submission, part.getName(), part.getInputStream()); + fileNode = JcrUtils.copyStreamAsFile(submission, partNameSane, part.getInputStream()); } String contentType = part.getContentType(); if (contentType != null) { fileNode.addMixin(NodeType.MIX_MIMETYPE); fileNode.setProperty(Property.JCR_MIMETYPE, contentType); - } if (part.getName().endsWith(".jpg") || part.getName().endsWith(".png")) { // TODO meta data and thumbnails @@ -115,25 +104,26 @@ public class OdkSubmissionServlet extends HttpServlet { } } - session.save(); + cmsSessionNode.getSession().save(); try { for (FormSubmissionListener submissionListener : submissionListeners) { - submissionListener.formSubmissionReceived(JcrContent.nodeToContent(submission)); + submissionListener.formSubmissionReceived(JcrContent.nodeToContent(submission), isIncomplete); } } catch (Exception e) { - log.error("Cannot save submision, cancelling...", e); - submission.remove(); - session.save(); + log.error("Cannot save submission, cancelling...", e); + if (cmsSessionNode.getSession().hasPendingChanges()) + cmsSessionNode.getSession().refresh(false);// discard + if (cmsSessionNode.getSession().itemExists(submissionPath)) + submission.remove(); + cmsSessionNode.getSession().save(); resp.setStatus(503); return; } } catch (Exception e) { - log.error("Cannot save submision", e); + log.error("Cannot save submission", e); resp.setStatus(503); return; - } finally { - Jcr.logout(session); } resp.setStatus(201); @@ -142,10 +132,6 @@ public class OdkSubmissionServlet extends HttpServlet { } - public void setRepository(Repository repository) { - this.repository = repository; - } - public synchronized void addSubmissionListener(FormSubmissionListener listener) { submissionListeners.add(listener); } @@ -153,4 +139,9 @@ public class OdkSubmissionServlet extends HttpServlet { public synchronized void removeSubmissionListener(FormSubmissionListener listener) { submissionListeners.remove(listener); } + + public void setAppUserState(AppUserState appUserState) { + this.appUserState = appUserState; + } + }