X-Git-Url: https://git.argeo.org/?a=blobdiff_plain;f=org.argeo.maintenance%2Fsrc%2Forg%2Fargeo%2Fmaintenance%2Fbackup%2FBackupContentHandler.java;fp=org.argeo.maintenance%2Fsrc%2Forg%2Fargeo%2Fmaintenance%2Fbackup%2FBackupContentHandler.java;h=099323833dfe6da23fdfc07a641428ccbf5d15d6;hb=9e5ea515aa9a855645c9d20c478c14770264a5cb;hp=0000000000000000000000000000000000000000;hpb=2cdcc7410782f46eac9a4a505de12e33f67acf15;p=lgpl%2Fargeo-commons.git diff --git a/org.argeo.maintenance/src/org/argeo/maintenance/backup/BackupContentHandler.java b/org.argeo.maintenance/src/org/argeo/maintenance/backup/BackupContentHandler.java new file mode 100644 index 000000000..099323833 --- /dev/null +++ b/org.argeo.maintenance/src/org/argeo/maintenance/backup/BackupContentHandler.java @@ -0,0 +1,195 @@ +package org.argeo.maintenance.backup; + +import java.io.IOException; +import java.io.InputStream; +import java.io.Writer; +import java.util.Base64; +import java.util.Set; +import java.util.TreeSet; + +import javax.jcr.Binary; +import javax.jcr.RepositoryException; +import javax.jcr.Session; + +import org.apache.commons.io.IOUtils; +import org.xml.sax.Attributes; +import org.xml.sax.SAXException; +import org.xml.sax.helpers.DefaultHandler; + +public class BackupContentHandler extends DefaultHandler { + final static int MAX_DEPTH = 1024; + final static String SV_NAMESPACE_URI = "http://www.jcp.org/jcr/sv/1.0"; + // elements + final static String NODE = "node"; + final static String PROPERTY = "property"; + final static String VALUE = "value"; + // attributes + final static String NAME = "name"; + final static String MULTIPLE = "multiple"; + final static String TYPE = "type"; + + // values + final static String BINARY = "Binary"; + final static String JCR_CONTENT = "jcr:content"; + + private Writer out; + private Session session; + private Set contentPaths = new TreeSet<>(); + + public BackupContentHandler(Writer out, Session session) { + super(); + this.out = out; + this.session = session; + } + + private int currentDepth = -1; + private String[] currentPath = new String[MAX_DEPTH]; + + private boolean currentPropertyIsMultiple = false; + private String currentEncoded = null; + private Base64.Encoder base64encore = Base64.getEncoder(); + + @Override + public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { + boolean isNode; + boolean isProperty; + switch (localName) { + case NODE: + isNode = true; + isProperty = false; + break; + case PROPERTY: + isNode = false; + isProperty = true; + break; + default: + isNode = false; + isProperty = false; + } + + if (isNode) { + String nodeName = attributes.getValue(SV_NAMESPACE_URI, NAME); + currentDepth = currentDepth + 1; + if (currentDepth > 0) + currentPath[currentDepth - 1] = nodeName; +// System.out.println(getCurrentPath() + " , depth=" + currentDepth); + } + + if (SV_NAMESPACE_URI.equals(uri)) + try { + out.write("<"); + out.write(localName); + if (isProperty) + currentPropertyIsMultiple = false; // always reset + for (int i = 0; i < attributes.getLength(); i++) { + String ns = attributes.getURI(i); + if (SV_NAMESPACE_URI.equals(ns)) { + String attrName = attributes.getLocalName(i); + String attrValue = attributes.getValue(i); + out.write(" "); + out.write(attrName); + out.write("="); + out.write("\""); + out.write(attrValue); + out.write("\""); + if (isProperty) { + if (MULTIPLE.equals(attrName)) + currentPropertyIsMultiple = Boolean.parseBoolean(attrValue); + else if (TYPE.equals(attrName)) { + if (BINARY.equals(attrValue)) { + if (JCR_CONTENT.equals(getCurrentName())) { + contentPaths.add(getCurrentPath()); + } else { + Binary binary = session.getNode(getCurrentPath()).getProperty(attrName) + .getBinary(); + try (InputStream in = binary.getStream()) { + currentEncoded = base64encore.encodeToString(IOUtils.toByteArray(in)); + } finally { + + } + } + } + } + } + } + } + if (currentDepth == 0) { + out.write(" xmlns=\"" + SV_NAMESPACE_URI + "\""); + } + out.write(">"); + if (isNode) + out.write("\n"); + else if (isProperty && currentPropertyIsMultiple) + out.write("\n"); + } catch (IOException | RepositoryException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + + @Override + public void endElement(String uri, String localName, String qName) throws SAXException { + if (localName.equals(NODE)) { +// System.out.println("endElement " + getCurrentPath() + " , depth=" + currentDepth); + if (currentDepth > 0) + currentPath[currentDepth - 1] = null; + currentDepth = currentDepth - 1; + } + boolean isValue = localName.equals(VALUE); + if (SV_NAMESPACE_URI.equals(uri)) + try { + if (isValue && currentEncoded != null) { + out.write(currentEncoded); + } + currentEncoded = null; + out.write(""); + if (!isValue) + out.write("\n"); + else { + if (currentPropertyIsMultiple) + out.write("\n"); + } + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + + @Override + public void characters(char[] ch, int start, int length) throws SAXException { + try { + out.write(ch, start, length); + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + + protected String getCurrentName() { + assert currentDepth >= 0; + if (currentDepth == 0) + return "jcr:root"; + return currentPath[currentDepth - 1]; + } + + protected String getCurrentPath() { + if (currentDepth == 0) + return "/"; + StringBuilder sb = new StringBuilder("/"); + for (int i = 0; i < currentDepth; i++) { + if (i != 0) + sb.append('/'); + sb.append(currentPath[i]); + } + return sb.toString(); + } + + public Set getContentPaths() { + return contentPaths; + } + + + +}