]> git.argeo.org Git - lgpl/argeo-commons.git/blob - org.argeo.cms/src/org/argeo/cms/dav/MultiStatusWriter.java
4c06b032f092d04623ba61dff316c549224a0f5f
[lgpl/argeo-commons.git] / org.argeo.cms / src / org / argeo / cms / dav / MultiStatusWriter.java
1 package org.argeo.cms.dav;
2
3 import java.io.IOException;
4 import java.io.OutputStream;
5 import java.nio.charset.StandardCharsets;
6 import java.util.HashSet;
7 import java.util.Set;
8 import java.util.concurrent.ArrayBlockingQueue;
9 import java.util.concurrent.BlockingQueue;
10 import java.util.concurrent.CompletionStage;
11 import java.util.concurrent.TimeUnit;
12 import java.util.concurrent.atomic.AtomicBoolean;
13 import java.util.function.Consumer;
14
15 import javax.xml.XMLConstants;
16 import javax.xml.namespace.NamespaceContext;
17 import javax.xml.namespace.QName;
18 import javax.xml.stream.FactoryConfigurationError;
19 import javax.xml.stream.XMLOutputFactory;
20 import javax.xml.stream.XMLStreamException;
21 import javax.xml.stream.XMLStreamWriter;
22
23 class MultiStatusWriter implements Consumer<DavResponse> {
24 private BlockingQueue<DavResponse> queue = new ArrayBlockingQueue<>(64);
25
26 // private OutputStream out;
27
28 private Thread processingThread;
29
30 private AtomicBoolean done = new AtomicBoolean(false);
31
32 private AtomicBoolean polling = new AtomicBoolean();
33
34 public void process(NamespaceContext namespaceContext, OutputStream out, CompletionStage<Void> published,
35 boolean propname) throws IOException {
36 published.thenRun(() -> allPublished());
37 processingThread = Thread.currentThread();
38 // this.out = out;
39
40 try {
41 XMLOutputFactory xmlOutputFactory = XMLOutputFactory.newFactory();
42 XMLStreamWriter xsWriter = xmlOutputFactory.createXMLStreamWriter(out, StandardCharsets.UTF_8.name());
43 xsWriter.setNamespaceContext(namespaceContext);
44 xsWriter.setDefaultNamespace(DavXmlElement.WEBDAV_NAMESPACE_URI);
45
46 xsWriter.writeStartDocument();
47 DavXmlElement.multistatus.startElement(xsWriter);
48 xsWriter.writeDefaultNamespace(DavXmlElement.WEBDAV_NAMESPACE_URI);
49
50 poll: while (!(done.get() && queue.isEmpty())) {
51 DavResponse davResponse;
52 try {
53 polling.set(true);
54 davResponse = queue.poll(10, TimeUnit.MILLISECONDS);
55 if (davResponse == null)
56 continue poll;
57 System.err.println(davResponse.getHref());
58 } catch (InterruptedException e) {
59 System.err.println(e);
60 continue poll;
61 } finally {
62 polling.set(false);
63 }
64
65 writeDavResponse(xsWriter, davResponse, propname);
66 }
67
68 xsWriter.writeEndElement();// multistatus
69 xsWriter.writeEndDocument();
70 xsWriter.close();
71 out.close();
72 } catch (FactoryConfigurationError | XMLStreamException e) {
73 synchronized (this) {
74 processingThread = null;
75 }
76 }
77 }
78
79 protected void writeDavResponse(XMLStreamWriter xsWriter, DavResponse davResponse, boolean propname)
80 throws XMLStreamException {
81 Set<String> namespaces = new HashSet<>();
82 for (QName key : davResponse.getPropertyNames()) {
83 if (key.getNamespaceURI().equals(DavXmlElement.WEBDAV_NAMESPACE_URI))
84 continue; // skip
85 if (key.getNamespaceURI().equals(XMLConstants.W3C_XML_SCHEMA_NS_URI))
86 continue; // skip
87 namespaces.add(key.getNamespaceURI());
88 }
89 DavXmlElement.response.startElement(xsWriter);
90 // namespaces
91 for (String ns : namespaces)
92 xsWriter.writeNamespace(xsWriter.getNamespaceContext().getPrefix(ns), ns);
93
94 DavXmlElement.href.setSimpleValue(xsWriter, davResponse.getHref());
95
96 {
97 DavXmlElement.propstat.startElement(xsWriter);
98 {
99 DavXmlElement.prop.startElement(xsWriter);
100 if (!davResponse.getResourceTypes().isEmpty() || davResponse.isCollection()) {
101 DavXmlElement.resourcetype.startElement(xsWriter);
102 if (davResponse.isCollection())
103 DavXmlElement.collection.emptyElement(xsWriter);
104 for (QName resourceType : davResponse.getResourceTypes()) {
105 xsWriter.writeEmptyElement(resourceType.getNamespaceURI(), resourceType.getLocalPart());
106 }
107 xsWriter.writeEndElement();// resource type
108 }
109 for (QName key : davResponse.getPropertyNames()) {
110 if (propname) {
111 xsWriter.writeEmptyElement(key.getNamespaceURI(), key.getLocalPart());
112 } else {
113 xsWriter.writeStartElement(key.getNamespaceURI(), key.getLocalPart());
114 xsWriter.writeCData(davResponse.getProperties().get(key));
115 xsWriter.writeEndElement();
116 }
117 }
118 xsWriter.writeEndElement();// prop
119 }
120 xsWriter.writeEndElement();// propstat
121 }
122 xsWriter.writeEndElement();// response
123 }
124
125 @Override
126 public void accept(DavResponse davResponse) {
127 try {
128 queue.put(davResponse);
129 } catch (InterruptedException e) {
130 e.printStackTrace();
131 }
132 }
133
134 protected synchronized void allPublished() {
135 done.set(true);
136 if (processingThread != null && queue.isEmpty() && polling.get()) {
137 // we only interrupt if the queue is already processed
138 // so as not to interrupt I/O
139 processingThread.interrupt();
140 }
141 }
142
143 }