import java.io.IOException;
import java.io.InputStream;
import java.io.Writer;
+import java.util.Arrays;
import java.util.Base64;
import java.util.Set;
import java.util.TreeSet;
import javax.jcr.Binary;
+import javax.jcr.Node;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import org.apache.commons.io.IOUtils;
+import org.argeo.jcr.Jcr;
+import org.argeo.jcr.JcrException;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
+/** XML handler serialising a JCR system view. */
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";
+ final static String SV_PREFIX = "sv";
// elements
final static String NODE = "node";
final static String PROPERTY = "property";
private Session session;
private Set<String> contentPaths = new TreeSet<>();
- public BackupContentHandler(Writer out, Session session) {
+ boolean prettyPrint = true;
+
+ private final String parentPath;
+
+// private boolean inSystem = false;
+
+ public BackupContentHandler(Writer out, Node node) {
super();
this.out = out;
- this.session = session;
+ this.session = Jcr.getSession(node);
+ parentPath = Jcr.getParentPath(node);
}
private int currentDepth = -1;
if (isNode) {
String nodeName = attributes.getValue(SV_NAMESPACE_URI, NAME);
currentDepth = currentDepth + 1;
- if (currentDepth > 0)
- currentPath[currentDepth - 1] = nodeName;
+// if (currentDepth >= 0)
+ currentPath[currentDepth] = nodeName;
// System.out.println(getCurrentPath() + " , depth=" + currentDepth);
+// if ("jcr:system".equals(nodeName)) {
+// inSystem = true;
+// }
}
+// if (inSystem)
+// return;
if (SV_NAMESPACE_URI.equals(uri))
try {
+ if (prettyPrint) {
+ if (isNode) {
+ out.write(spaces());
+ out.write("<!-- ");
+ out.write(getCurrentJcrPath());
+ out.write(" -->\n");
+ out.write(spaces());
+ } else if (isProperty)
+ out.write(spaces());
+ else if (currentPropertyIsMultiple)
+ out.write(spaces());
+ }
+
out.write("<");
- out.write(localName);
+ out.write(SV_PREFIX + ":" + localName);
if (isProperty)
currentPropertyIsMultiple = false; // always reset
for (int i = 0; i < attributes.getLength(); i++) {
String attrName = attributes.getLocalName(i);
String attrValue = attributes.getValue(i);
out.write(" ");
- out.write(attrName);
+ out.write(SV_PREFIX + ":" + attrName);
out.write("=");
out.write("\"");
out.write(attrValue);
else if (TYPE.equals(attrName)) {
if (BINARY.equals(attrValue)) {
if (JCR_CONTENT.equals(getCurrentName())) {
- contentPaths.add(getCurrentPath());
+ contentPaths.add(getCurrentJcrPath());
} else {
- Binary binary = session.getNode(getCurrentPath()).getProperty(attrName)
+ Binary binary = session.getNode(getCurrentJcrPath()).getProperty(attrName)
.getBinary();
try (InputStream in = binary.getStream()) {
currentEncoded = base64encore.encodeToString(IOUtils.toByteArray(in));
}
}
}
- if (currentDepth == 0) {
- out.write(" xmlns=\"" + SV_NAMESPACE_URI + "\"");
+ if (isNode && currentDepth == 0) {
+ // out.write(" xmlns=\"" + SV_NAMESPACE_URI + "\"");
+ out.write(" xmlns:" + SV_PREFIX + "=\"" + 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();
+
+ if (prettyPrint)
+ if (isNode)
+ out.write("\n");
+ else if (isProperty && currentPropertyIsMultiple)
+ out.write("\n");
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ } catch (RepositoryException e) {
+ throw new JcrException(e);
}
}
@Override
public void endElement(String uri, String localName, String qName) throws SAXException {
- if (localName.equals(NODE)) {
+ boolean isNode = localName.equals(NODE);
+ boolean isValue = localName.equals(VALUE);
+ if (prettyPrint)
+ if (!isValue)
+ try {
+ if (isNode || currentPropertyIsMultiple)
+ out.write(spaces());
+ } catch (IOException e1) {
+ throw new RuntimeException(e1);
+ }
+ if (isNode) {
// System.out.println("endElement " + getCurrentPath() + " , depth=" + currentDepth);
- if (currentDepth > 0)
- currentPath[currentDepth - 1] = null;
+// if (currentDepth > 0)
+ currentPath[currentDepth] = null;
currentDepth = currentDepth - 1;
+// if (inSystem) {
+// // System.out.println("Skip " + getCurrentPath()+" ,
+// // currentDepth="+currentDepth);
+// if (currentDepth == 0) {
+// inSystem = false;
+// return;
+// }
+// }
}
- boolean isValue = localName.equals(VALUE);
+// if (inSystem)
+// return;
if (SV_NAMESPACE_URI.equals(uri))
try {
if (isValue && currentEncoded != null) {
}
currentEncoded = null;
out.write("</");
- out.write(localName);
+ out.write(SV_PREFIX + ":" + localName);
out.write(">");
- if (!isValue)
- out.write("\n");
- else {
- if (currentPropertyIsMultiple)
+ if (prettyPrint)
+ if (!isValue)
out.write("\n");
- }
+ else {
+ if (currentPropertyIsMultiple)
+ out.write("\n");
+ }
+ if (currentDepth == 0)
+ out.flush();
} catch (IOException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
+ throw new RuntimeException(e);
}
+
+ }
+
+ private char[] spaces() {
+ char[] arr = new char[currentDepth];
+ Arrays.fill(arr, ' ');
+ return arr;
}
@Override
public void characters(char[] ch, int start, int length) throws SAXException {
+// if (inSystem)
+// return;
try {
out.write(ch, start, length);
} catch (IOException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
+ throw new RuntimeException(e);
}
}
protected String getCurrentName() {
assert currentDepth >= 0;
- if (currentDepth == 0)
- return "jcr:root";
- return currentPath[currentDepth - 1];
+// if (currentDepth == 0)
+// return "jcr:root";
+ return currentPath[currentDepth];
}
- protected String getCurrentPath() {
- if (currentDepth == 0)
- return "/";
- StringBuilder sb = new StringBuilder("/");
- for (int i = 0; i < currentDepth; i++) {
- if (i != 0)
- sb.append('/');
+ protected String getCurrentJcrPath() {
+// if (currentDepth == 0)
+// return "/";
+ StringBuilder sb = new StringBuilder(parentPath.equals("/") ? "" : parentPath);
+ for (int i = 0; i <= currentDepth; i++) {
+// if (i != 0)
+ sb.append('/');
sb.append(currentPath[i]);
}
return sb.toString();
return contentPaths;
}
-
-
}