1 package org
.argeo
.maintenance
.backup
;
3 import java
.io
.IOException
;
4 import java
.io
.InputStream
;
6 import java
.util
.Base64
;
8 import java
.util
.TreeSet
;
10 import javax
.jcr
.Binary
;
11 import javax
.jcr
.RepositoryException
;
12 import javax
.jcr
.Session
;
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
;
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";
23 final static String NODE
= "node";
24 final static String PROPERTY
= "property";
25 final static String VALUE
= "value";
27 final static String NAME
= "name";
28 final static String MULTIPLE
= "multiple";
29 final static String TYPE
= "type";
32 final static String BINARY
= "Binary";
33 final static String JCR_CONTENT
= "jcr:content";
36 private Session session
;
37 private Set
<String
> contentPaths
= new TreeSet
<>();
39 public BackupContentHandler(Writer out
, Session session
) {
42 this.session
= session
;
45 private int currentDepth
= -1;
46 private String
[] currentPath
= new String
[MAX_DEPTH
];
48 private boolean currentPropertyIsMultiple
= false;
49 private String currentEncoded
= null;
50 private Base64
.Encoder base64encore
= Base64
.getEncoder();
53 public void startElement(String uri
, String localName
, String qName
, Attributes attributes
) throws SAXException
{
71 String nodeName
= attributes
.getValue(SV_NAMESPACE_URI
, NAME
);
72 currentDepth
= currentDepth
+ 1;
74 currentPath
[currentDepth
- 1] = nodeName
;
75 // System.out.println(getCurrentPath() + " , depth=" + currentDepth);
78 if (SV_NAMESPACE_URI
.equals(uri
))
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
);
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());
103 Binary binary
= session
.getNode(getCurrentPath()).getProperty(attrName
)
105 try (InputStream in
= binary
.getStream()) {
106 currentEncoded
= base64encore
.encodeToString(IOUtils
.toByteArray(in
));
116 if (currentDepth
== 0) {
117 out
.write(" xmlns=\"" + SV_NAMESPACE_URI
+ "\"");
122 else if (isProperty
&& currentPropertyIsMultiple
)
124 } catch (IOException
| RepositoryException e
) {
125 // TODO Auto-generated catch block
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;
138 boolean isValue
= localName
.equals(VALUE
);
139 if (SV_NAMESPACE_URI
.equals(uri
))
141 if (isValue
&& currentEncoded
!= null) {
142 out
.write(currentEncoded
);
144 currentEncoded
= null;
146 out
.write(localName
);
151 if (currentPropertyIsMultiple
)
154 } catch (IOException e
) {
155 // TODO Auto-generated catch block
161 public void characters(char[] ch
, int start
, int length
) throws SAXException
{
163 out
.write(ch
, start
, length
);
164 } catch (IOException e
) {
165 // TODO Auto-generated catch block
170 protected String
getCurrentName() {
171 assert currentDepth
>= 0;
172 if (currentDepth
== 0)
174 return currentPath
[currentDepth
- 1];
177 protected String
getCurrentPath() {
178 if (currentDepth
== 0)
180 StringBuilder sb
= new StringBuilder("/");
181 for (int i
= 0; i
< currentDepth
; i
++) {
184 sb
.append(currentPath
[i
]);
186 return sb
.toString();
189 public Set
<String
> getContentPaths() {