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