X-Git-Url: https://git.argeo.org/?a=blobdiff_plain;f=org.argeo.support.odk%2Fsrc%2Forg%2Fargeo%2Fsupport%2Fodk%2Fservlet%2FOdkManifestServlet.java;fp=org.argeo.support.odk%2Fsrc%2Forg%2Fargeo%2Fsupport%2Fodk%2Fservlet%2FOdkManifestServlet.java;h=3510e06ee154b50e7426c38773f01fe8107cd15c;hb=3440f51df3e4c015972c7b6a0efb3ce16188b89b;hp=0000000000000000000000000000000000000000;hpb=752a7b2614895002a3d184be166ef4162caf0d05;p=gpl%2Fargeo-suite.git diff --git a/org.argeo.support.odk/src/org/argeo/support/odk/servlet/OdkManifestServlet.java b/org.argeo.support.odk/src/org/argeo/support/odk/servlet/OdkManifestServlet.java new file mode 100644 index 0000000..3510e06 --- /dev/null +++ b/org.argeo.support.odk/src/org/argeo/support/odk/servlet/OdkManifestServlet.java @@ -0,0 +1,189 @@ +package org.argeo.support.odk.servlet; + +import java.io.IOException; +import java.io.OutputStream; +import java.io.Writer; +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. */ +public class OdkManifestServlet extends HttpServlet { + private static final long serialVersionUID = 138030510865877478L; + + private Repository repository; + + @Override + protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { + resp.setHeader("X-OpenRosa-Version", "1.0"); + resp.setDateHeader("Date", System.currentTimeMillis()); + + String pathInfo = req.getPathInfo(); + if (pathInfo.startsWith("//")) + pathInfo = pathInfo.substring(1); + + String serverName = req.getServerName(); + int serverPort = req.getServerPort(); + String protocol = serverPort == 443 || req.isSecure() ? "https" : "http"; + + Session session = ServletAuthUtils.doAs(() -> Jcr.login(repository, null), req); + + try { + Node node = session.getNode(pathInfo); + if (node.isNodeType(OrxManifestName.manifest.get())) { + resp.setContentType(EntityMimeType.XML.toHttpContentType()); + Writer writer = resp.getWriter(); + writer.append(""); + writer.append(""); + NodeIterator nit = node.getNodes(); + children: while (nit.hasNext()) { + Node file = nit.nextNode(); + if (file.isNodeType(OrxManifestName.mediaFile.get())) { + 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; + try { + target = file.getProperty(Property.JCR_ID).getNode(); + } catch (ItemNotFoundException e) { + // TODO remove old manifests + continue children; + } + writer.append(""); + writer.append(""); + // Work around bug in ODK Collect not supporting paths + // writer.append(target.getPath().substring(1) + ".xml"); + writer.append(target.getIdentifier() + "." + mimeType.getDefaultExtension()); + writer.append(""); + + 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(""); + writer.append("md5sum:" + DigestUtils.encodeHexString(out.getMessageDigest().digest())); + writer.append(""); + } + +// try (ByteArrayOutputStream out = new ByteArrayOutputStream()) { +// session.exportDocumentView(target.getPath(), out, true, false); +// String fileCsum = DigestUtils.digest(DigestUtils.MD5, out.toByteArray()); +// writer.append(""); +// writer.append("md5sum:" + fileCsum); +// writer.append(""); +// } + writer.append("" + protocol + "://" + serverName + + (serverPort == 80 || serverPort == 443 ? "" : ":" + serverPort) + + "/api/odk/formManifest" + file.getPath() + ""); + } + writer.append(""); + } + } + + writer.append(""); + } 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(); + + 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); + } + } 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 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; + } + +}