ODK servlets based on JCR.
[gpl/argeo-suite.git] / knowledge / org.argeo.support.odk / src / org / argeo / support / odk / servlet / OdkFormListServlet.java
1 package org.argeo.support.odk.servlet;
2
3 import java.io.IOException;
4 import java.io.Writer;
5 import java.security.AccessControlContext;
6 import java.time.ZoneId;
7 import java.time.ZoneOffset;
8 import java.time.format.DateTimeFormatter;
9 import java.util.Collections;
10 import java.util.HashSet;
11 import java.util.Set;
12
13 import javax.jcr.Node;
14 import javax.jcr.NodeIterator;
15 import javax.jcr.Property;
16 import javax.jcr.Repository;
17 import javax.jcr.RepositoryException;
18 import javax.jcr.Session;
19 import javax.jcr.query.Query;
20 import javax.jcr.query.QueryResult;
21 import javax.security.auth.Subject;
22 import javax.servlet.ServletException;
23 import javax.servlet.http.HttpServlet;
24 import javax.servlet.http.HttpServletRequest;
25 import javax.servlet.http.HttpServletResponse;
26
27 import org.apache.commons.logging.Log;
28 import org.apache.commons.logging.LogFactory;
29 import org.argeo.api.NodeConstants;
30 import org.argeo.cms.servlet.ServletAuthUtils;
31 import org.argeo.entity.EntityType;
32 import org.argeo.jcr.Jcr;
33 import org.argeo.jcr.JcrUtils;
34 import org.argeo.jcr.JcrxApi;
35 import org.argeo.support.odk.OdkForm;
36 import org.argeo.support.odk.OrxListType;
37
38 /** Lists available forms. */
39 public class OdkFormListServlet extends HttpServlet {
40         private static final long serialVersionUID = 2706191315048423321L;
41         private final static Log log = LogFactory.getLog(OdkFormListServlet.class);
42
43         private Set<OdkForm> odkForms = Collections.synchronizedSet(new HashSet<>());
44
45         private DateTimeFormatter versionFormatter = DateTimeFormatter.ofPattern("YYYY-MM-dd-HHmm")
46                         .withZone(ZoneId.from(ZoneOffset.UTC));
47
48         private Repository repository;
49
50         @Override
51         protected void doGet(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
56                 String serverName = req.getServerName();
57                 int serverPort = req.getServerPort();
58                 String protocol = serverPort == 443 || req.isSecure() ? "https" : "http";
59
60                 String pathInfo = req.getPathInfo();
61
62                 Subject subject = Subject
63                                 .getSubject((AccessControlContext) req.getAttribute(AccessControlContext.class.getName()));
64                 log.debug("SERVLET CONTEXT: " + subject);
65
66                 Session session = ServletAuthUtils.doAs(() -> Jcr.login(repository, NodeConstants.SYS_WORKSPACE), req);
67 //              session = NodeUtils.openDataAdminSession(repository, NodeConstants.SYS_WORKSPACE);
68                 Writer writer = resp.getWriter();
69                 writer.append("<?xml version='1.0' encoding='UTF-8' ?>");
70                 writer.append("<xforms xmlns=\"http://openrosa.org/xforms/xformsList\">");
71                 boolean oldApproach = false;
72                 if (oldApproach) {
73                         try {
74
75                                 Query query;
76                                 if (pathInfo == null) {
77 //                              query = session.getWorkspace().getQueryManager()
78 //                                              .createQuery("SELECT * FROM [nt:unstructured]", Query.JCR_SQL2);
79                                         query = session.getWorkspace().getQueryManager()
80                                                         .createQuery("SELECT * FROM [" + OrxListType.xform.get() + "]", Query.JCR_SQL2);
81                                 } else {
82                                         query = session.getWorkspace().getQueryManager()
83                                                         .createQuery(
84                                                                         "SELECT node FROM [" + OrxListType.xform.get()
85                                                                                         + "] AS node WHERE ISDESCENDANTNODE (node, '" + pathInfo + "')",
86                                                                         Query.JCR_SQL2);
87                                 }
88                                 QueryResult queryResult = query.execute();
89
90                                 NodeIterator nit = queryResult.getNodes();
91 //                              log.debug(session.getUserID());
92 //                              log.debug(session.getWorkspace().getName());
93 //                              NodeIterator nit = session.getRootNode().getNodes();
94 //                              while (nit.hasNext()) {
95 //                                      log.debug(nit.nextNode());
96 //                              }
97                                 while (nit.hasNext()) {
98                                         StringBuilder sb = new StringBuilder();
99                                         Node node = nit.nextNode();
100                                         if (node.isNodeType(OrxListType.xform.get())) {
101                                                 sb.append("<xform>");
102                                                 sb.append("<formID>" + node.getNode("h:html").getIdentifier() + "</formID>");
103                                                 sb.append("<name>" + Jcr.getTitle(node) + "</name>");
104                                                 sb.append("<version>" + versionFormatter.format(JcrUtils.getModified(node)) + "</version>");
105                                                 sb.append("<hash>md5:" + JcrxApi.getChecksum(node, JcrxApi.MD5) + "</hash>");
106                                                 if (node.hasProperty(Property.JCR_DESCRIPTION))
107                                                         sb.append("<name>" + node.getProperty(Property.JCR_DESCRIPTION).getString() + "</name>");
108                                                 sb.append("<downloadUrl>" + protocol + "://" + serverName
109                                                                 + (serverPort == 80 || serverPort == 443 ? "" : ":" + serverPort) + "/api/odk/form/"
110                                                                 + node.getPath() + "</downloadUrl>");
111                                                 sb.append("</xform>");
112                                         } else if (node.isNodeType(EntityType.formSet.get())) {
113                                                 sb.append("<xforms-group>");
114                                                 sb.append("<groupId>" + node.getPath() + "</groupId>");
115                                                 sb.append("<name>" + node.getProperty(Property.JCR_TITLE).getString() + "</name>");
116                                                 sb.append("<listUrl>" + protocol + "://" + serverName
117                                                                 + (serverPort == 80 || serverPort == 443 ? "" : ":" + serverPort) + "/api/odk/formList"
118                                                                 + node.getPath() + "</listUrl>");
119                                                 sb.append("</xforms-group>");
120                                         }
121                                         String str = sb.toString();
122                                         if (!str.equals("")) {
123                                                 if (log.isDebugEnabled())
124                                                         log.debug(str);
125                                                 writer.append(str);
126                                         }
127                                 }
128                         } catch (RepositoryException e) {
129                                 e.printStackTrace();
130                                 // TODO error message
131                                 // resp.sendError(500);
132                         } finally {
133                                 Jcr.logout(session);
134                         }
135
136                 } else {
137                         for (OdkForm form : odkForms) {
138                                 StringBuilder sb = new StringBuilder();
139                                 sb.append("<xform>");
140                                 sb.append("<formID>" + form.getFormId() + "</formID>");
141                                 sb.append("<name>" + form.getName() + "</name>");
142                                 sb.append("<version>" + form.getVersion() + "</version>");
143                                 sb.append("<hash>" + form.getHash(null) + "</hash>");
144                                 sb.append("<descriptionText>" + form.getDescription() + "</descriptionText>");
145                                 sb.append("<downloadUrl>" + protocol + "://" + serverName
146                                                 + (serverPort == 80 || serverPort == 443 ? "" : ":" + serverPort) + "/api/odk/form/"
147                                                 + form.getFileName() + "</downloadUrl>");
148                                 sb.append("</xform>");
149                                 String str = sb.toString();
150                                 if (log.isDebugEnabled())
151                                         log.debug(str);
152                                 writer.append(str);
153                         }
154                 }
155                 writer.append("</xforms>");
156         }
157
158         public void addForm(OdkForm odkForm) {
159                 odkForms.add(odkForm);
160         }
161
162         public void removeForm(OdkForm odkForm) {
163                 odkForms.remove(odkForm);
164         }
165
166         public void setRepository(Repository repository) {
167                 this.repository = repository;
168         }
169
170 }