OpenOffice.org offers the possibility to load and store files using streams. For using this, all you need are two classes implementing XInputStream and XOutputStream. Additionally it seems to be important, that the class that implements XInputStream also implements XSeekable.
I've developed this example on Windows XP using OOo 2.3.1, NetBeans IDE 6.0 and Java 1.6_04.
Code:
Select all
package ooo.streams;
import java.io.ByteArrayInputStream;
import com.sun.star.io.BufferSizeExceededException;
import com.sun.star.io.NotConnectedException;
import com.sun.star.io.XInputStream;
import com.sun.star.io.XSeekable;
* <a href="http://www.oooforum.org/forum/viewtopic.phtml?t=13205">OOInputStream from the thread <b>OOo-Java: Using XInputStream...</b></a>
public class OOoInputStream extends ByteArrayInputStream implements XInputStream, XSeekable {
public OOoInputStream(byte[] buf) {
super(buf);
// Implement XInputStream
public int readBytes(byte[][] buffer, int bufferSize) throws NotConnectedException, BufferSizeExceededException, com.sun.star.io.IOException {
int numberOfReadBytes;
try {
byte[] bytes = new byte[bufferSize];
numberOfReadBytes = super.read(bytes);
if(numberOfReadBytes > 0) {
if(numberOfReadBytes < bufferSize) {
byte[] smallerBuffer = new byte[numberOfReadBytes];
System.arraycopy(bytes, 0, smallerBuffer, 0, numberOfReadBytes);
bytes = smallerBuffer;
else {
bytes = new byte[0];
numberOfReadBytes = 0;
buffer[0]=bytes;
return numberOfReadBytes;
catch (java.io.IOException e) {
throw new com.sun.star.io.IOException(e.getMessage(),this);
public int readSomeBytes(byte[][] buffer, int bufferSize) throws NotConnectedException, BufferSizeExceededException, com.sun.star.io.IOException {
return readBytes(buffer, bufferSize);
public void skipBytes(int skipLength) throws NotConnectedException, BufferSizeExceededException, com.sun.star.io.IOException {
skip(skipLength);
public void closeInput() throws NotConnectedException, com.sun.star.io.IOException {
try {
close();
catch (java.io.IOException e) {
throw new com.sun.star.io.IOException(e.getMessage(), this);
// Implement XSeekable
public long getLength() throws com.sun.star.io.IOException {
return count;
public long getPosition() throws com.sun.star.io.IOException {
return pos;
public void seek(long position) throws IllegalArgumentException, com.sun.star.io.IOException {
pos = (int) position;
The second class implements XOutputStream:Code: Select all
package ooo.streams;
import java.io.ByteArrayOutputStream;
import com.sun.star.io.BufferSizeExceededException;
import com.sun.star.io.NotConnectedException;
import com.sun.star.io.XOutputStream;
* <a href="http://www.oooforum.org/forum/viewtopic.phtml?t=13205">OOInputStream from the thread <b>OOo-Java: Using XInputStream...</b></a>
public class OOoOutputStream extends ByteArrayOutputStream implements XOutputStream {
public OOoOutputStream() {
super(32768);
// Implement XOutputStream
public void writeBytes(byte[] values) throws NotConnectedException, BufferSizeExceededException, com.sun.star.io.IOException {
try {
this.write(values);
catch (java.io.IOException e) {
throw(new com.sun.star.io.IOException(e.getMessage()));
public void closeOutput() throws NotConnectedException, BufferSizeExceededException, com.sun.star.io.IOException {
try {
super.flush();
super.close();
catch (java.io.IOException e) {
throw(new com.sun.star.io.IOException(e.getMessage()));
@Override
public void flush() {
try {
super.flush();
catch (java.io.IOException e) {
The last class is a little example that uses OOoInputStream and OOoOutputStream to convert an OOo Writer document to PDF:Code: Select all
package ooo.streams;
import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import com.sun.star.beans.PropertyValue;
import com.sun.star.comp.helper.BootstrapException;
import com.sun.star.frame.XComponentLoader;
import com.sun.star.frame.XStorable;
import com.sun.star.lang.XComponent;
import com.sun.star.lang.XMultiComponentFactory;
import com.sun.star.uno.Exception;
import com.sun.star.uno.UnoRuntime;
import com.sun.star.uno.XComponentContext;
import com.sun.star.util.XCloseable;
import ooo.connector.BootstrapSocketConnector;
public class OOoStreamConverter {
private XComponentContext xComponentContext;
public OOoStreamConverter(XComponentContext xComponentContext) {
this.xComponentContext = xComponentContext;
public void convert(OOoInputStream input, OOoOutputStream output, String filterName) throws Exception {
XMultiComponentFactory xMultiComponentFactory = xComponentContext.getServiceManager();
Object desktopService = xMultiComponentFactory.createInstanceWithContext("com.sun.star.frame.Desktop", xComponentContext);
XComponentLoader xComponentLoader = (XComponentLoader) UnoRuntime.queryInterface(XComponentLoader.class, desktopService);
PropertyValue[] conversionProperties = new PropertyValue[2];
conversionProperties[0] = new PropertyValue();
conversionProperties[1] = new PropertyValue();
conversionProperties[0].Name = "InputStream";
conversionProperties[0].Value = input;
conversionProperties[1].Name = "Hidden";
conversionProperties[1].Value = new Boolean(true);
XComponent document = xComponentLoader.loadComponentFromURL("private:stream", "_blank", 0, conversionProperties);
conversionProperties[0].Name = "OutputStream";
conversionProperties[0].Value = output;
conversionProperties[1].Name = "FilterName";
conversionProperties[1].Value = filterName;
XStorable xstorable = (XStorable) UnoRuntime.queryInterface(XStorable.class,document);
xstorable.storeToURL("private:stream", conversionProperties);
XCloseable xclosable = (XCloseable) UnoRuntime.queryInterface(XCloseable.class,document);
xclosable.close(true);
public static void main(String[] args) {
String oooExecutableFolder = "c:/program files/openoffice.org 2.3/program/";
String inputFilename = "c:/temp/text.odt";
String outputFilename = "c:/temp/text.pdf";
try {
// Connect to OOo server
XComponentContext xComponentContext = BootstrapSocketConnector.bootstrap(oooExecutableFolder);
OOoStreamConverter converter = new OOoStreamConverter(xComponentContext);
// Create OOoInputStream
InputStream inputFile = new BufferedInputStream(new FileInputStream(inputFilename));
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
byte[] byteBuffer = new byte[4096];
int byteBufferLength = 0;
while ((byteBufferLength = inputFile.read(byteBuffer)) > 0) {
bytes.write(byteBuffer,0,byteBufferLength);
inputFile.close();
OOoInputStream inputStream = new OOoInputStream(bytes.toByteArray());
// Create OOoOutputStream
OOoOutputStream outputStream = new OOoOutputStream();
// Convert document to PDF
converter.convert(inputStream, outputStream, "writer_pdf_Export");
// Save OOoOutputStream
FileOutputStream outputFile = new FileOutputStream(outputFilename);
outputFile.write(outputStream.toByteArray());
outputFile.close();
} catch (BootstrapException e) {
System.err.println("Connection not available");
e.printStackTrace();
} catch (IOException e) {
System.err.println("File error");
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
System.exit(0);
The method OOoStreamConverter.convert() contains the crucial part of this example. It shows how to tell OOo to use an InputStream for loading (conversionProperties[0].Name = "InputStream"; conversionProperties[0].Value = input; and loadComponentFromURL("private:stream", ...)) and an OutputStream for storing (conversionProperties[0].Name = "OutputStream"; conversionProperties[0].Value = output; and storeToURL("private:stream", ...).
Credits
The idea to develop this little how-to comes from the thread OOo-Java: Using XInputStream... and from various posts in the (Unofficial) OpenOffice.org Forum asking how to handle XInputStream and XOutputStream.
I am a new convert to the OO side of things, and have been tasked with writing a .NET (C#) module that does this same thing. Has anyone done this? Can you give me a link/somewhere to look to get me started?
I have the code using the OO API, and I seem to get the document loaded, but when I do the save I get a blank document.
Suggestions? Somewhere to look?
THANKS!
(aka Gandalf the White)
loadComponentFromURL("private:stream") opens Writer because it's default component.
How can i put the stream into component loading Spreadsheet (ods) ?
private:factory/scalc - loading empty component
private:stream/scalc - didn't work
gato wrote:loadComponentFromURL("private:stream") opens Writer because it's default component.
This is not correct!
loadComponentFromURL("private:stream") loads a stream. OOo decides from the stream content, which OOo application should be opened. In the example above it opens OOo Writer, because the stream is filled from
inputFilename = "c:/temp/text.odt";.
gato wrote:How can i put the stream into component loading Spreadsheet (ods) ?
Fill the stream from an ods document. That's all!
Yes, you right. The problem that FODS (flat ods) do not works correctly with stream.Why is it?
Success example:
loadComponentFromURL("c:/test.fods", "_blank", 0, propertyValues);
propertyValues[1].Name = "FilterName";
propertyValues[1].Value = "calc8";
xstorable.storeToURL("c:/test.ods", propertyValues);
Error:
InputStream inputFile = new BufferedInputStream(new FileInputStream("c:/test.fods"));
OOoInputStream inputStream = new OOoInputStream(bytes.toByteArray());
loadComponentFromURL("private:stream", "_blank", 0, propertyValues);
propertyValues[1].Name = "FilterName";
propertyValues[1].Value = "calc8";
xstorable.storeToURL("private:stream", propertyValues);
FileOutputStream outputFile = new FileOutputStream(outputFilename);
outputFile.write(outputStream.toByteArray());
outputFile.close();
gato wrote:The problem that FODS (flat ods) do not works correctly with stream.Why is it?
What is a flat ods? I've never worked with a flat ods, whatever that might be.
gato wrote:Error:
Code: Select all
InputStream inputFile = new BufferedInputStream(new FileInputStream("c:/test.fods"));
OOoInputStream inputStream = new OOoInputStream(bytes.toByteArray());
loadComponentFromURL("private:stream", "_blank", 0, propertyValues);
It's hard to guess what went wrong, because you omitted in your code example the setting of
propertyValues.
I used the same code to do a server client conversion.
However, when I convert the odt document into html document, the images in the odt document is not extracted.
Any idea what is wrong?
private static XComponentContext componentContext = null;
private XComponentLoader componentLoader = null;
private XComponent component = null;
private String connectionString = "uno:socket,host=192.168.0.10,port=8100;urp;StarOffice.ServiceManager";
//Method to convert OpenOffice document to html and vice versa
public boolean convert(OOInputStream inputStream, OOOutputStream outputStream, String conversionType) {
boolean converted = false;
setNeccessaryComponents(inputStream, outputStream);
if(componentContext != null && componentLoader != null && component != null) {
storeConvertedDocToPath(conversionType, outputStream);
converted = true;
System.out.println("Converted");
return converted;
//Set the ComponentContext, ComponentLoader and Component
public void setNeccessaryComponents(OOInputStream inputFile, OOOutputStream output) {
XComponentContext cc = getComponentContext();
if(cc != null)
componentContext = cc;
XComponentLoader cl = getComponentLoader();
if(cl != null)
componentLoader = cl;
XComponent c = getXComponent(inputFile, output);
if(c != null)
component = c;
//Retrieve the xComponentContext object
public XComponentContext getComponentContext() {
XComponentContext cc = null;
try {
cc = Bootstrap.createInitialComponentContext(null);
catch(Exception e) {}
return cc;
//Retrieve the xComponentLoader object
public XComponentLoader getComponentLoader() {
XComponentLoader cl = null;
try {
XMultiComponentFactory multiComponentFactory = getXMulitComponentFactory();
if(multiComponentFactory != null) {
XPropertySet propertySet = (XPropertySet) UnoRuntime.queryInterface(XPropertySet.class, multiComponentFactory);
Object defaultContext = propertySet.getPropertyValue("DefaultContext");
componentContext = (XComponentContext) UnoRuntime.queryInterface(XComponentContext.class, defaultContext);
cl = (XComponentLoader) UnoRuntime.queryInterface(XComponentLoader.class,
multiComponentFactory.createInstanceWithContext("com.sun.star.frame.Desktop", componentContext));
catch(Exception e) {}
return cl;
public XMultiComponentFactory getXMulitComponentFactory() {
XMultiComponentFactory multiComponentFactory = null;
try {
multiComponentFactory = componentContext.getServiceManager();
Object objectUrlResolver = multiComponentFactory.createInstanceWithContext("com.sun.star.bridge.UnoUrlResolver", componentContext);
XUnoUrlResolver xurlresolver = (XUnoUrlResolver) UnoRuntime.queryInterface(XUnoUrlResolver.class, objectUrlResolver);
Object objectInitial = xurlresolver.resolve(connectionString);
multiComponentFactory = (XMultiComponentFactory) UnoRuntime.queryInterface(XMultiComponentFactory.class, objectInitial);
catch(Exception e) {}
return multiComponentFactory;
//Retrieve the xComponent object
public XComponent getXComponent(OOInputStream inputStream, OOOutputStream outputStream) {
XComponent component = null;
try {
PropertyValue[] conversionProperties = new PropertyValue[2];
conversionProperties[0] = new PropertyValue();
conversionProperties[1] = new PropertyValue();
conversionProperties[0].Name = "InputStream";
conversionProperties[0].Value = inputStream;
conversionProperties[1].Name = "Hidden";
conversionProperties[1].Value = new Boolean(true);
component = componentLoader.loadComponentFromURL("private:stream", "_blank", 0, conversionProperties);
catch(Exception e) {}
return component;
//Store the converted doc using XStorable object
public void storeConvertedDocToPath(String conversionType, OOOutputStream output) {
try {
XStorable storable = (XStorable) UnoRuntime.queryInterface(XStorable.class, component);
PropertyValue[] outputProperties = getOutputProperties(output, conversionType);
storable.storeToURL("private:stream", outputProperties);
XCloseable xclosable = (XCloseable) UnoRuntime.queryInterface(XCloseable.class, component);
xclosable.close(true);
catch(Exception e){}
//Get conversion properties
public PropertyValue[] getOutputProperties(OOOutputStream output, String conversionType)
PropertyValue[] outputProperties = new PropertyValue[2];
outputProperties[0] = new PropertyValue();
outputProperties[0].Name = "OutputStream";
outputProperties[0].Value = output;
outputProperties[1] = new PropertyValue();
outputProperties[1].Name = "FilterName";
outputProperties[1].Value = conversionType;
return outputProperties;
//Get Array output stream for openoffice
public ByteArrayOutputStream getByteArrayOutputStream(String docPath) {
ByteArrayOutputStream bytes = null;
try {
InputStream inputFile = new BufferedInputStream(new FileInputStream(docPath));
bytes = new ByteArrayOutputStream();
byte[] byteBuffer = new byte[4096];
int byteBufferLength = 0;
while ((byteBufferLength = inputFile.read(byteBuffer)) > 0) {
bytes.write(byteBuffer,0,byteBufferLength);
inputFile.close();
catch(Exception e) {}
return bytes;
//Write out the converted document
public void writeOut(String filePath, OOOutputStream outputStream) {
try {
FileOutputStream outputFile = new FileOutputStream(filePath);
outputFile.write(outputStream.toByteArray());
outputFile.close();
catch(IOException ioe) {}
Main class to test the abv codes
OpenOffice oo = new OpenOffice();
ByteArrayOutputStream baos = oo.getByteArrayOutputStream("/tmp/test.odt");
OOInputStream inputStream = new OOInputStream(baos.toByteArray());
OOOutputStream outputStream = new OOOutputStream();
String conversionType = "HTML";
boolean converted = oo.convert(inputStream, outputStream, conversionType);
String outputPath = "/tmp/test.html";
if(converted == true)
oo.writeOut(outputPath, outputStream);
The html file is generated however the images inside the odt file is not generated. Thanks for the help