]> git.argeo.org Git - gpl/argeo-suite.git/blob - org.argeo.support.odk/src/org/argeo/support/odk/servlet/OdkSubmissionServlet.java
Adapt to changes in Argeo Commons
[gpl/argeo-suite.git] / org.argeo.support.odk / src / org / argeo / support / odk / servlet / OdkSubmissionServlet.java
1 package org.argeo.support.odk.servlet;
2
3 import java.io.IOException;
4 import java.time.Instant;
5 import java.time.ZoneId;
6 import java.time.ZoneOffset;
7 import java.time.format.DateTimeFormatter;
8 import java.util.HashSet;
9 import java.util.Set;
10
11 import javax.jcr.ImportUUIDBehavior;
12 import javax.jcr.Node;
13 import javax.jcr.Property;
14 import javax.jcr.Repository;
15 import javax.jcr.RepositoryException;
16 import javax.jcr.Session;
17 import javax.jcr.nodetype.NodeType;
18 import javax.servlet.ServletException;
19 import javax.servlet.http.HttpServlet;
20 import javax.servlet.http.HttpServletRequest;
21 import javax.servlet.http.HttpServletResponse;
22 import javax.servlet.http.Part;
23
24 import org.apache.commons.logging.Log;
25 import org.apache.commons.logging.LogFactory;
26 import org.argeo.api.cms.CmsSession;
27 import org.argeo.cms.auth.HttpRequest;
28 import org.argeo.cms.jcr.CmsJcrUtils;
29 import org.argeo.cms.servlet.ServletAuthUtils;
30 import org.argeo.cms.servlet.ServletHttpRequest;
31 import org.argeo.jcr.Jcr;
32 import org.argeo.jcr.JcrUtils;
33 import org.argeo.suite.SuiteUtils;
34 import org.argeo.support.odk.OrxType;
35 import org.argeo.support.xforms.FormSubmissionListener;
36
37 /** Receives a form submission. */
38 public class OdkSubmissionServlet extends HttpServlet {
39 private static final long serialVersionUID = 7834401404691302385L;
40 private final static Log log = LogFactory.getLog(OdkSubmissionServlet.class);
41
42 private final static String XML_SUBMISSION_FILE = "xml_submission_file";
43
44 private DateTimeFormatter submissionNameFormatter = DateTimeFormatter.ofPattern("YYYY-MM-dd-HHmmssSSS")
45 .withZone(ZoneId.from(ZoneOffset.UTC));
46
47 private Repository repository;
48
49 private Set<FormSubmissionListener> submissionListeners = new HashSet<>();
50
51 @Override
52 protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
53 resp.setContentType("text/xml; charset=utf-8");
54 resp.setHeader("X-OpenRosa-Version", "1.0");
55 resp.setDateHeader("Date", System.currentTimeMillis());
56 resp.setIntHeader("X-OpenRosa-Accept-Content-Length", 1024 * 1024);
57
58 HttpRequest request = new ServletHttpRequest(req);
59 Session session = ServletAuthUtils.doAs(() -> Jcr.login(repository, null), request);
60
61 try {
62 // Node submissions = JcrUtils.mkdirs(session,
63 // "/" + EntityType.form.get() + "/" + EntityNames.SUBMISSIONS_BASE);
64 CmsSession cmsSession = ServletAuthUtils.getCmsSession(request);
65
66 ClassLoader currentContextCl = Thread.currentThread().getContextClassLoader();
67 Thread.currentThread().setContextClassLoader(ServletAuthUtils.class.getClassLoader());
68 Session adminSession = null;
69 try {
70 // TODO centralise at a deeper level
71 adminSession = CmsJcrUtils.openDataAdminSession(repository, null);
72 SuiteUtils.getOrCreateCmsSessionNode(adminSession, cmsSession);
73 } finally {
74 Jcr.logout(adminSession);
75 Thread.currentThread().setContextClassLoader(currentContextCl);
76 }
77
78 Node cmsSessionNode = SuiteUtils.getCmsSessionNode(session, cmsSession);
79 Node submission = cmsSessionNode.addNode(submissionNameFormatter.format(Instant.now()),
80 OrxType.submission.get());
81 for (Part part : req.getParts()) {
82 if (log.isDebugEnabled())
83 log.debug("Part: " + part.getName() + ", " + part.getContentType());
84
85 if (part.getName().equals(XML_SUBMISSION_FILE)) {
86 Node xml = submission.addNode(XML_SUBMISSION_FILE, NodeType.NT_UNSTRUCTURED);
87 session.importXML(xml.getPath(), part.getInputStream(),
88 ImportUUIDBehavior.IMPORT_UUID_COLLISION_REPLACE_EXISTING);
89
90 } else {
91 Node fileNode = JcrUtils.copyStreamAsFile(submission, part.getName(), part.getInputStream());
92 String contentType = part.getContentType();
93 if (contentType != null) {
94 fileNode.addMixin(NodeType.MIX_MIMETYPE);
95 fileNode.setProperty(Property.JCR_MIMETYPE, contentType);
96
97 }
98 if (part.getName().endsWith(".jpg") || part.getName().endsWith(".png")) {
99 // TODO meta data and thumbnails
100 }
101 }
102 }
103 session.save();
104 for (FormSubmissionListener submissionListener : submissionListeners) {
105 submissionListener.formSubmissionReceived(submission);
106 }
107 } catch (RepositoryException e) {
108 e.printStackTrace();
109 resp.setStatus(503);
110 return;
111 } finally {
112 Jcr.logout(session);
113 }
114
115 resp.setStatus(201);
116 resp.getWriter().write("<OpenRosaResponse xmlns=\"http://openrosa.org/http/response\">"
117 + "<message>Form Received!</message>" + "</OpenRosaResponse>");
118
119 }
120
121 public void setRepository(Repository repository) {
122 this.repository = repository;
123 }
124
125 public synchronized void addSubmissionListener(FormSubmissionListener listener) {
126 submissionListeners.add(listener);
127 }
128
129 public synchronized void removeSubmissionListener(FormSubmissionListener listener) {
130 submissionListeners.remove(listener);
131 }
132 }