OpenOffice.org Forum at OOoForum.orgThe OpenOffice.org Forum
 
 [Home]   [FAQ]   [Search]   [Memberlist]   [Usergroups]   [Register
 [Profile]   [Log in to check your private messages]   [Log in

Correct FilterName to open RTF from bytestream?
Goto page 1, 2  Next
 
Post new topic   Reply to topic    OOoForum.org Forum Index -> OpenOffice.org Macros and API
View previous topic :: View next topic  
Author Message
bdirkson
General User
General User


Joined: 26 Jul 2006
Posts: 5
Location: Netherlands

PostPosted: Thu Jul 27, 2006 7:53 am    Post subject: Correct FilterName to open RTF from bytestream? Reply with quote

Hello,

I am currently using OO.o as a conversion service to convert RTF files to PDF. The RTF's are created as templates with MS Word 2003, then uploaded in our application.
This is a J2EE application, where at a certain point a template is merged with data. After that the file is stored as a byte[] in a BLOB field in the database.
When someone wants to see the document, it is retrieved from the database and served.
The RTF contains some formatting specific to Word, so opening in WordPad results in a document with a far different layout.
Now we need to convert to PDF, because the end-user probably does not have MS Word at his/her disposal.

What I thought up was to use OpenOffice.org. There are very few tools that can do the RTF to PDF conversion and can be called from Java.
Now, I have incorporated the libs from the SDK in our appl. I have made an OOInputStream and OOOutputStream class similarly as found in several topics in this fine forum.

The problem I run into: I cannot get the loadComponentFromURL method to work with my RTF stream.
When I write the byte[] to file and use this method with "file:///d:/temp/test.rtf" it works. And the output PDF is sent back to my application as a byte[]. Works very fine.
(Even calling a remote OO.o which has access to a share where I write my temporary file works OK.)

But of course I don't want to write files on my filesystem. I want to send a byte[].

The problem seems to be in the FilterName I use. I have used DannyB's 'FilterNamesListing-2003-11-22-05.sxd' (found also here) to generate all FilterNames.
"Rich Text Format" does seem the most logical one. But when I use this, loadComponentFromURL returns null, resulting in a nullpointerexception further on.
When I use "MS Word 97" or even "MS Word 2003 XML" as FilterName my XComponent is not null, but the end result is a PDF of one empty page.

So, can someone point me to the correct filter to use for importing RTF?
Apparently OO.o itself knows what to do with it when I let it open the file from the filesystem. The same way when I open it through the OO.o GUI.
It's driving me nuts. It's the very last piece I need
Till I have a solution we try to get the filebased workaround working in our production environment, but I think it's a dirty way.

Below a code snippet to illustrate how I have it working so far. Three different FilterNames are for testing purposes of course.

Thanks in advance!!

Bart

Code:
    public byte[] getByteStreamFromStream(byte[] doc) {
        try {

            if (xComponentLoader == null){
                connect();
            }

            OOInputStream oois = new OOInputStream(doc);

            PropertyValue[] loadProps = new PropertyValue[3];
            loadProps[0] = new PropertyValue();
            loadProps[0].Name = "Hidden";
            loadProps[0].Value = new Boolean(true);
           
            loadProps[1] = new PropertyValue();
            loadProps[1].Name = "FilterName";
            loadProps[1].Value = "Rich Text Format";
                                 
            loadProps[2] = new PropertyValue();
            loadProps[2].Name = "InputStream";
            loadProps[2].Value = oois;

            xComp = xComponentLoader.loadComponentFromURL("private:stream", "_blank", 0, loadProps);
            byte[] result = null;
            if (xComp != null ) {
                result = convertDoc();
            }

            loadProps[1].Value = "MS Word 97";
            xComp = xComponentLoader.loadComponentFromURL("private:stream", "_blank", 0, loadProps);
            if (xComp != null ) {
                result = convertDoc();
            }

            loadProps[1].Value = "MS Word 2003 XML";
            xComp = xComponentLoader.loadComponentFromURL("private:stream", "_blank", 0, loadProps);
            if (xComp != null ) {
                result = convertDoc();
            }

            return result;
        } catch (java.lang.Exception e) {
            e.printStackTrace();
        }

        return null;
    }

    private byte[] convertDoc() throws Exception {
       
        // Get the textdocument
        XTextDocument aTextDocument = (XTextDocument) UnoRuntime.queryInterface(com.sun.star.text.XTextDocument.class, xComp);

        XStorable xStorable = (XStorable) UnoRuntime.queryInterface(XStorable.class, aTextDocument);
        OOOutputStream ooos = new OOOutputStream();
        PropertyValue[] storeProps = new PropertyValue[4];

        storeProps[0] = new PropertyValue();
        storeProps[0].Name = "FilterName";
        storeProps[0].Value = "writer_pdf_Export";

        storeProps[1] = new PropertyValue();
        storeProps[1].Name = "CompressMode";
        storeProps[1].Value = "0";

        storeProps[2] = new PropertyValue();
        storeProps[2].Name = "Overwrite";
        storeProps[2].Value = Boolean.TRUE;

        storeProps[3] = new PropertyValue();
        storeProps[3].Name = "OutputStream";
        storeProps[3].Value = ooos;

        xStorable.storeToURL("private:stream", storeProps);

        XModel xModel = (XModel) UnoRuntime.queryInterface(XModel.class, xComp);
        XCloseable xCloseable = (XCloseable) UnoRuntime.queryInterface(XCloseable.class, xModel);
        xCloseable.close(false);

        byte[] result = ooos.toByteArray();
        return result;
       
    }
Back to top
View user's profile Send private message
mnasato
Power User
Power User


Joined: 26 Apr 2005
Posts: 54
Location: London, U.K.

PostPosted: Thu Jul 27, 2006 8:18 am    Post subject: Re: Correct FilterName to open RTF from bytestream? Reply with quote

What happens if you simply don't specify an import filter?

I'm working on the upcoming release of JOOConverter that will use streams instead of files and it seems to work fine without specifying any import filter, including RTF to PDF.

See the loadAndExport() method in this class http://joott.cvs.sourceforge.net/joott/jooconverter2/src/net/sf/jooreports/openoffice/converter/OpenOfficeDocumentConverter.java?view=markup if it can help.

Cheers

Mirko
Back to top
View user's profile Send private message
bdirkson
General User
General User


Joined: 26 Jul 2006
Posts: 5
Location: Netherlands

PostPosted: Fri Jul 28, 2006 4:47 am    Post subject: Reply with quote

Hi Mirko,
thank you for your answer.
I tried not specifying a FilterName (why didn't I come up with that myself?), and got no nulls but instead a blank PDF.

In your code I saw you used ByteArrayToXInputStreamAdapter to convert byte[] to XInputStream. And your comment about XSeekable.

So, I tried first ByteArrayToXInputStreamAdapter, and later my OOInputStream that I modified to also implement XSeekable. (found here)

Both result in a nice PDF!!
Downside is both approaches are slow as thick mud running up a hill. Sad It takes approx. 4-5 minutes before I get the result. Crying or Very sad

Do you have any performance issues?
When opened from file, the conversion does not take too long.
Back to top
View user's profile Send private message
mnasato
Power User
Power User


Joined: 26 Apr 2005
Posts: 54
Location: London, U.K.

PostPosted: Sat Jul 29, 2006 6:48 am    Post subject: Reply with quote

bdirkson wrote:
So, I tried first ByteArrayToXInputStreamAdapter, and later my OOInputStream that I modified to also implement XSeekable. (found here)

Both result in a nice PDF!!

Good!

bdirkson wrote:

Downside is both approaches are slow as thick mud running up a hill. Sad It takes approx. 4-5 minutes before I get the result. Crying or Very sad

Do you have any performance issues?
When opened from file, the conversion does not take too long.


I did some benchmarks before releasing the new stream-based code and while it was slightly slower than using files it wasn't that bad (an average of 100ms instead of 70ms). See results on the tracker issue.

Also my tests show that using a named pipe instead of a tcp socket connection gives better performance.

What you say is quite worrying. How big is the file your converting? Maybe performance with streams is much worse for big files?

Cheers

Mirko
Back to top
View user's profile Send private message
hol.sten
Super User
Super User


Joined: 14 Nov 2004
Posts: 3533
Location: Hamburg, Germany

PostPosted: Sun Jul 30, 2006 1:39 am    Post subject: Reply with quote

mnasato wrote:
Also my tests show that using a named pipe instead of a tcp socket connection gives better performance.

I never used a named pipe to connect from my Java application to OOo. What have I to do to change from a tcp socket connection to a named pipe connection? Am I right in guessing that named pipes only work on *nix systems and not with a Windows (XP) system?

With kind regards
hol.sten
Back to top
View user's profile Send private message
mnasato
Power User
Power User


Joined: 26 Apr 2005
Posts: 54
Location: London, U.K.

PostPosted: Sun Jul 30, 2006 5:24 am    Post subject: Reply with quote

hol.sten wrote:
What have I to do to change from a tcp socket connection to a named pipe connection?

You need to start OOo with
Code:
soffice -accept="pipe,name=my_app;urp;"
where name is pretty much an arbitrary string, and use the same connection parameters from your Java client app.

Caveat: this uses a native library, sal3, that you need to make available in the java.library.path when starting the Java app, e.g.
Code:
java -Djava.library.path=/opt/openoffice.org/program my.java.App


hol.sten wrote:
Am I right in guessing that named pipes only work on *nix systems and not with a Windows (XP) system?

Surprise: it actually works on Windows as well! Wink

If you're passing documents as file URLs using a pipe doesn't make any real difference over a socket (as the amount of data passed between the Java app and the OOo service is very small anyway), but with streams the difference is noticeable.

Some info about the pipe connection is contained here:
http://api.openoffice.org/docs/DevelopersGuide/OfficeBean/OfficeBean.xhtml

Cheers

Mirko
Back to top
View user's profile Send private message
hol.sten
Super User
Super User


Joined: 14 Nov 2004
Posts: 3533
Location: Hamburg, Germany

PostPosted: Sun Jul 30, 2006 6:16 am    Post subject: Reply with quote

mnasato wrote:
You need to start OOo with
Code:
soffice -accept="pipe,name=my_app;urp;"
where name is pretty much an arbitrary string, and use the same connection parameters from your Java client app.

Thanks a lot for the clarification. I'll give it a try and measure the impact on my application.

With kind regards
hol.sten
Back to top
View user's profile Send private message
bdirkson
General User
General User


Joined: 26 Jul 2006
Posts: 5
Location: Netherlands

PostPosted: Mon Jul 31, 2006 1:08 am    Post subject: Reply with quote

mnasato wrote:

Also my tests show that using a named pipe instead of a tcp socket connection gives better performance.

What you say is quite worrying. How big is the file your converting? Maybe performance with streams is much worse for big files?

My files are quite big, I guess. 500-600 kB, mostly due to an inline logo. Most letters are only 1-2 pages. (Files used to be 2,5 MB (!), mind you, until I discovered the 'Compress image' option in Word)

I'm going to test with smaller files, and try the pipes.
When I get some results I'll post it here

Thanks!
Back to top
View user's profile Send private message
bdirkson
General User
General User


Joined: 26 Jul 2006
Posts: 5
Location: Netherlands

PostPosted: Wed Aug 02, 2006 7:21 am    Post subject: Reply with quote

Update:
When using a pipe to connect, the average conversion time is about 2,5 minutes.
Quite an improvement I'd say! But still long.
With a smaller template (one where I removed the image), 22kB, the conversion takes approx. 30 secs

Disadvantage of using a pipe is the disability of a remote machine (at least on Windows).

So, we're trying to find a solution where the user can continue his work. Maybe the conversion will be done in a separate thread and user is notified when it's done.

Thanks for all the help.

@Mirko: you may want to check if a bridge exists in connect():
Code:
            bridge = bridgeFactory.getBridge(BRIDGENAME);
            if (bridge == null){
                bridge = bridgeFactory.createBridge(BRIDGENAME, "urp", connection, null);
            }


I got a BridgeExistsException when trying to connect a second time. Wink
Back to top
View user's profile Send private message
mnasato
Power User
Power User


Joined: 26 Apr 2005
Posts: 54
Location: London, U.K.

PostPosted: Wed Aug 02, 2006 9:09 am    Post subject: Reply with quote

bdirkson wrote:
@Mirko: you may want to check if a bridge exists in connect():
Code:
            bridge = bridgeFactory.getBridge(BRIDGENAME);
            if (bridge == null){
                bridge = bridgeFactory.createBridge(BRIDGENAME, "urp", connection, null);
            }


I got a BridgeExistsException when trying to connect a second time. Wink


Thanks for reporting the problem. I could not reproduce it though.

And I'm passing an empty name to createBridge(): according to the same documentation page you linked, that should create a new anonymous bridge each time.

Could you give me some more detailed instructions on how to reproduce that exception?

Thanks

Mirko
Back to top
View user's profile Send private message
bdirkson
General User
General User


Joined: 26 Jul 2006
Posts: 5
Location: Netherlands

PostPosted: Mon Aug 07, 2006 4:27 am    Post subject: Reply with quote

Hmm, indeed it shouldn't happen with an anonymous bridge.
What I did was borrowing your connection classes and connect with:
Code:
connection = new SocketOpenOfficeConnection(HOST, PORT);
xComponentLoader = connection.getDesktop();

When I tried a second conversion from my app, I got the BridgeExistsException.

Previously I used the UnoUrlResolver, but I know now that using a bridge is preferable.
Back to top
View user's profile Send private message
aloiziops
Power User
Power User


Joined: 07 Jul 2006
Posts: 52

PostPosted: Wed Aug 23, 2006 4:59 am    Post subject: Reply with quote

Hi bdirkson,

I am developed the same thing you did. Could you help me? How I can merge a lot of streams that are stored into a database as blob?

thanks
Back to top
View user's profile Send private message
pitonyak
Administrator
Administrator


Joined: 09 Mar 2004
Posts: 3655
Location: Columbus, Ohio, USA

PostPosted: Wed Aug 23, 2006 5:27 am    Post subject: Reply with quote

I demonstrate how to use a stream from an image in AndrewBase.odt. The problem, however, is that the stream that you obtain does not support the XSeekable interface. So, although you can use the stream to write the file to disk, which I demonstrate, you can not use it with loadComponenetFromURL in Basic.

I saw a solution in Java that used a helper class to wrap the binary stream. The helper class supports XSeekable so then it can be used. Not of any use from Basic, however. Crying or Very sad
_________________
--
Andrew Pitonyak
http://www.pitonyak.org/oo.php
Back to top
View user's profile Send private message Send e-mail Visit poster's website AIM Address
ms777
Super User
Super User


Joined: 07 Feb 2004
Posts: 1355

PostPosted: Thu Sep 14, 2006 1:54 pm    Post subject: Reply with quote

pitonyak wrote:
... So, although you can use the stream to write the file to disk, which I demonstrate, you can not use it with loadComponenetFromURL in Basic.

I saw a solution in Java that used a helper class to wrap the binary stream. The helper class supports XSeekable so then it can be used. Not of any use from Basic, however. Crying or Very sad


As an old Basic fan, this deficiency did not let me sleep - here is a solution/workaround to load from streams in OO Basic: http://www.oooforum.org/forum/viewtopic.phtml?t=43637
Back to top
View user's profile Send private message
hol.sten
Super User
Super User


Joined: 14 Nov 2004
Posts: 3533
Location: Hamburg, Germany

PostPosted: Mon Dec 18, 2006 12:06 pm    Post subject: Reply with quote

hol.sten wrote:
mnasato wrote:
You need to start OOo with
Code:
soffice -accept="pipe,name=my_app;urp;"
where name is pretty much an arbitrary string, and use the same connection parameters from your Java client app.

I'll give it a try and measure the impact on my application.

I gave the named pipe a try.

I changed my connection string from
Code:
uno:socket,host=localhost,port=2042;urp;StarOffice.ServiceManager

to
Code:
uno:pipe,name=localpipe;urp;StarOffice.ServiceManager


Next I changed my start command from
Code:
soffice.exe -headless -norestore -accept=socket,host=localhost,port=2042;urp

to
Code:
soffice.exe -headless -norestore -accept=pipe,name=localpipe;urp;


As mnasato suggested I added the library path directive to the call of my Java application
Code:
-Djava.library.path="c:/program/openoffice.org2.1/program"


On my Windows XP Home running my application with a pipe instead of a socket was around 1 - 2 % "faster". Not much, but more then nothing.

Regards
hol.sten
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic    OOoForum.org Forum Index -> OpenOffice.org Macros and API All times are GMT - 8 Hours
Goto page 1, 2  Next
Page 1 of 2

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group