package org.argeo.support.odk.servlet;
-import java.io.ByteArrayOutputStream;
import java.io.IOException;
+import java.io.OutputStream;
import java.io.Writer;
-import java.nio.charset.StandardCharsets;
-
+import java.nio.charset.Charset;
+import java.security.DigestOutputStream;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.jcr.ItemNotFoundException;
import javax.jcr.Node;
import javax.jcr.NodeIterator;
import javax.jcr.Property;
import javax.jcr.Repository;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
+import javax.jcr.Value;
import javax.jcr.nodetype.NodeType;
+import javax.jcr.query.Query;
+import javax.jcr.query.QueryResult;
+import javax.jcr.query.Row;
+import javax.jcr.query.RowIterator;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
+import org.apache.commons.io.output.NullOutputStream;
import org.argeo.cms.servlet.ServletAuthUtils;
+import org.argeo.entity.EntityMimeType;
import org.argeo.jcr.Jcr;
import org.argeo.jcr.JcrException;
import org.argeo.support.odk.OrxManifestName;
+import org.argeo.util.CsvWriter;
import org.argeo.util.DigestUtils;
/** Describe additional files. */
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
- resp.setContentType("text/xml; charset=utf-8");
resp.setHeader("X-OpenRosa-Version", "1.0");
resp.setDateHeader("Date", System.currentTimeMillis());
try {
Node node = session.getNode(pathInfo);
if (node.isNodeType(OrxManifestName.manifest.get())) {
+ resp.setContentType(EntityMimeType.XML.toHttpContentType());
Writer writer = resp.getWriter();
writer.append("<?xml version='1.0' encoding='UTF-8' ?>");
writer.append("<manifest xmlns=\"http://openrosa.org/xforms/xformsManifest\">");
NodeIterator nit = node.getNodes();
- while (nit.hasNext()) {
+ children: while (nit.hasNext()) {
Node file = nit.nextNode();
if (file.isNodeType(OrxManifestName.mediaFile.get())) {
- writer.append("<mediaFile>");
+ EntityMimeType mimeType = EntityMimeType
+ .find(file.getProperty(Property.JCR_MIMETYPE).getString());
+ Charset charset = Charset.forName(file.getProperty(Property.JCR_ENCODING).getString());
if (file.isNodeType(NodeType.NT_ADDRESS)) {
- Node target = file.getProperty(Property.JCR_ID).getNode();
+ Node target;
+ try {
+ target = file.getProperty(Property.JCR_ID).getNode();
+ } catch (ItemNotFoundException e) {
+ // TODO remove old manifests
+ continue children;
+ }
+ writer.append("<mediaFile>");
writer.append("<filename>");
// Work around bug in ODK Collect not supporting paths
// writer.append(target.getPath().substring(1) + ".xml");
- writer.append(target.getIdentifier() + ".xml");
+ writer.append(target.getIdentifier() + "." + mimeType.getDefaultExtension());
writer.append("</filename>");
-// StringBuilder xml = new StringBuilder();
-// xml.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
-// JcrUtils.toSimpleXml(target, xml);
-// String fileCsum = DigestUtils.digest(DigestUtils.MD5,
-// xml.toString().getBytes(StandardCharsets.UTF_8));
-// writer.append("<hash>");
-// writer.append("md5sum:" + fileCsum);
-// writer.append("</hash>");
-
- try (ByteArrayOutputStream out = new ByteArrayOutputStream()) {
- session.exportDocumentView(target.getPath(), out, true, false);
- String fileCsum = DigestUtils.digest(DigestUtils.MD5, out.toByteArray());
-// JcrxApi.addChecksum(file, fileCsum);
+ MessageDigest messageDigest = MessageDigest.getInstance(DigestUtils.MD5);
+ // TODO cache a temp file ?
+ try (DigestOutputStream out = new DigestOutputStream(new NullOutputStream(),
+ messageDigest)) {
+ writeMediaFile(out, target, mimeType, charset);
writer.append("<hash>");
- writer.append("md5sum:" + fileCsum);
+ writer.append("md5sum:" + DigestUtils.encodeHexString(out.getMessageDigest().digest()));
writer.append("</hash>");
}
+
+// try (ByteArrayOutputStream out = new ByteArrayOutputStream()) {
+// session.exportDocumentView(target.getPath(), out, true, false);
+// String fileCsum = DigestUtils.digest(DigestUtils.MD5, out.toByteArray());
+// writer.append("<hash>");
+// writer.append("md5sum:" + fileCsum);
+// writer.append("</hash>");
+// }
writer.append("<downloadUrl>" + protocol + "://" + serverName
+ (serverPort == 80 || serverPort == 443 ? "" : ":" + serverPort)
+ "/api/odk/formManifest" + file.getPath() + "</downloadUrl>");
writer.append("</manifest>");
} else if (node.isNodeType(OrxManifestName.mediaFile.get())) {
+ EntityMimeType mimeType = EntityMimeType.find(node.getProperty(Property.JCR_MIMETYPE).getString());
+ Charset charset = Charset.forName(node.getProperty(Property.JCR_ENCODING).getString());
+ resp.setContentType(mimeType.toHttpContentType(charset));
if (node.isNodeType(NodeType.NT_ADDRESS)) {
Node target = node.getProperty(Property.JCR_ID).getNode();
-// StringBuilder xml = new StringBuilder();
-// xml.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
-// JcrUtils.toSimpleXml(target, xml);
-// System.out.println(xml);
-// resp.getOutputStream().write(xml.toString().getBytes(StandardCharsets.UTF_8));
-// resp.flushBuffer();
-
- try (ByteArrayOutputStream out = new ByteArrayOutputStream()) {
- session.exportDocumentView(target.getPath(), out, true, false);
- System.out.println(new String(out.toByteArray(), StandardCharsets.UTF_8));
- resp.getOutputStream().write(out.toByteArray());
- }
+ writeMediaFile(resp.getOutputStream(), target, mimeType, charset);
+// try (ByteArrayOutputStream out = new ByteArrayOutputStream()) {
+// session.exportDocumentView(target.getPath(), out, true, false);
+// System.out.println(new String(out.toByteArray(), StandardCharsets.UTF_8));
+// resp.getOutputStream().write(out.toByteArray());
+// }
} else {
throw new IllegalArgumentException("Unsupported node " + node);
}
}
} catch (RepositoryException e) {
throw new JcrException(e);
+ } catch (NoSuchAlgorithmException e) {
+ throw new ServletException(e);
} finally {
Jcr.logout(session);
}
}
+ protected void writeMediaFile(OutputStream out, Node target, EntityMimeType mimeType, Charset charset)
+ throws RepositoryException, IOException {
+ if (target.isNodeType(NodeType.NT_QUERY)) {
+ Query query = target.getSession().getWorkspace().getQueryManager().getQuery(target);
+ QueryResult queryResult = query.execute();
+ String[] columnNames = queryResult.getColumnNames();
+ if (EntityMimeType.XML.equals(mimeType)) {
+ } else if (EntityMimeType.CSV.equals(mimeType)) {
+ CsvWriter csvWriter = new CsvWriter(out, charset);
+ csvWriter.writeLine(columnNames);
+ RowIterator rit = queryResult.getRows();
+ while (rit.hasNext()) {
+ Row row = rit.nextRow();
+ Value[] values = row.getValues();
+ List<String> lst = new ArrayList<>();
+ for (Value value : values) {
+ lst.add(value.getString());
+ }
+ csvWriter.writeLine(lst);
+ }
+ }
+ } else {
+ if (EntityMimeType.XML.equals(mimeType)) {
+ target.getSession().exportDocumentView(target.getPath(), out, true, false);
+ } else if (EntityMimeType.CSV.equals(mimeType)) {
+ CsvWriter csvWriter = new CsvWriter(out, charset);
+ csvWriter.writeLine(new String[] { "name", "label" });
+ NodeIterator children = target.getNodes();
+ while (children.hasNext()) {
+ Node child = children.nextNode();
+ String label = Jcr.getTitle(child);
+ csvWriter.writeLine(new String[] { child.getIdentifier(), label });
+ }
+ }
+
+ }
+
+ }
+
public void setRepository(Repository repository) {
this.repository = repository;
}