Skip to content

Commit 1a23a83

Browse files
author
ehennum
committed
streaming implementations of bufferable content handles #1250
1 parent d4b6529 commit 1a23a83

File tree

6 files changed

+186
-97
lines changed

6 files changed

+186
-97
lines changed

marklogic-client-api/src/main/java/com/marklogic/client/io/InputSourceHandle.java

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@
5252
*/
5353
public class InputSourceHandle
5454
extends BaseHandle<InputStream, OutputStreamSender>
55-
implements OutputStreamSender, BufferableHandle, ContentHandle<InputSource>,
55+
implements OutputStreamSender, StreamingContentHandle<InputSource, InputStream>,
5656
XMLReadHandle, XMLWriteHandle,
5757
StructureReadHandle, StructureWriteHandle, CtsQueryWriteHandle,
5858
Closeable
@@ -248,6 +248,27 @@ public byte[] toBuffer() {
248248
throw new MarkLogicIOException(e);
249249
}
250250
}
251+
@Override
252+
public InputSource toContent(InputStream serialization) {
253+
return (serialization == null) ? null :
254+
new InputSource(new InputStreamReader(serialization, StandardCharsets.UTF_8));
255+
}
256+
@Override
257+
public InputSource bytesToContent(byte[] buffer) {
258+
return (buffer == null || buffer.length == 0) ? null :
259+
toContent(new ByteArrayInputStream(buffer));
260+
}
261+
@Override
262+
public byte[] contentToBytes(InputSource content) {
263+
try {
264+
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
265+
sendContent(content).write(buffer);
266+
return buffer.toByteArray();
267+
} catch (IOException e) {
268+
throw new MarkLogicIOException("Could not convert InputSource to byte[] array", e);
269+
}
270+
}
271+
251272
/**
252273
* Buffers the SAX input source and returns the buffer
253274
* as an XML string.
@@ -397,6 +418,10 @@ protected OutputStreamSender sendContent() {
397418

398419
return this;
399420
}
421+
protected OutputStreamSender sendContent(InputSource content) {
422+
return (content == null) ? null :
423+
new OutputStreamSenderImpl(makeTransformer(), makeReader(true), content);
424+
}
400425
@Override
401426
public void write(OutputStream out) throws IOException {
402427
try {
@@ -471,4 +496,28 @@ public void close() {
471496
}
472497
}
473498
}
499+
500+
private static class OutputStreamSenderImpl implements OutputStreamSender {
501+
private final TransformerFactory transformerFactory;
502+
private final XMLReader xmlReader;
503+
private final InputSource content;
504+
private OutputStreamSenderImpl(TransformerFactory transformerFactory, XMLReader xmlReader, InputSource content) {
505+
this.transformerFactory = transformerFactory;
506+
this.xmlReader = xmlReader;
507+
this.content = content;
508+
}
509+
510+
@Override
511+
public void write(OutputStream out) throws IOException {
512+
try {
513+
this.transformerFactory.newTransformer().transform(
514+
new SAXSource(this.xmlReader, this.content),
515+
new StreamResult(new OutputStreamWriter(out, StandardCharsets.UTF_8))
516+
);
517+
} catch (TransformerException e) {
518+
logger.error("Failed to transform input source into result",e);
519+
throw new MarkLogicIOException(e);
520+
}
521+
}
522+
}
474523
}

marklogic-client-api/src/main/java/com/marklogic/client/io/JacksonParserHandle.java

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
import java.io.*;
1919

20+
import com.marklogic.client.io.marker.*;
2021
import org.slf4j.Logger;
2122
import org.slf4j.LoggerFactory;
2223

@@ -26,14 +27,6 @@
2627
import com.fasterxml.jackson.databind.ObjectMapper;
2728
import com.marklogic.client.MarkLogicIOException;
2829
import com.marklogic.client.impl.JacksonBaseHandle;
29-
import com.marklogic.client.io.marker.BufferableHandle;
30-
import com.marklogic.client.io.marker.ContentHandle;
31-
import com.marklogic.client.io.marker.ContentHandleFactory;
32-
import com.marklogic.client.io.marker.CtsQueryWriteHandle;
33-
import com.marklogic.client.io.marker.JSONReadHandle;
34-
import com.marklogic.client.io.marker.JSONWriteHandle;
35-
import com.marklogic.client.io.marker.StructureReadHandle;
36-
import com.marklogic.client.io.marker.StructureWriteHandle;
3730

3831
/**
3932
* <p>An adapter for using the streaming capabilities of the Jackson Open Source library.
@@ -45,8 +38,7 @@
4538
*/
4639
public class JacksonParserHandle
4740
extends JacksonBaseHandle<JsonParser>
48-
implements ContentHandle<JsonParser>,
49-
OutputStreamSender, BufferableHandle,
41+
implements OutputStreamSender, StreamingContentHandle<JsonParser, InputStream>,
5042
JSONReadHandle, JSONWriteHandle,
5143
StructureReadHandle, StructureWriteHandle, CtsQueryWriteHandle,
5244
Closeable

marklogic-client-api/src/main/java/com/marklogic/client/io/ReaderHandle.java

Lines changed: 24 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -25,26 +25,12 @@
2525
import java.io.Reader;
2626
import java.nio.charset.StandardCharsets;
2727

28+
import com.marklogic.client.io.marker.*;
2829
import org.slf4j.Logger;
2930
import org.slf4j.LoggerFactory;
3031

3132
import com.marklogic.client.MarkLogicIOException;
3233
import com.marklogic.client.impl.Utilities;
33-
import com.marklogic.client.io.marker.BufferableHandle;
34-
import com.marklogic.client.io.marker.ContentHandle;
35-
import com.marklogic.client.io.marker.ContentHandleFactory;
36-
import com.marklogic.client.io.marker.CtsQueryWriteHandle;
37-
import com.marklogic.client.io.marker.JSONReadHandle;
38-
import com.marklogic.client.io.marker.JSONWriteHandle;
39-
import com.marklogic.client.io.marker.QuadsWriteHandle;
40-
import com.marklogic.client.io.marker.StructureReadHandle;
41-
import com.marklogic.client.io.marker.StructureWriteHandle;
42-
import com.marklogic.client.io.marker.TextReadHandle;
43-
import com.marklogic.client.io.marker.TextWriteHandle;
44-
import com.marklogic.client.io.marker.TriplesReadHandle;
45-
import com.marklogic.client.io.marker.TriplesWriteHandle;
46-
import com.marklogic.client.io.marker.XMLReadHandle;
47-
import com.marklogic.client.io.marker.XMLWriteHandle;
4834

4935
/**
5036
* <p>A Reader Handle represents a character content as a reader
@@ -55,7 +41,7 @@
5541
*/
5642
public class ReaderHandle
5743
extends BaseHandle<InputStream, OutputStreamSender>
58-
implements OutputStreamSender, BufferableHandle, ContentHandle<Reader>,
44+
implements OutputStreamSender, StreamingContentHandle<Reader, InputStream>,
5945
JSONReadHandle, JSONWriteHandle,
6046
TextReadHandle, TextWriteHandle,
6147
XMLReadHandle, XMLWriteHandle,
@@ -198,6 +184,28 @@ public byte[] toBuffer() {
198184
throw new MarkLogicIOException(e);
199185
}
200186
}
187+
@Override
188+
public Reader toContent(InputStream serialization) {
189+
return (serialization == null) ? null :
190+
new InputStreamReader(serialization, StandardCharsets.UTF_8);
191+
}
192+
@Override
193+
public Reader bytesToContent(byte[] buffer) {
194+
return (buffer == null || buffer.length == 0) ? null :
195+
toContent(new ByteArrayInputStream(buffer));
196+
}
197+
@Override
198+
public byte[] contentToBytes(Reader content) {
199+
if (content == null) return null;
200+
try {
201+
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
202+
Utilities.write(content, buffer);
203+
return buffer.toByteArray();
204+
} catch (IOException e) {
205+
throw new MarkLogicIOException("Could not convert Reader to byte[] array", e);
206+
}
207+
}
208+
201209
/**
202210
* Buffers the character stream and returns the buffer as a string.
203211
*/

marklogic-client-api/src/main/java/com/marklogic/client/io/SourceHandle.java

Lines changed: 25 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -31,18 +31,11 @@
3131
import javax.xml.transform.stream.StreamResult;
3232
import javax.xml.transform.stream.StreamSource;
3333

34+
import com.marklogic.client.io.marker.*;
3435
import org.slf4j.Logger;
3536
import org.slf4j.LoggerFactory;
3637

3738
import com.marklogic.client.MarkLogicIOException;
38-
import com.marklogic.client.io.marker.BufferableHandle;
39-
import com.marklogic.client.io.marker.ContentHandle;
40-
import com.marklogic.client.io.marker.ContentHandleFactory;
41-
import com.marklogic.client.io.marker.CtsQueryWriteHandle;
42-
import com.marklogic.client.io.marker.StructureReadHandle;
43-
import com.marklogic.client.io.marker.StructureWriteHandle;
44-
import com.marklogic.client.io.marker.XMLReadHandle;
45-
import com.marklogic.client.io.marker.XMLWriteHandle;
4639

4740
/**
4841
* <p>A Source Handle represents XML content as a transform source for reading
@@ -52,7 +45,7 @@
5245
*/
5346
public class SourceHandle
5447
extends BaseHandle<InputStream, OutputStreamSender>
55-
implements OutputStreamSender, BufferableHandle, ContentHandle<Source>,
48+
implements OutputStreamSender, StreamingContentHandle<Source, InputStream>,
5649
XMLReadHandle, XMLWriteHandle,
5750
StructureReadHandle, StructureWriteHandle, CtsQueryWriteHandle,
5851
Closeable
@@ -259,6 +252,29 @@ public byte[] toBuffer() {
259252
throw new MarkLogicIOException(e);
260253
}
261254
}
255+
@Override
256+
public Source toContent(InputStream serialization) {
257+
return (serialization == null) ? null :
258+
new StreamSource(new InputStreamReader(serialization, StandardCharsets.UTF_8));
259+
}
260+
@Override
261+
public Source bytesToContent(byte[] buffer) {
262+
return (buffer == null || buffer.length == 0) ? null :
263+
toContent(new ByteArrayInputStream(buffer));
264+
}
265+
@Override
266+
public byte[] contentToBytes(Source content) {
267+
if (content == null) return null;
268+
try {
269+
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
270+
makeTransformer().newTransformer().transform(content,
271+
new StreamResult(new OutputStreamWriter(buffer, StandardCharsets.UTF_8)));
272+
return buffer.toByteArray();
273+
} catch (TransformerException e) {
274+
throw new MarkLogicIOException("Could not convert Source to byte[] array", e);
275+
}
276+
}
277+
262278
/**
263279
* Buffers the transform source and returns the buffer as a string.
264280
*/

marklogic-client-api/src/main/java/com/marklogic/client/io/XMLEventReaderHandle.java

Lines changed: 41 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@
2121
import java.io.IOException;
2222
import java.io.InputStream;
2323
import java.io.OutputStream;
24-
import java.io.UnsupportedEncodingException;
2524
import java.nio.charset.StandardCharsets;
2625

2726
import javax.xml.stream.FactoryConfigurationError;
@@ -32,19 +31,12 @@
3231
import javax.xml.stream.XMLResolver;
3332
import javax.xml.stream.XMLStreamException;
3433

34+
import com.marklogic.client.io.marker.*;
3535
import org.slf4j.Logger;
3636
import org.slf4j.LoggerFactory;
3737

3838
import com.marklogic.client.MarkLogicIOException;
3939
import com.marklogic.client.MarkLogicInternalException;
40-
import com.marklogic.client.io.marker.BufferableHandle;
41-
import com.marklogic.client.io.marker.ContentHandle;
42-
import com.marklogic.client.io.marker.ContentHandleFactory;
43-
import com.marklogic.client.io.marker.CtsQueryWriteHandle;
44-
import com.marklogic.client.io.marker.StructureReadHandle;
45-
import com.marklogic.client.io.marker.StructureWriteHandle;
46-
import com.marklogic.client.io.marker.XMLReadHandle;
47-
import com.marklogic.client.io.marker.XMLWriteHandle;
4840

4941
/**
5042
* <p>An XML Event Reader Handle represents XML content as an XML event reader
@@ -55,7 +47,7 @@
5547
*/
5648
public class XMLEventReaderHandle
5749
extends BaseHandle<InputStream, OutputStreamSender>
58-
implements OutputStreamSender, BufferableHandle, ContentHandle<XMLEventReader>,
50+
implements OutputStreamSender, StreamingContentHandle<XMLEventReader, InputStream>,
5951
XMLReadHandle, XMLWriteHandle,
6052
StructureReadHandle, StructureWriteHandle, CtsQueryWriteHandle,
6153
Closeable
@@ -214,6 +206,39 @@ public byte[] toBuffer() {
214206
throw new MarkLogicIOException(e);
215207
}
216208
}
209+
@Override
210+
public XMLEventReader toContent(InputStream serialization) {
211+
if (serialization == null) return null;
212+
try {
213+
XMLInputFactory factory = getFactory();
214+
if (factory == null) {
215+
throw new MarkLogicInternalException("Failed to make StAX input factory");
216+
}
217+
218+
if (resolver != null)
219+
factory.setXMLResolver(resolver);
220+
221+
return factory.createXMLEventReader(serialization, "UTF-8");
222+
} catch (XMLStreamException e) {
223+
logger.error("Failed to parse StAX events from input stream",e);
224+
throw new MarkLogicInternalException(e);
225+
} catch (FactoryConfigurationError e) {
226+
logger.error("Failed to parse StAX events from input stream",e);
227+
throw new MarkLogicInternalException(e);
228+
}
229+
}
230+
@Override
231+
public XMLEventReader bytesToContent(byte[] buffer) {
232+
return (buffer == null || buffer.length == 0) ? null :
233+
toContent(new ByteArrayInputStream(buffer));
234+
}
235+
@Override
236+
public byte[] contentToBytes(XMLEventReader content) {
237+
if (content == null) return null;
238+
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
239+
write(content, buffer);
240+
return buffer.toByteArray();
241+
}
217242
/**
218243
* Buffers the StAX event source and returns the buffer
219244
* as an XML string.
@@ -275,26 +300,10 @@ protected void receiveContent(InputStream content) {
275300
}
276301

277302
this.underlyingStream = content;
278-
try {
279-
if (logger.isInfoEnabled())
280-
logger.info("Parsing StAX events from input stream");
281-
282-
XMLInputFactory factory = getFactory();
283-
if (factory == null) {
284-
throw new MarkLogicInternalException("Failed to make StAX input factory");
285-
}
286303

287-
if (resolver != null)
288-
factory.setXMLResolver(resolver);
289-
290-
this.content = factory.createXMLEventReader(content, "UTF-8");
291-
} catch (XMLStreamException e) {
292-
logger.error("Failed to parse StAX events from input stream",e);
293-
throw new MarkLogicInternalException(e);
294-
} catch (FactoryConfigurationError e) {
295-
logger.error("Failed to parse StAX events from input stream",e);
296-
throw new MarkLogicInternalException(e);
297-
}
304+
if (logger.isInfoEnabled())
305+
logger.info("Parsing StAX events from input stream");
306+
this.content = toContent(content);
298307
}
299308
@Override
300309
protected OutputStreamSender sendContent() {
@@ -306,6 +315,9 @@ protected OutputStreamSender sendContent() {
306315
}
307316
@Override
308317
public void write(OutputStream out) throws IOException {
318+
write(this.content, out);
319+
}
320+
private void write(XMLEventReader content, OutputStream out) {
309321
try {
310322
XMLOutputFactory factory = XMLOutputFactory.newFactory();
311323
XMLEventWriter writer = factory.createXMLEventWriter(out, "UTF-8");

0 commit comments

Comments
 (0)