/* * Copyright (c) 2019 MarkLogic Corporation */ package com.marklogic.xcc.examples; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.PipedInputStream; import java.io.PipedOutputStream; import com.marklogic.xcc.Content; import com.marklogic.xcc.ContentCreateOptions; import com.marklogic.xcc.ContentFactory; /** *

* This is a specialized implementation of the {@link Content} interface which allows you to write * your content to an {@link OutputStream}. *

*

* Click here for the source code for this * class *

*

* This class creates a piped pair of streams. The source ({@link InputStream}) is passed to the * standard factory method * {@link ContentFactory#newUnBufferedContent(String, java.io.InputStream, com.marklogic.xcc.ContentCreateOptions)} * . The sink ({@link OutputStream}) can be retrieved with the {@link #getOutputStream()} method. *

*

* NOTE: You must write to the {@link OutputStream} in a different thread than the * one in which you invoke {@link com.marklogic.xcc.Session#insertContent} or your program may * deadlock. The {@link OutputStreamInserter} class shows an example of how to use this class. *

* * @see OutputStreamInserter */ public class OutputStreamContent implements Content { private final OutputStream sink; private final InputStream source; private final Content content; /** * Construct an instance with the usual URI and options parameters, the actual content will be * read from the other end of the pipe provided by {@link #getOutputStream()}. * * @param uri * The URI by which the content (document) will be known in the contentbase. * @param options * An instance of {@link ContentCreateOptions}. * @throws IOException * If there is a problem creating the pipe (unlikely). */ public OutputStreamContent(String uri, ContentCreateOptions options) throws IOException { PipedOutputStream sink = new PipedOutputStream(); this.sink = sink; this.source = new PipedInputStream(sink); this.content = ContentFactory.newUnBufferedContent(uri, source, options); } // ----------------------------------------------------------- // Implementation class-specific methods /** * Return the end of the pipe to which you will write your content (the sink). * * @return An instance of {@link OutputStream}. Be sure to close this object when you've written * all the data. */ public OutputStream getOutputStream() { return sink; } // ----------------------------------------------------------- // Content interface delegation public String getUri() { return content.getUri(); } /** * Passes the read end (source) of the pipe to the content insertion framework. * * @return An instance of {@link InputStream}. * @throws IOException * Will never happen in this implementation. */ public InputStream openDataStream() throws IOException { return source; } public ContentCreateOptions getCreateOptions() { return content.getCreateOptions(); } /** * The answer is "no". * * @return Always returns false, this implementation is non-rewindable. */ public boolean isRewindable() { return false; } /** * This streaming-only implementation is not rewindable. * * @throws IOException * Will always be thrown if called. */ public void rewind() throws IOException { throw new IOException("Rewind is not supported"); } /** * Unknown size. * * @return Always returns -1 to indicate that the size is unknown. */ public long size() { return -1; } public void close() { content.close(); } }