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