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