Hi,

I am interested to know if there is an idiomatic way to avoid or recover
from crashes in the following use case.

The program opens an OpenOffice writer document with a custom XInputStream
defined below.
It changes some user fields and bookmarks contents and save the document as
pdf.

For saving it uses the XStorable.storeUrl method and a custom XOutputStream,
also defined below.

When doing the stress test below, it always crashes after having looped
around 8500 times with the exception:
com.sun.star.lang.IllegalArgumentException: URL seems to be an unsupported
one

I have put a comment on the code above the line where the program itself
crashes.

The OpenOffice instance is still up and running though.

1- Is there something wrong in the code that causes the crash? Maybe some
wrong parameter?
Something else that needs to be closed or disposed?

2- If not is there a proper way to recover from the crash and retry the
operation?
What are usually the recoverable exceptions and which cleanup should be
done? Maybe we need to reload / refresh / recreate some object for a safe
recovery?

Any idea?

PS.: I find the "URL seems to be an unsupported one" message quite puzzling
since the URL that is used is always "private:stream".
So why do this URL become unsupported after it has been used for about 8500
times?



// MAIN Java code
final XComponentContext context = Bootstrap
        .createInitialComponentContext(null);

final XUnoUrlResolver resolver = UnoUrlResolver.create(context);

final String unoUrl =
"uno:socket,host=localhost,port=8100;urp;StarOffice.ServiceManager";

final Object initialObject = resolver.resolve(unoUrl);

final XMultiComponentFactory factory = (XMultiComponentFactory) UnoRuntime
        .queryInterface(XMultiComponentFactory.class, initialObject);

final XPropertySet props = (XPropertySet) UnoRuntime.queryInterface(
        XPropertySet.class, factory);

final Object defaultContext = props.getPropertyValue("DefaultContext");

final XComponentContext componentContent = (XComponentContext) UnoRuntime
        .queryInterface(XComponentContext.class, defaultContext);

final Object frameDesktop = factory.createInstanceWithContext(
        "com.sun.star.frame.Desktop", componentContent);

final XDesktop desktop = (XDesktop) UnoRuntime.queryInterface(
        XDesktop.class, frameDesktop);

final XComponentLoader loader = (XComponentLoader) UnoRuntime
        .queryInterface(XComponentLoader.class, desktop);

for (int i = 0; i < 20000; i++) {
    final OfficeInputStream officeInputStream = new OfficeInputStream(
            new FileInputStream("some-path.odt"));
    final PropertyValue[] propsVals = new PropertyValue[2];
    propsVals[0] = new PropertyValue();
    propsVals[0].Name = "InputStream";
    propsVals[0].Value = officeInputStream;
    propsVals[1] = new PropertyValue();
    propsVals[1].Name = "Hidden";
    propsVals[1].Value = Boolean.TRUE;
    // IT CRASHES WHEN EXECUTING THE LINE BELOW
    final XComponent doc = loader.loadComponentFromURL(
            "private:stream", "doc", 0, propsVals);
    officeInputStream.closeInput();

    // DO SOME STUFF WITH DOC :
    // change content of user fields and bookmarks, refresh
    // and save as pdf
    // ...
    doc.dispose();
}



// THE OFFICEINPUTSTREAM CLASS
final class OfficeInputStream extends ByteArrayInputStream implements
        XSeekable, XInputStream {

    OfficeInputStream(final byte[] buf) {
        super(buf);
    }

    OfficeInputStream(final InputStream input) throws java.io.IOException {
        this(IOUtils.toByteArray(input));
    }

    public int readBytes(final byte[][] buffer, final 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) {
                    final 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 (final java.io.IOException e) {
            throw new IOException(e.getMessage(), this);
        }
    }

    public int readSomeBytes(final byte[][] buffer, final int bufferSize)
            throws NotConnectedException, BufferSizeExceededException,
            IOException {
        return readBytes(buffer, bufferSize);
    }

    public void skipBytes(final int skipLength) throws
NotConnectedException,
            BufferSizeExceededException, IOException {
        skip(skipLength);
    }

    public void closeInput() throws NotConnectedException,
            com.sun.star.io.IOException {
        try {
            close();
        } catch (final java.io.IOException e) {
            throw new IOException(e.getMessage(), this);
        }
    }

    public long getLength() throws IOException {
        return count;
    }

    public long getPosition() throws IOException {
        return pos;
    }

    public void seek(final long position) throws IllegalArgumentException,
            IOException {
        pos = (int) position;
    }
}


// THE OFFICEOUTPUTSTREAM CLASS
final class OfficeOutputStream extends ByteArrayOutputStream implements
        XOutputStream {

    private static final int BUFFER_SIZE = 32768;

    OfficeOutputStream() {
        super(BUFFER_SIZE);
    }

    public void writeBytes(final byte[] values) throws
NotConnectedException,
            BufferSizeExceededException, IOException {
        try {
            this.write(values);
        } catch (final java.io.IOException e) {
            throw new IOException(e.getMessage());
        }
    }

    public void closeOutput() throws NotConnectedException,
            BufferSizeExceededException, com.sun.star.io.IOException {
        try {
            super.flush();
            super.close();
        } catch (final java.io.IOException e) {
            throw new IOException(e.getMessage());
        }
    }

    @Override
    public void flush() {
        try {
            super.flush();
        } catch (final java.io.IOException e) {
        }
    }
}

Reply via email to