]> git.argeo.org Git - lgpl/argeo-commons.git/blob - org.argeo.cms.jcr/src/org/argeo/maintenance/backup/BackupContentHandler.java
Move time UUID nodeid back to the factory
[lgpl/argeo-commons.git] / org.argeo.cms.jcr / src / org / argeo / maintenance / backup / 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.Arrays;
7 import java.util.Base64;
8 import java.util.Set;
9 import java.util.TreeSet;
10
11 import javax.jcr.Binary;
12 import javax.jcr.Node;
13 import javax.jcr.RepositoryException;
14 import javax.jcr.Session;
15
16 import org.apache.commons.io.IOUtils;
17 import org.argeo.jcr.Jcr;
18 import org.argeo.jcr.JcrException;
19 import org.xml.sax.Attributes;
20 import org.xml.sax.SAXException;
21 import org.xml.sax.helpers.DefaultHandler;
22
23 /** XML handler serialising a JCR system view. */
24 public class BackupContentHandler extends DefaultHandler {
25 final static int MAX_DEPTH = 1024;
26 final static String SV_NAMESPACE_URI = "http://www.jcp.org/jcr/sv/1.0";
27 final static String SV_PREFIX = "sv";
28 // elements
29 final static String NODE = "node";
30 final static String PROPERTY = "property";
31 final static String VALUE = "value";
32 // attributes
33 final static String NAME = "name";
34 final static String MULTIPLE = "multiple";
35 final static String TYPE = "type";
36
37 // values
38 final static String BINARY = "Binary";
39 final static String JCR_CONTENT = "jcr:content";
40
41 private Writer out;
42 private Session session;
43 private Set<String> contentPaths = new TreeSet<>();
44
45 boolean prettyPrint = true;
46
47 private final String parentPath;
48
49 // private boolean inSystem = false;
50
51 public BackupContentHandler(Writer out, Node node) {
52 super();
53 this.out = out;
54 this.session = Jcr.getSession(node);
55 parentPath = Jcr.getParentPath(node);
56 }
57
58 private int currentDepth = -1;
59 private String[] currentPath = new String[MAX_DEPTH];
60
61 private boolean currentPropertyIsMultiple = false;
62 private String currentEncoded = null;
63 private Base64.Encoder base64encore = Base64.getEncoder();
64
65 @Override
66 public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
67 boolean isNode;
68 boolean isProperty;
69 switch (localName) {
70 case NODE:
71 isNode = true;
72 isProperty = false;
73 break;
74 case PROPERTY:
75 isNode = false;
76 isProperty = true;
77 break;
78 default:
79 isNode = false;
80 isProperty = false;
81 }
82
83 if (isNode) {
84 String nodeName = attributes.getValue(SV_NAMESPACE_URI, NAME);
85 currentDepth = currentDepth + 1;
86 // if (currentDepth >= 0)
87 currentPath[currentDepth] = nodeName;
88 // System.out.println(getCurrentPath() + " , depth=" + currentDepth);
89 // if ("jcr:system".equals(nodeName)) {
90 // inSystem = true;
91 // }
92 }
93 // if (inSystem)
94 // return;
95
96 if (SV_NAMESPACE_URI.equals(uri))
97 try {
98 if (prettyPrint) {
99 if (isNode) {
100 out.write(spaces());
101 out.write("<!-- ");
102 out.write(getCurrentJcrPath());
103 out.write(" -->\n");
104 out.write(spaces());
105 } else if (isProperty)
106 out.write(spaces());
107 else if (currentPropertyIsMultiple)
108 out.write(spaces());
109 }
110
111 out.write("<");
112 out.write(SV_PREFIX + ":" + localName);
113 if (isProperty)
114 currentPropertyIsMultiple = false; // always reset
115 for (int i = 0; i < attributes.getLength(); i++) {
116 String ns = attributes.getURI(i);
117 if (SV_NAMESPACE_URI.equals(ns)) {
118 String attrName = attributes.getLocalName(i);
119 String attrValue = attributes.getValue(i);
120 out.write(" ");
121 out.write(SV_PREFIX + ":" + attrName);
122 out.write("=");
123 out.write("\"");
124 out.write(attrValue);
125 out.write("\"");
126 if (isProperty) {
127 if (MULTIPLE.equals(attrName))
128 currentPropertyIsMultiple = Boolean.parseBoolean(attrValue);
129 else if (TYPE.equals(attrName)) {
130 if (BINARY.equals(attrValue)) {
131 if (JCR_CONTENT.equals(getCurrentName())) {
132 contentPaths.add(getCurrentJcrPath());
133 } else {
134 Binary binary = session.getNode(getCurrentJcrPath()).getProperty(attrName)
135 .getBinary();
136 try (InputStream in = binary.getStream()) {
137 currentEncoded = base64encore.encodeToString(IOUtils.toByteArray(in));
138 } finally {
139
140 }
141 }
142 }
143 }
144 }
145 }
146 }
147 if (isNode && currentDepth == 0) {
148 // out.write(" xmlns=\"" + SV_NAMESPACE_URI + "\"");
149 out.write(" xmlns:" + SV_PREFIX + "=\"" + SV_NAMESPACE_URI + "\"");
150 }
151 out.write(">");
152
153 if (prettyPrint)
154 if (isNode)
155 out.write("\n");
156 else if (isProperty && currentPropertyIsMultiple)
157 out.write("\n");
158 } catch (IOException e) {
159 throw new RuntimeException(e);
160 } catch (RepositoryException e) {
161 throw new JcrException(e);
162 }
163 }
164
165 @Override
166 public void endElement(String uri, String localName, String qName) throws SAXException {
167 boolean isNode = localName.equals(NODE);
168 boolean isValue = localName.equals(VALUE);
169 if (prettyPrint)
170 if (!isValue)
171 try {
172 if (isNode || currentPropertyIsMultiple)
173 out.write(spaces());
174 } catch (IOException e1) {
175 throw new RuntimeException(e1);
176 }
177 if (isNode) {
178 // System.out.println("endElement " + getCurrentPath() + " , depth=" + currentDepth);
179 // if (currentDepth > 0)
180 currentPath[currentDepth] = null;
181 currentDepth = currentDepth - 1;
182 // if (inSystem) {
183 // // System.out.println("Skip " + getCurrentPath()+" ,
184 // // currentDepth="+currentDepth);
185 // if (currentDepth == 0) {
186 // inSystem = false;
187 // return;
188 // }
189 // }
190 }
191 // if (inSystem)
192 // return;
193 if (SV_NAMESPACE_URI.equals(uri))
194 try {
195 if (isValue && currentEncoded != null) {
196 out.write(currentEncoded);
197 }
198 currentEncoded = null;
199 out.write("</");
200 out.write(SV_PREFIX + ":" + localName);
201 out.write(">");
202 if (prettyPrint)
203 if (!isValue)
204 out.write("\n");
205 else {
206 if (currentPropertyIsMultiple)
207 out.write("\n");
208 }
209 if (currentDepth == 0)
210 out.flush();
211 } catch (IOException e) {
212 throw new RuntimeException(e);
213 }
214
215 }
216
217 private char[] spaces() {
218 char[] arr = new char[currentDepth];
219 Arrays.fill(arr, ' ');
220 return arr;
221 }
222
223 @Override
224 public void characters(char[] ch, int start, int length) throws SAXException {
225 // if (inSystem)
226 // return;
227 try {
228 out.write(ch, start, length);
229 } catch (IOException e) {
230 throw new RuntimeException(e);
231 }
232 }
233
234 protected String getCurrentName() {
235 assert currentDepth >= 0;
236 // if (currentDepth == 0)
237 // return "jcr:root";
238 return currentPath[currentDepth];
239 }
240
241 protected String getCurrentJcrPath() {
242 // if (currentDepth == 0)
243 // return "/";
244 StringBuilder sb = new StringBuilder(parentPath.equals("/") ? "" : parentPath);
245 for (int i = 0; i <= currentDepth; i++) {
246 // if (i != 0)
247 sb.append('/');
248 sb.append(currentPath[i]);
249 }
250 return sb.toString();
251 }
252
253 public Set<String> getContentPaths() {
254 return contentPaths;
255 }
256
257 }