]> git.argeo.org Git - lgpl/argeo-commons.git/blob - BackupContentHandler.java
099323833dfe6da23fdfc07a641428ccbf5d15d6
[lgpl/argeo-commons.git] / BackupContentHandler.java
1 package org.argeo.maintenance.backup;
2
3 import java.io.IOException;
4 import java.io.InputStream;
5 import java.io.Writer;
6 import java.util.Base64;
7 import java.util.Set;
8 import java.util.TreeSet;
9
10 import javax.jcr.Binary;
11 import javax.jcr.RepositoryException;
12 import javax.jcr.Session;
13
14 import org.apache.commons.io.IOUtils;
15 import org.xml.sax.Attributes;
16 import org.xml.sax.SAXException;
17 import org.xml.sax.helpers.DefaultHandler;
18
19 public class BackupContentHandler extends DefaultHandler {
20 final static int MAX_DEPTH = 1024;
21 final static String SV_NAMESPACE_URI = "http://www.jcp.org/jcr/sv/1.0";
22 // elements
23 final static String NODE = "node";
24 final static String PROPERTY = "property";
25 final static String VALUE = "value";
26 // attributes
27 final static String NAME = "name";
28 final static String MULTIPLE = "multiple";
29 final static String TYPE = "type";
30
31 // values
32 final static String BINARY = "Binary";
33 final static String JCR_CONTENT = "jcr:content";
34
35 private Writer out;
36 private Session session;
37 private Set<String> contentPaths = new TreeSet<>();
38
39 public BackupContentHandler(Writer out, Session session) {
40 super();
41 this.out = out;
42 this.session = session;
43 }
44
45 private int currentDepth = -1;
46 private String[] currentPath = new String[MAX_DEPTH];
47
48 private boolean currentPropertyIsMultiple = false;
49 private String currentEncoded = null;
50 private Base64.Encoder base64encore = Base64.getEncoder();
51
52 @Override
53 public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
54 boolean isNode;
55 boolean isProperty;
56 switch (localName) {
57 case NODE:
58 isNode = true;
59 isProperty = false;
60 break;
61 case PROPERTY:
62 isNode = false;
63 isProperty = true;
64 break;
65 default:
66 isNode = false;
67 isProperty = false;
68 }
69
70 if (isNode) {
71 String nodeName = attributes.getValue(SV_NAMESPACE_URI, NAME);
72 currentDepth = currentDepth + 1;
73 if (currentDepth > 0)
74 currentPath[currentDepth - 1] = nodeName;
75 // System.out.println(getCurrentPath() + " , depth=" + currentDepth);
76 }
77
78 if (SV_NAMESPACE_URI.equals(uri))
79 try {
80 out.write("<");
81 out.write(localName);
82 if (isProperty)
83 currentPropertyIsMultiple = false; // always reset
84 for (int i = 0; i < attributes.getLength(); i++) {
85 String ns = attributes.getURI(i);
86 if (SV_NAMESPACE_URI.equals(ns)) {
87 String attrName = attributes.getLocalName(i);
88 String attrValue = attributes.getValue(i);
89 out.write(" ");
90 out.write(attrName);
91 out.write("=");
92 out.write("\"");
93 out.write(attrValue);
94 out.write("\"");
95 if (isProperty) {
96 if (MULTIPLE.equals(attrName))
97 currentPropertyIsMultiple = Boolean.parseBoolean(attrValue);
98 else if (TYPE.equals(attrName)) {
99 if (BINARY.equals(attrValue)) {
100 if (JCR_CONTENT.equals(getCurrentName())) {
101 contentPaths.add(getCurrentPath());
102 } else {
103 Binary binary = session.getNode(getCurrentPath()).getProperty(attrName)
104 .getBinary();
105 try (InputStream in = binary.getStream()) {
106 currentEncoded = base64encore.encodeToString(IOUtils.toByteArray(in));
107 } finally {
108
109 }
110 }
111 }
112 }
113 }
114 }
115 }
116 if (currentDepth == 0) {
117 out.write(" xmlns=\"" + SV_NAMESPACE_URI + "\"");
118 }
119 out.write(">");
120 if (isNode)
121 out.write("\n");
122 else if (isProperty && currentPropertyIsMultiple)
123 out.write("\n");
124 } catch (IOException | RepositoryException e) {
125 // TODO Auto-generated catch block
126 e.printStackTrace();
127 }
128 }
129
130 @Override
131 public void endElement(String uri, String localName, String qName) throws SAXException {
132 if (localName.equals(NODE)) {
133 // System.out.println("endElement " + getCurrentPath() + " , depth=" + currentDepth);
134 if (currentDepth > 0)
135 currentPath[currentDepth - 1] = null;
136 currentDepth = currentDepth - 1;
137 }
138 boolean isValue = localName.equals(VALUE);
139 if (SV_NAMESPACE_URI.equals(uri))
140 try {
141 if (isValue && currentEncoded != null) {
142 out.write(currentEncoded);
143 }
144 currentEncoded = null;
145 out.write("</");
146 out.write(localName);
147 out.write(">");
148 if (!isValue)
149 out.write("\n");
150 else {
151 if (currentPropertyIsMultiple)
152 out.write("\n");
153 }
154 } catch (IOException e) {
155 // TODO Auto-generated catch block
156 e.printStackTrace();
157 }
158 }
159
160 @Override
161 public void characters(char[] ch, int start, int length) throws SAXException {
162 try {
163 out.write(ch, start, length);
164 } catch (IOException e) {
165 // TODO Auto-generated catch block
166 e.printStackTrace();
167 }
168 }
169
170 protected String getCurrentName() {
171 assert currentDepth >= 0;
172 if (currentDepth == 0)
173 return "jcr:root";
174 return currentPath[currentDepth - 1];
175 }
176
177 protected String getCurrentPath() {
178 if (currentDepth == 0)
179 return "/";
180 StringBuilder sb = new StringBuilder("/");
181 for (int i = 0; i < currentDepth; i++) {
182 if (i != 0)
183 sb.append('/');
184 sb.append(currentPath[i]);
185 }
186 return sb.toString();
187 }
188
189 public Set<String> getContentPaths() {
190 return contentPaths;
191 }
192
193
194
195 }