]> git.argeo.org Git - gpl/argeo-suite.git/blob - knowledge/org.argeo.support.odk/src/org/argeo/support/odk/servlet/OdkManifestServlet.java
3510e06ee154b50e7426c38773f01fe8107cd15c
[gpl/argeo-suite.git] / knowledge / org.argeo.support.odk / src / org / argeo / support / odk / servlet / OdkManifestServlet.java
1 package org.argeo.support.odk.servlet;
2
3 import java.io.IOException;
4 import java.io.OutputStream;
5 import java.io.Writer;
6 import java.nio.charset.Charset;
7 import java.security.DigestOutputStream;
8 import java.security.MessageDigest;
9 import java.security.NoSuchAlgorithmException;
10 import java.util.ArrayList;
11 import java.util.List;
12
13 import javax.jcr.ItemNotFoundException;
14 import javax.jcr.Node;
15 import javax.jcr.NodeIterator;
16 import javax.jcr.Property;
17 import javax.jcr.Repository;
18 import javax.jcr.RepositoryException;
19 import javax.jcr.Session;
20 import javax.jcr.Value;
21 import javax.jcr.nodetype.NodeType;
22 import javax.jcr.query.Query;
23 import javax.jcr.query.QueryResult;
24 import javax.jcr.query.Row;
25 import javax.jcr.query.RowIterator;
26 import javax.servlet.ServletException;
27 import javax.servlet.http.HttpServlet;
28 import javax.servlet.http.HttpServletRequest;
29 import javax.servlet.http.HttpServletResponse;
30
31 import org.apache.commons.io.output.NullOutputStream;
32 import org.argeo.cms.servlet.ServletAuthUtils;
33 import org.argeo.entity.EntityMimeType;
34 import org.argeo.jcr.Jcr;
35 import org.argeo.jcr.JcrException;
36 import org.argeo.support.odk.OrxManifestName;
37 import org.argeo.util.CsvWriter;
38 import org.argeo.util.DigestUtils;
39
40 /** Describe additional files. */
41 public class OdkManifestServlet extends HttpServlet {
42 private static final long serialVersionUID = 138030510865877478L;
43
44 private Repository repository;
45
46 @Override
47 protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
48 resp.setHeader("X-OpenRosa-Version", "1.0");
49 resp.setDateHeader("Date", System.currentTimeMillis());
50
51 String pathInfo = req.getPathInfo();
52 if (pathInfo.startsWith("//"))
53 pathInfo = pathInfo.substring(1);
54
55 String serverName = req.getServerName();
56 int serverPort = req.getServerPort();
57 String protocol = serverPort == 443 || req.isSecure() ? "https" : "http";
58
59 Session session = ServletAuthUtils.doAs(() -> Jcr.login(repository, null), req);
60
61 try {
62 Node node = session.getNode(pathInfo);
63 if (node.isNodeType(OrxManifestName.manifest.get())) {
64 resp.setContentType(EntityMimeType.XML.toHttpContentType());
65 Writer writer = resp.getWriter();
66 writer.append("<?xml version='1.0' encoding='UTF-8' ?>");
67 writer.append("<manifest xmlns=\"http://openrosa.org/xforms/xformsManifest\">");
68 NodeIterator nit = node.getNodes();
69 children: while (nit.hasNext()) {
70 Node file = nit.nextNode();
71 if (file.isNodeType(OrxManifestName.mediaFile.get())) {
72 EntityMimeType mimeType = EntityMimeType
73 .find(file.getProperty(Property.JCR_MIMETYPE).getString());
74 Charset charset = Charset.forName(file.getProperty(Property.JCR_ENCODING).getString());
75
76 if (file.isNodeType(NodeType.NT_ADDRESS)) {
77 Node target;
78 try {
79 target = file.getProperty(Property.JCR_ID).getNode();
80 } catch (ItemNotFoundException e) {
81 // TODO remove old manifests
82 continue children;
83 }
84 writer.append("<mediaFile>");
85 writer.append("<filename>");
86 // Work around bug in ODK Collect not supporting paths
87 // writer.append(target.getPath().substring(1) + ".xml");
88 writer.append(target.getIdentifier() + "." + mimeType.getDefaultExtension());
89 writer.append("</filename>");
90
91 MessageDigest messageDigest = MessageDigest.getInstance(DigestUtils.MD5);
92 // TODO cache a temp file ?
93 try (DigestOutputStream out = new DigestOutputStream(new NullOutputStream(),
94 messageDigest)) {
95 writeMediaFile(out, target, mimeType, charset);
96 writer.append("<hash>");
97 writer.append("md5sum:" + DigestUtils.encodeHexString(out.getMessageDigest().digest()));
98 writer.append("</hash>");
99 }
100
101 // try (ByteArrayOutputStream out = new ByteArrayOutputStream()) {
102 // session.exportDocumentView(target.getPath(), out, true, false);
103 // String fileCsum = DigestUtils.digest(DigestUtils.MD5, out.toByteArray());
104 // writer.append("<hash>");
105 // writer.append("md5sum:" + fileCsum);
106 // writer.append("</hash>");
107 // }
108 writer.append("<downloadUrl>" + protocol + "://" + serverName
109 + (serverPort == 80 || serverPort == 443 ? "" : ":" + serverPort)
110 + "/api/odk/formManifest" + file.getPath() + "</downloadUrl>");
111 }
112 writer.append("</mediaFile>");
113 }
114 }
115
116 writer.append("</manifest>");
117 } else if (node.isNodeType(OrxManifestName.mediaFile.get())) {
118 EntityMimeType mimeType = EntityMimeType.find(node.getProperty(Property.JCR_MIMETYPE).getString());
119 Charset charset = Charset.forName(node.getProperty(Property.JCR_ENCODING).getString());
120 resp.setContentType(mimeType.toHttpContentType(charset));
121 if (node.isNodeType(NodeType.NT_ADDRESS)) {
122 Node target = node.getProperty(Property.JCR_ID).getNode();
123
124 writeMediaFile(resp.getOutputStream(), target, mimeType, charset);
125 // try (ByteArrayOutputStream out = new ByteArrayOutputStream()) {
126 // session.exportDocumentView(target.getPath(), out, true, false);
127 // System.out.println(new String(out.toByteArray(), StandardCharsets.UTF_8));
128 // resp.getOutputStream().write(out.toByteArray());
129 // }
130 } else {
131 throw new IllegalArgumentException("Unsupported node " + node);
132 }
133 } else {
134 throw new IllegalArgumentException("Unsupported node " + node);
135 }
136 } catch (RepositoryException e) {
137 throw new JcrException(e);
138 } catch (NoSuchAlgorithmException e) {
139 throw new ServletException(e);
140 } finally {
141 Jcr.logout(session);
142 }
143
144 }
145
146 protected void writeMediaFile(OutputStream out, Node target, EntityMimeType mimeType, Charset charset)
147 throws RepositoryException, IOException {
148 if (target.isNodeType(NodeType.NT_QUERY)) {
149 Query query = target.getSession().getWorkspace().getQueryManager().getQuery(target);
150 QueryResult queryResult = query.execute();
151 String[] columnNames = queryResult.getColumnNames();
152 if (EntityMimeType.XML.equals(mimeType)) {
153 } else if (EntityMimeType.CSV.equals(mimeType)) {
154 CsvWriter csvWriter = new CsvWriter(out, charset);
155 csvWriter.writeLine(columnNames);
156 RowIterator rit = queryResult.getRows();
157 while (rit.hasNext()) {
158 Row row = rit.nextRow();
159 Value[] values = row.getValues();
160 List<String> lst = new ArrayList<>();
161 for (Value value : values) {
162 lst.add(value.getString());
163 }
164 csvWriter.writeLine(lst);
165 }
166 }
167 } else {
168 if (EntityMimeType.XML.equals(mimeType)) {
169 target.getSession().exportDocumentView(target.getPath(), out, true, false);
170 } else if (EntityMimeType.CSV.equals(mimeType)) {
171 CsvWriter csvWriter = new CsvWriter(out, charset);
172 csvWriter.writeLine(new String[] { "name", "label" });
173 NodeIterator children = target.getNodes();
174 while (children.hasNext()) {
175 Node child = children.nextNode();
176 String label = Jcr.getTitle(child);
177 csvWriter.writeLine(new String[] { child.getIdentifier(), label });
178 }
179 }
180
181 }
182
183 }
184
185 public void setRepository(Repository repository) {
186 this.repository = repository;
187 }
188
189 }