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