1 package org
.argeo
.cms
.jcr
.acr
;
3 import java
.io
.IOException
;
4 import java
.io
.InputStream
;
5 import java
.io
.PipedInputStream
;
6 import java
.io
.PipedOutputStream
;
7 import java
.util
.HashSet
;
9 import java
.util
.concurrent
.CompletableFuture
;
10 import java
.util
.concurrent
.ExecutionException
;
12 import javax
.jcr
.Node
;
13 import javax
.jcr
.NodeIterator
;
14 import javax
.jcr
.RepositoryException
;
15 import javax
.jcr
.nodetype
.NodeType
;
16 import javax
.xml
.XMLConstants
;
17 import javax
.xml
.namespace
.QName
;
18 import javax
.xml
.parsers
.DocumentBuilder
;
19 import javax
.xml
.parsers
.DocumentBuilderFactory
;
20 import javax
.xml
.parsers
.ParserConfigurationException
;
21 import javax
.xml
.transform
.Source
;
22 import javax
.xml
.transform
.dom
.DOMSource
;
24 import org
.argeo
.api
.acr
.Content
;
25 import org
.argeo
.api
.acr
.ContentName
;
26 import org
.argeo
.api
.acr
.CrName
;
27 import org
.argeo
.api
.acr
.NamespaceUtils
;
28 import org
.argeo
.api
.acr
.spi
.ProvidedContent
;
29 import org
.argeo
.api
.acr
.spi
.ProvidedSession
;
30 import org
.argeo
.api
.cms
.CmsLog
;
31 import org
.argeo
.jcr
.Jcr
;
32 import org
.argeo
.jcr
.JcrException
;
33 import org
.argeo
.jcr
.JcrUtils
;
34 import org
.w3c
.dom
.Attr
;
35 import org
.w3c
.dom
.Document
;
36 import org
.w3c
.dom
.Element
;
37 import org
.w3c
.dom
.NamedNodeMap
;
38 import org
.w3c
.dom
.NodeList
;
39 import org
.xml
.sax
.SAXException
;
41 /** Utilities around integration between JCR and ACR. */
42 public class JcrContentUtils
{
43 private final static CmsLog log
= CmsLog
.getLog(JcrContentUtils
.class);
45 public static void copyFiles(Node folder
, Content collection
, String
... additionalCollectionTypes
) {
47 log
.debug("Copy collection " + collection
);
48 nodes
: for (NodeIterator it
= folder
.getNodes(); it
.hasNext();) {
49 Node node
= it
.nextNode();
50 String name
= node
.getName();
51 if (node
.isNodeType(NodeType
.NT_FILE
)) {
52 Content file
= collection
.anyOrAddChild(new ContentName(name
));
53 try (InputStream in
= JcrUtils
.getFileAsStream(node
)) {
54 file
.write(InputStream
.class).complete(in
);
56 } else if (node
.isNodeType(NodeType
.NT_FOLDER
)) {
57 Content subCol
= collection
.add(name
, CrName
.collection
.qName());
58 copyFiles(node
, subCol
, additionalCollectionTypes
);
60 for (String collectionType
: additionalCollectionTypes
) {
61 if (node
.isNodeType(collectionType
)) {
62 Content subCol
= collection
.add(name
, CrName
.collection
.qName());
63 copyFiles(node
, subCol
, additionalCollectionTypes
);
68 QName qName
= NamespaceUtils
.parsePrefixedName(name
);
69 // if (NamespaceUtils.hasNamespace(qName)) {
70 if (node
.getIndex() > 1) {
71 log
.warn("Same name siblings not supported, skipping " + node
);
74 Content content
= collection
.add(qName
, qName
);
75 Source source
= toSource(node
);
76 ((ProvidedContent
) content
).getSession().edit((s
) -> {
77 ((ProvidedSession
) s
).notifyModification((ProvidedContent
) content
);
78 content
.write(Source
.class).complete(source
);
79 }).toCompletableFuture().join();
83 // log.debug(() -> "Ignored " + node);
88 } catch (RepositoryException e
) {
89 throw new JcrException("Cannot copy files from " + folder
+ " to " + collection
, e
);
90 } catch (IOException e
) {
91 throw new RuntimeException("Cannot copy files from " + folder
+ " to " + collection
, e
);
95 private static Source
toSource(Node node
) {
96 try (PipedInputStream in
= new PipedInputStream();) {
98 CompletableFuture
<Document
> toDo
= CompletableFuture
.supplyAsync(() -> {
100 DocumentBuilder documentBuilder
= DocumentBuilderFactory
.newNSInstance().newDocumentBuilder();
101 return documentBuilder
.parse(in
);
102 } catch (ParserConfigurationException
| SAXException
| IOException e
) {
103 throw new RuntimeException("Cannot parse", e
);
108 try (PipedOutputStream out
= new PipedOutputStream(in
)) {
109 node
.getSession().exportDocumentView(node
.getPath(), out
, true, false);
110 } catch (IOException
| RepositoryException e
) {
111 throw new RuntimeException("Cannot export " + node
+ " in workspace " + Jcr
.getWorkspaceName(node
), e
);
113 Document document
= toDo
.get();
114 cleanJcrDom(document
);
115 return new DOMSource(document
);
116 } catch (IOException
| InterruptedException
| ExecutionException e1
) {
117 throw new RuntimeException("Cannot parse", e1
);
122 static final String JCR_NAMESPACE_URI
= "http://www.jcp.org/jcr/1.0";
124 public static void cleanJcrDom(Document document
) {
125 Element documentElement
= document
.getDocumentElement();
126 Set
<String
> namespaceUris
= new HashSet
<>();
127 cleanJcrDom(documentElement
, namespaceUris
);
129 // remove unused namespaces
130 NamedNodeMap attrs
= documentElement
.getAttributes();
131 Set
<Attr
> toRemove
= new HashSet
<>();
132 for (int i
= 0; i
< attrs
.getLength(); i
++) {
133 Attr attr
= (Attr
) attrs
.item(i
);
134 // log.debug("Check "+i+" " + attr);
135 String prefix
= attr
.getPrefix();
136 if (prefix
!= null && prefix
.equals(XMLConstants
.XMLNS_ATTRIBUTE
)) {
137 String namespaceUri
= attr
.getValue();
138 if (!namespaceUris
.contains(namespaceUri
)) {
140 // log.debug("Removing "+i+" " + namespaceUri);
144 for (Attr attr
: toRemove
)
145 documentElement
.removeAttributeNode(attr
);
149 private static void cleanJcrDom(Element element
, Set
<String
> namespaceUris
) {
150 NodeList children
= element
.getElementsByTagName("*");
151 for (int i
= 0; i
< children
.getLength(); i
++) {
152 Element child
= (Element
) children
.item(i
);
153 if (!namespaceUris
.contains(child
.getNamespaceURI()))
154 namespaceUris
.add(child
.getNamespaceURI());
155 cleanJcrDom(child
, namespaceUris
);
158 NamedNodeMap attrs
= element
.getAttributes();
159 attributes
: for (int i
= 0; i
< attrs
.getLength(); i
++) {
160 Attr attr
= (Attr
) attrs
.item(i
);
161 String namespaceUri
= attr
.getNamespaceURI();
162 if (namespaceUri
== null)
164 if (JCR_NAMESPACE_URI
.equals(namespaceUri
)) {
165 element
.removeAttributeNode(attr
);
168 if (!namespaceUris
.contains(namespaceUri
))
169 namespaceUris
.add(attr
.getNamespaceURI());
176 private JcrContentUtils() {