1 package org
.argeo
.util
.dav
;
3 import java
.io
.InputStream
;
4 import java
.util
.Iterator
;
5 import java
.util
.concurrent
.ArrayBlockingQueue
;
6 import java
.util
.concurrent
.BlockingQueue
;
7 import java
.util
.concurrent
.CompletableFuture
;
8 import java
.util
.concurrent
.ExecutionException
;
9 import java
.util
.concurrent
.ForkJoinPool
;
10 import java
.util
.concurrent
.atomic
.AtomicBoolean
;
12 import javax
.xml
.namespace
.QName
;
13 import javax
.xml
.stream
.FactoryConfigurationError
;
14 import javax
.xml
.stream
.XMLInputFactory
;
15 import javax
.xml
.stream
.XMLStreamConstants
;
16 import javax
.xml
.stream
.XMLStreamException
;
17 import javax
.xml
.stream
.XMLStreamReader
;
19 class MultiStatusReader
implements Iterator
<DavResponse
> {
20 private CompletableFuture
<Boolean
> empty
= new CompletableFuture
<Boolean
>();
21 private AtomicBoolean processed
= new AtomicBoolean(false);
23 private BlockingQueue
<DavResponse
> queue
= new ArrayBlockingQueue
<>(64);
25 private final String ignoredHref
;
27 public MultiStatusReader(InputStream in
) {
31 /** Typically ignoring self */
32 public MultiStatusReader(InputStream in
, String ignoredHref
) {
33 this.ignoredHref
= ignoredHref
;
34 ForkJoinPool
.commonPool().execute(() -> process(in
));
38 protected void process(InputStream in
) {
40 XMLInputFactory inputFactory
= XMLInputFactory
.newFactory();
41 XMLStreamReader reader
= inputFactory
.createXMLStreamReader(in
);
43 DavResponse currentResponse
= null;
44 boolean collectiongProperties
= false;
46 final QName COLLECTION
= DavXmlElement
.collection
.qName(); // optimisation
47 elements
: while (reader
.hasNext()) {
49 if (reader
.isStartElement()) {
50 QName name
= reader
.getName();
51 // System.out.println(name);
52 DavXmlElement davXmlElement
= DavXmlElement
.toEnum(name
);
53 if (davXmlElement
!= null) {
54 switch (davXmlElement
) {
56 currentResponse
= new DavResponse();
59 assert currentResponse
!= null;
60 while (reader
.hasNext() && !reader
.hasText())
62 String href
= reader
.getText();
63 currentResponse
.setHref(href
);
66 // currentResponse.setCollection(true);
69 collectiongProperties
= true;
72 while (reader
.hasNext()) {
73 int event
= reader
.nextTag();
74 QName resourceType
= reader
.getName();
75 if (event
== XMLStreamConstants
.END_ELEMENT
&& name
.equals(resourceType
))
77 assert currentResponse
!= null;
78 if (event
== XMLStreamConstants
.START_ELEMENT
) {
79 if (COLLECTION
.equals(resourceType
))
80 currentResponse
.setCollection(true);
82 currentResponse
.getResourceTypes().add(resourceType
);
90 if (collectiongProperties
) {
92 // TODO deal with complex properties
93 readProperty
: while (reader
.hasNext()) {
95 if (reader
.getEventType() == XMLStreamConstants
.END_ELEMENT
)
97 if (reader
.getEventType() == XMLStreamConstants
.CHARACTERS
)
98 value
= reader
.getText();
101 if (name
.getNamespaceURI().equals(DavResponse
.MODE_DAV_NAMESPACE
))
102 continue elements
; // skip mod_dav properties
104 assert currentResponse
!= null;
105 currentResponse
.getPropertyNames().add(name
);
107 currentResponse
.getProperties().put(name
, value
);
111 } else if (reader
.isEndElement()) {
112 QName name
= reader
.getName();
113 // System.out.println(name);
114 DavXmlElement davXmlElement
= DavXmlElement
.toEnum(name
);
115 if (davXmlElement
!= null)
116 switch (davXmlElement
) {
118 assert currentResponse
!= null;
119 if (ignoredHref
== null || !ignoredHref
.equals(currentResponse
.getHref())) {
121 empty
.complete(false);
122 publish(currentResponse
);
125 collectiongProperties
= false;
134 empty
.complete(true);
135 } catch (FactoryConfigurationError
| XMLStreamException e
) {
136 throw new IllegalStateException("Cannot process DAV response", e
);
142 protected synchronized void publish(DavResponse response
) {
145 } catch (InterruptedException e
) {
146 throw new IllegalStateException("Cannot put response " + response
, e
);
152 protected synchronized void processed() {
158 public synchronized boolean hasNext() {
162 while (!processed
.get() && queue
.isEmpty()) {
165 if (!queue
.isEmpty())
169 throw new IllegalStateException("Cannot determine hasNext");
170 } catch (InterruptedException
| ExecutionException e
) {
171 throw new IllegalStateException("Cannot determine hasNext", e
);
178 public synchronized DavResponse
next() {
181 throw new IllegalStateException("No fursther items are available");
183 DavResponse response
= queue
.take();
185 } catch (InterruptedException e
) {
186 throw new IllegalStateException("Cannot get next", e
);