Generating PDF Documents with Java CAPS

Generating PDF Documents with Java CAPS Holger Paffrath July 2009 This tutorial will go through how to create a PDF document in Java CAPS. To create t...
Author: Tiffany Sims
10 downloads 1 Views 968KB Size
Generating PDF Documents with Java CAPS Holger Paffrath July 2009 This tutorial will go through how to create a PDF document in Java CAPS. To create the PDF document, we will use an Open Office document as the template and then use Open Office to generate the PDF with calls from Java CAPS. This is handy in generating automated letters or reports and rather than using a flat file allows you to add a little formatting to your report. This example is used to generate a PDF document, but you can use the same call to generate Microsoft Word Documents, HTML pages, RTF pages and other numerous outputs. The differences are only a single parameter value which will be indicated in the tutorial.

Introduction Open Office was built using a base technology called UNO (Universal Network Object). This technology allows you to utilize components that interact across different computer languages, platforms and technology. You can access UNO components through the UNO API (Application Programming Interface). This technology thus allows us to interact with OpenOffice which is how we will generate our PDF documents. Therefore for this tutorial, you will need to download and install OpenOffice. The latest version of OpenOffice can be found at http://OpenOffice.org. To give you an overview of what we will be doing in this tutorial, see the diagram below.

Java CAPS will be picking up an Open Office Document which will have fields specified. This document will then be streamed to Open Office through the UNO API Calls. Java CAPS will then specify which fields will be populated in the document and their respective values. Java CAPS will request OpenOffice to stream back the populated document to Java CAPS in the specified format. In this case it will be PDF. A Web service will be created to expose the whole process as a service.

Open Office Install First off, if you haven't already got open office or StarOffice, install OpenOffice from http://OpenOffice.org. OpenOffice is a free open source alternative to Microsoft Office. It is supported on a number of platforms including Windows, Linux, Mac, Solaris. OpenOffice will quite happily sit on a computer already running Microsoft Office. Alternatively, you do not need to install OpenOffice on the computer that is running Java CAPS. It can be running on a separate system. We just need to have a network connection between the two systems and communication over port 8000 open.

Install OpenOffice SDK The OpenOffice SDK (Software Development Kit) gives us the APIs to communicate with UNO. The SDK can be found at http://download.openoffice.org/3.0.0/sdk.html The OpenOffice SDK needs to be installed on the same system that OpenOffice is installed obviously.

Running OpenOffice Before we can use anything developed to communicate with OpenOffice, we need to start OpenOffice. Since OpenOffice is to be used as a service, not as an application, we need to start it up in what is known as “Headless” mode. In this mode, OpenOffice runs in the background. Any documents opened by OpenOffice will not be shown on the screen. This gives us a clean runtime environment. The only problem is that if you need to modify the template, you have to kill the headless instance of OpenOffice then you can start OpenOffice normally. To start OpenOffice in Headless mode, enter the following on the command line in the “/program” directory. soffice.exe -headless -accept="socket,host=localhost,port=8100;urp;StarOffice.Service"

Create Template Before we continue, lets create an OpenOffice document ready for population. If you have started OpenOffice in headless mode as per the above command line, kill the soffice.exe process. You can re-start OpenOffice in headless mode after you have created your template. Create an OpenOffice Document with fields ready for population. Create a new Document in Open Office. For the purposes of this tutorial, I have created a simple form where the Name and address is displayed.

In this template, we have areas to put the details, but no place markers, so we'll add them now. Select the “Name” entry box and select “Insert/Fields/Other”.

Select the “Variables” tab, then the Type as “Set Variable” and the Format as “Text”. Give the variable a name, in this case “NAME” and a default value. In this case I have given it “%NAME%”.

Click “Insert” then “Close”. You will now have a new field in your document with “%NAME% as the value.

Repeat this Process for Other Fields giving Street

%STREET%

City

%CITY%

PostCode

%POSTCODE%

State

%STATE%

Note : There is no relevance to the percentage “%” symbol wrapping the values. I'm just using this as an indicator for the default values. Save your template.

OpenOffice Plugin Once we have installed OpenOffice, we now need to install the OpenOffice plugin into Netbeans. Bring up Netbeans and select “Tools” then “Plugins”.

You will then see a Dialog box with the installed plugins. Select the “Plugins Settings” tab.

Make sure that the “NetBeans Beta” check box is checked. As of writing, the OpenOffice plugin was still in Beta, but works quite well. Once you have checked “NetBeans Beta”, the “Available Plugins” tab will be available if it isn't already and a number of new Plugins will now be available. Click on the “Available Plugins” Tab.

Scroll down the list and select the “OpenOffice.org API Plugin” and click the “Install” button on the bottom left of the box. Accept the defaults and license agreement and the plugin should start installing.

Once complete, click Finished. The OpenOffice plugin is now installed. To configure the plugin, go to “Tools/Options”

Select the “Miscellaneous” Button, then the “OOo API Plugin” tab.

Make sure that the “OpenOffice.org Installation” and the “OpenOffice.org SDK Installation” are populated correctly. That's it for the preparation. Now we can start coding.

Creating the Wrapper For this implementation, I created a wrapper for the OpenOffice API. This allowed me to hide a lot of the complexity in the Java CAPS implementation. It also allows me to re-use the implementation for future use in JBI projects or basically any other implementation in the future. So lets start by creating a new project. In Netbeans, select “File” then “New Project”

Select “OpenOffice.org” then “OpenOffice.org Client Application”.

Then click Next. Give the Project a name and Package name, and a location where the project will be saved.

Then click “Finish”.

You should now have a new project called “OpenOfficeWrapper” or whatever name you gave it previously.

As a base for this Wrapper API, I have taken the code written by hol.sten (Great beer!!) which can be found at “http://user.services.openoffice.org/en/forum/viewtopic.php?f=44&t=3801 “ In this tutorial, the author has given 3 classes. The first, OOoInputStream implements XInputStream and the XSeekable. The OOoInputStream constructor allows us to take a byte array (Our document) and converts it into a stream format that the OpenOffice API can handle. The OOoOutputStream class allows us to do the opposite, convert the OpenOffice stream back into a byte array. The third class provided gives us an example of converting an odt (OpenOffice native document format) document into a PDF document. It might be a worth while exercise to try to get this example working before continuing. In the mean time, add the OOoInputStream and OOoOutputStream classes to your project and delete the OpenOfficeWrapper.java file. We won't be needing it.

Right Click the com.sun.OpenOffice package and select “New/Java Class...”.

Give this class the name “populateTemplate” and accept all other defaults and click “Finish”.

Replace the code with that supplied in the Source Code section of this document for “populateTemplate.java”. Save and build the project. There are two areas of interest in the source code. The first area is the argument to the call to populateTemplate. public byte[] populateTemplate(OOoInputStream input, OOoOutputStream output, HashMap hm) throws Exception {

Here we see that we are providing an OooInputStream, OooOutputStream for the input and output result. The final is a hashmap. This hashmap contains the variable names and values that we are going to populate into the document. The names have to match exactly the names specified in the OpenOffice Document template. For example, for our test template, the following would be used to populate the hashmap.

HashMap hm = new HashMap(46); hm.put("Name", "Holger Paffrath"); hm.put("Street", "476 St Kilda Rd"); hm.put("City", "Melbourne"); hm.put("PostCode", "3000"); hm.put("State", "Victoria");

The next area of interest in the source code is how we do the pair matching with what is in the document and what is in the hash map. Then going about setting/replacing the value. Here we are going through the fields in the OpenOffice document. Then we check to see if the field exists in the hashmap. If the field exists, we then replace the value with that stored in the hashmap. while (e.hasMoreElements()) { Any tf = (Any) e.nextElement(); XTextField xtf = (XTextField) tf.getObject(); // get the properties of the field XPropertySet xPropertySet = (XPropertySet) UnoRuntime.queryInterface(XPropertySet.class, xtf); Property[] arrprop = xPropertySet.getPropertySetInfo().getProperties(); try { // for ms-word mailmergefield the fieldcode looks // like: MERGEFIELD FIELD_3 * MERGEFORMAT String fieldName = (String) xPropertySet.getPropertyValue("VariableName"); // Check if the field exists in the hashmap. if (hm.containsKey(fieldName)) { String value = (String) hm.get(fieldName); // set the content of the field xPropertySet.setPropertyValue("Content", value); } } catch (UnknownPropertyException ex) { // Fieldcode property doesn't exist, ignore System.out.println("[===] Field property does not exist - ignore"); } }

If you recall from above when we set the variables in the template, there was a number of types of fields that could be added. User Fields, Input Fields and various properties. All these fields come up in the property lookup. To identify different types of fields, they are perpended with different information. Only the variable field represents the Name set in the document. This makes coding easier hence the reason a variable was chosen. The final piece of code which will be of interest is the following. // Write the data to PDF convertProps[0].Name = "OutputStream"; convertProps[0].Value = output; convertProps[1].Name = "FilterName"; convertProps[1].Value = "writer_PDF_Export";

Here we are telling the system that the output format of the document we want to produce is in PDF format. This is done by specifying that the filter is “write_PDF_Export”. PDF Is not the only format that can be produced. By specifying the filter type, the final document can be specified in any number of formats including Microsoft Word, RTF, HTML, Lotus, Word Perfect All the supported formats can be found at : http://wiki.services.openoffice.org/wiki/Framework/Article/Filter/FilterList_OOo_3_0

Testing the Wrapper I have included source code to test the populateTemplate.java source file. This test program will read in the test file from C:\temp\Template.odt. Populate the template and then output the result as a PDF document to C:\Temp\ResultTemplate.pdf. The final result should produce an output like the following.

Note : If you get the following error while running the test....

com.sun.star.connection.NoConnectException: java.net.ConnectException: Connection refused: connect at com.sun.star.lib.connections.socket.socketConnector.connect(socketConnector.java:166) at com.sun.star.comp.connections.Connector.connect(Connector.java:141) at com.sun.star.comp.urlresolver.UrlResolver$_UrlResolver.resolve(UrlResolver.java:128) at com.sun.OpenOffice.populateTemplate.populateTemplate(populateTemplate.java:49) at com.sun.OpenOffice.testPopulateTempate.main(testPopulateTempate.java:67) BUILD SUCCESSFUL (total time: 1 second)

This has occurred because OpenOffice has not been started in Headless mode. Start OpenOffice using the following command : C:\Program Files (x86)\Sun\StarOffice 9\program>soffice.exe -headless -accept="socket,host=localhost,port=8100;urp;StarOffice.Service"

From the “/program” directory.

Create Java CAPS Project (To Complete) Now that we have our wrapper class, lets create a Java CAPS project to call the wrapper. Based on a previous tutorial I wrote on how to create a jcdWebService1, we are going to create a web service that will populate the template and return the resultant document in base64 format. Start off by selecting “File” then “New Project” Select “CAPS\ESB” then “CAPS Repository based Project” then click “Next”

Give the project the name of “CAPSPDFExample”

Right click the “CAPSPDFExample” project and select “New/XML Schema Definition”. 1 http://blogs.sun.com/jcapsuser/entry/creating_a_simple_web_service

Using “Creating a Simple Web Service from a JCD” totorial as a guide, create an XML Schema with the following elements all of type “xsd:string”

Export the Request and Response nodes in the XML Schema and create a jcd called jcdPDFConverter using a new web service with an Operation of opPDFConverter. This jcd should use the Request node for the input and the Response node for the output. You should now have these components.

Now we need to import the wrapper class that we created previously into the jcd we have just created. Right click on “CAPSPDFExample” project and select “Import/File”.

In the dialog box, browse to the directory where your OpenOfficeWrapper project is saved and go into the “dist” directory. There you will find the jar file we are after. Select it, then press “Select”. Finally press the “Import” button.

The OpenOfficeWrapper jar file will now be available in the Java CAPS project.

Repeat the above process for the following OpenOffice jar files • juh.jar • jurt.jar • ridl.jar These files can be found in the “/URE/Java” directory of the OpenOffice installation.

Open the “jcdPDFConverter” and click on the “Import Jar File” Icon as indicated below.

Add the OpenOfficeWrapper.jar, juh.jar, jurt.jar and ridl.jar files to the project and click “Close”.

Add the source code for the jcd and build the project. Remember to configure the Java CAPS environment as per the instructions in the “Creating a Simple We Service from a JCD” tutorial.

There are 4 segments of the code that will be of interest. // Read the template file into Java CAPS java.io.File sourceFile = new java.io.File("c:/template/Template.odt"); String inputFileName = sourceFile.getCanonicalPath().replace('\\', '/'); ByteArrayOutputStream baos = new ByteArrayOutputStream(); logger.info("[===] Input File Name = " + inputFileName); FileInputStream fis = new FileInputStream(inputFileName); InputStream inputFile = new BufferedInputStream(fis); // Retrieve the template file into memory as a byte array. byte[] b = new byte[fis.available()]; fis.read(b); baos.write(b); fis.close();

This first segment deals with retrieving the template to a byte array. As you can see in the code, we are retrieving the file from the C:/template directory. So before you run the project, you may want to place your template file in that directory. /* CONVERSION CODE * */ // Create Input Stream - Specify the Template file OOoInputStream inputStream = new com.sun.OpenOffice.OOoInputStream(baos.toByteArray()); // Create Output Stream OOoOutputStream outputStream = new OOoOutputStream(); populateTemplate myPopTemplate = new populateTemplate(); // Try empty filter. byte[] myDocument = myPopTemplate.populateTemplate(inputStream, outputStream, populateHashMap(input));

The second segment of code deals with the conversion and population of the template. Since all the logic is in the wrapper class, all we need to do is specify the input stream, output stream and call the populateTemplate method. public HashMap populateHashMap(stcgen.fcxotd.http___localhost_12000_repository_repository6u1_CA1487746138.RequestD ocument input) throws Exception { HashMap hm = new HashMap(); hm.put("Name", input.getRequest().getName()); hm.put("Street", input.getRequest().getStreet()); hm.put("City", input.getRequest().getCity()); hm.put("PostCode", input.getRequest().getPostCode()); hm.put("State", input.getRequest().getState()); return hm; }

To populate the hashmap, we have specific code that will map the fields from the Web Service input to a hashmap. output.getResponse().setDocument(new BASE64Encoder().encode(myDocument));

The final piece of code is to format the response. We are base64 encoding the document which is in byte array format as the field takes a string. There is no particular reason for base64 encoding. I just like dealing with Strings. Base64 encoding is an encoding scheme that encodes binary data into a base64 representation which uses a character set of printable characters. Finally, create your connectivity map and deployment profile similar to the tutorial Creating a Simple We Service from a JCD” Now that we have our web service built and our environment in Java CAPS configured, we now need to add the required jar files to Glassfish.

Glassfish Configuration Log into the Glassfish application server's Admin console using http://:4848.

Click on “Application Server” then select the “JVM Settings” tab and finally select “Path Settings”.

Add the following to the Classpath Suffix for Glassfish \URE\java\juh.jar \URE\java\jurt.jar \URE\java\ridl.jar \Basis\program\classes\unoil.jar Add the following to the Native Library Path Prefix for Glassfish \Basis\sdk\classes\win\unowinreg.dll where is the full path to your OpenOffice install. See the figure below for an example entry.

Save your changes and re-start the Glassfish server. You will now be in a position to deploy and run your project.

Testing the Project Now that the project is up and running, we need to test it. Again, using the “Creating A Simple Web Service from a JCD” tutorial as a guide, add the WSDL generated when you built the project to SOAPUI. Expand out the tree and double click on Request1. This will give you the details for the request.

Fill in the Name, Street, City etc with any detail you wish and then press the “Submit Request” button as shown.

The final result should be an XML Response containing the base64 encoded document.

Note : If you get the following response,

This indicates that Open Office is not running in headless mode, start OpenOffice using the following command line. soffice.exe -headless -accept="socket,host=localhost,port=8100;urp;StarOffice.Service"

Now, our base64 encoded document is in a great format for transmission, we can also store the data in a CLOB (or convert the data back to a byte array and store in a BLOB) in a database. We could also write a test Java CAPS application to call the web service, retrieve the base64 encoded data, convert the data back to a byte array and store it to a file. This will give us our PDF document. For the purposes of this tutorial, we're going to leave the data as is, and use a tool to do the conversion for us. Go to the following URL. http://www.motobit.com/util/base64-decoder-encoder.asp This web site allows you to encode or decode base64 data. In your result box, Copy the Base64 encoded data. This is everything between the tags and place the data into the Text box in the above web site. Change the setting to “decode” and export the data to a file. I suggest using an extension of .pdf for the filename.

Click the “Convert the source data” The final result will be a PDF document containing one page with the details you specified in your web service call.

Summary In this tutorial, you have seen how to leverage the OpenOffice UNO API to populate templates with Java and hence Java CAPS. The final document can then be processed any number of ways. It can be stored either in a file or a database, emailed, printed (you can interact with OpenOffice to print the document to a printer) faxed (again through using OpenOffice to print to a fax printer) etc. Along with this tutorial, I have uploaded the Netbeans and Java CAPS projects used in its creation. The file can be found at : http://mediacast.sun.com/users/jcapsuser/media/GeneratingPDFDocumentsWithJavaCAPS.zip/details If you or your company have issues using OpenOffice as it is OpenSource software and is not a supported product, Sun have StarOffice which is a supported version of OpenOffice.

Source Code /* * populateTemplate.java * * Created on 2009.07.10 - 14:58:51 * */ package com.sun.OpenOffice; import import import import import import import import import import import import import import import import import import import

com.sun.star.beans.PropertyValue; com.sun.star.comp.helper.Bootstrap; com.sun.star.bridge.UnoUrlResolver; com.sun.star.bridge.XUnoUrlResolver; com.sun.star.lang.XMultiComponentFactory; com.sun.star.uno.UnoRuntime; com.sun.star.beans.XPropertySet; com.sun.star.lang.XComponent; com.sun.star.beans.Property; com.sun.star.beans.UnknownPropertyException; com.sun.star.container.XEnumeration; com.sun.star.container.XEnumerationAccess; com.sun.star.frame.XStorable; com.sun.star.sdbc.XCloseable; com.sun.star.style.XStyleFamiliesSupplier; com.sun.star.text.XTextField; com.sun.star.text.XTextFieldsSupplier; com.sun.star.uno.Any; java.util.HashMap;

/** * * @author hpaffrath */ public class populateTemplate { /** Creates a new instance of populateTemplate */ public populateTemplate() { } /** * @param args the command line arguments */ public byte[] populateTemplate(OOoInputStream input, OOoOutputStream output, HashMap hm) throws Exception { try { // get the remote office component context com.sun.star.uno.XComponentContext xComponentContext = Bootstrap.createInitialComponentContext(null); // Create a URL Resolver // create a connector, so that it can contact the office XUnoUrlResolver urlResolver = UnoUrlResolver.create(xComponentContext); Object initialObject = urlResolver.resolve( "uno:socket,host=localhost,port=8100;urp;StarOffice.ServiceManager"); XMultiComponentFactory xMultiComponentFactory = (XMultiComponentFactory) UnoRuntime.queryInterface( XMultiComponentFactory.class, initialObject); // retrieve the component context as property (it is not yet exported from the office) // Query for the XPropertySet interface. XPropertySet xProperySet = (XPropertySet) UnoRuntime.queryInterface( XPropertySet.class, xMultiComponentFactory); // Get the default context from the office server. Object oDefaultContext = xProperySet.getPropertyValue("DefaultContext"); // now create the desktop service // NOTE: use the office component context here! Object oDesktop = xMultiComponentFactory.createInstanceWithContext( "com.sun.star.frame.Desktop", xComponentContext); // Create the component Loader com.sun.star.frame.XComponentLoader xComponentLoader = (com.sun.star.frame.XComponentLoader) UnoRuntime.queryInterface(com.sun.star.frame.XComponentLoader.class, oDesktop); //Set the conversion properties PropertyValue[] convertProps = new PropertyValue[2];

convertProps[0] = new PropertyValue(); convertProps[0].Name = "InputStream"; convertProps[0].Value = input; convertProps[1] = new PropertyValue(); convertProps[1].Name = "Hidden"; convertProps[1].Value = new Boolean(true); // Load the document as a stream XComponent xDoc = xComponentLoader.loadComponentFromURL( "private:stream", "_blank", 0, convertProps); if (xDoc != null) { // Retrieve Fields XTextFieldsSupplier fieldSupplier = (XTextFieldsSupplier) UnoRuntime.queryInterface(XTextFieldsSupplier.class, xDoc); XStyleFamiliesSupplier styleFamiliesSupplier = (XStyleFamiliesSupplier) UnoRuntime.queryInterface(XStyleFamiliesSupplier.class, xDoc); // View the fields in the document String[] elementNames = fieldSupplier.getTextFieldMasters().getElementNames(); for (int i = 0; i < elementNames.length; i++) { System.out.println("Element No [" + i + "] name = [" + elementNames[i] + "]"); } XEnumerationAccess xEnumeratedFields = fieldSupplier.getTextFields(); XEnumeration e = xEnumeratedFields.createEnumeration(); while (e.hasMoreElements()) { Any tf = (Any) e.nextElement(); XTextField xtf = (XTextField) tf.getObject(); // get the properties of the field XPropertySet xPropertySet = (XPropertySet) UnoRuntime.queryInterface(XPropertySet.class, xtf); Property[] arrprop = xPropertySet.getPropertySetInfo().getProperties(); try { // for ms-word mailmergefield the fieldcode looks // like: MERGEFIELD FIELD_3 * MERGEFORMAT String fieldName = (String) xPropertySet.getPropertyValue("VariableName"); // Check if the field exists in the hashmap. if (hm.containsKey(fieldName)) { String value = (String) hm.get(fieldName); // set the content of the field xPropertySet.setPropertyValue("Content", value); } } catch (UnknownPropertyException ex) { // Fieldcode property doesn't exist, ignore System.out.println("[===] Field property does not exist - ignore"); } } // Write the data to PDF convertProps[0].Name = "OutputStream"; convertProps[0].Value = output; convertProps[1].Name = "FilterName"; convertProps[1].Value = "writer_PDF_Export"; /* * FILTER LIST * http://wiki.services.openoffice.org/wiki/Framework/Article/Filter/FilterList_OOo_2_1 * */ XStorable xStorable = (XStorable) UnoRuntime.queryInterface( XStorable.class, xDoc); xStorable.storeToURL("private:stream", convertProps); XCloseable xcloseable = (XCloseable) UnoRuntime.queryInterface(XCloseable.class, xDoc); } //Return } catch (java.lang.Exception e) { e.printStackTrace(); } finally { return (output.toByteArray()); } } }

/* * testPopulateTemplate.java * * Created on 2009.03.12 - 13:46:21 * */ /* * * Before running this program you need to start up open office in server mode. * To do so, in the open office (or Staroffice) binary directory enter * soffice.exe -headless -accept="socket,host=localhost,port=8100;urp;StarOffice.Service" * Then you should be able to run the program. * * // References * http://www.it-eye.nl/weblog/2008/07/23/mailmerge-ms-word-template-using-openoffice-and-java/ * http://www.oooforum.org/forum/viewtopic.phtml?t=61386 */ package com.sun.OpenOffice; import import import import import import

java.io.BufferedInputStream; java.io.ByteArrayOutputStream; java.io.FileInputStream; java.io.FileOutputStream; java.io.InputStream; java.util.HashMap;

/**import com. * * @author hpaffrath */ public class testPopulateTempate { private static String sOutputDir; /** Creates a new instance of FirstUnoContact */ public testPopulateTempate() { } /** * @param args the command line arguments */ public static void main(String[] args) { try { // Read the file as a stream java.io.File sourceFile = new java.io.File("c:/temp/Template.odt"); String inputFileName = sourceFile.getCanonicalPath().replace('\\', '/'); ByteArrayOutputStream baos = new ByteArrayOutputStream(); System.out.println("[===] Input File Name = " + inputFileName); FileInputStream fis = new FileInputStream(inputFileName); InputStream inputFile = new BufferedInputStream(fis); byte[] b = new byte[fis.available()]; fis.read(b); baos.write(b); fis.close(); /* * CONVERSION CODE * */ // Create Input Stream OOoInputStream inputStream = new OOoInputStream(baos.toByteArray()); // Create Output Stream OOoOutputStream outputStream = new OOoOutputStream(); populateTemplate myPopTemplate = new populateTemplate(); // Try empty filter. byte[] myPDF = myPopTemplate.populateTemplate(inputStream, outputStream, populateHashMap() ); /* * END CONVERSION CODE * */ // Write to File String outputFilename = "C:\\temp\\ResultTemplate.pdf"; FileOutputStream outputFile = new FileOutputStream(outputFilename); outputFile.write(outputStream.toByteArray()); outputFile.close(); outputStream.closeOutput();

outputStream.close(); inputStream.closeInput(); inputStream.close(); Runtime.getRuntime().exit(0); } catch (Exception e) {

}

e.printStackTrace(); Runtime.getRuntime().exit(0);

} public static HashMap populateHashMap() { //Retrieve Details from OTD. HashMap hm = new HashMap(46); hm.put("Name", "Holger Paffrath"); hm.put("Street", "476 St Kilda Rd"); hm.put("City", "Melbourne"); hm.put("PostCode", "3000"); hm.put("State", "Victoria"); return hm; }

}

/* * jcdPDFConverter * * Created on 2009.07.12 * */ package CAPSPDFExample; import java.io.FileInputStream; import import import import import import import import import import import import import import

com.sun.star.beans.PropertyValue; com.sun.star.comp.helper.Bootstrap; com.sun.star.bridge.UnoUrlResolver; com.sun.star.bridge.XUnoUrlResolver; com.sun.star.lang.XMultiComponentFactory; com.sun.star.uno.UnoRuntime; com.sun.star.beans.XPropertySet; com.sun.star.lang.XComponent; java.io.BufferedInputStream; java.io.ByteArrayOutputStream; java.io.InputStream; sun.misc.BASE64Encoder; com.sun.OpenOffice.*; java.util.HashMap;

public class jcdPDFConverter { public public public public

com.stc.codegen.logger.Logger logger; com.stc.codegen.alerter.Alerter alerter; com.stc.codegen.util.CollaborationContext collabContext; com.stc.codegen.util.TypeConverter typeConverter;

public void opPDFConverter(stcgen.fcxotd.http___localhost_12000_repository_repository6u1_CA1487746138.RequestDo cument input, stcgen.fcxotd.http___localhost_12000_repository_repository6u1_CA1487746138.ResponseDocument output) throws Throwable { try { // Read the template file into Java CAPS java.io.File sourceFile = new java.io.File("c:/template/Template.odt"); String inputFileName = sourceFile.getCanonicalPath().replace('\\', '/'); ByteArrayOutputStream baos = new ByteArrayOutputStream(); logger.info("[===] Input File Name = " + inputFileName); FileInputStream fis = new FileInputStream(inputFileName); InputStream inputFile = new BufferedInputStream(fis); // Retrieve the template file into memory as a byte array. byte[] b = new byte[fis.available()]; fis.read(b); baos.write(b); fis.close(); /* CONVERSION CODE * */ // Create Input Stream - Specify the Template file OOoInputStream inputStream = new com.sun.OpenOffice.OOoInputStream(baos.toByteArray()); // Create Output Stream OOoOutputStream outputStream = new OOoOutputStream(); populateTemplate myPopTemplate = new populateTemplate(); // Try empty filter. byte[] myDocument = myPopTemplate.populateTemplate(inputStream, outputStream, populateHashMap(input)); output.getResponse().setDocument(new BASE64Encoder().encode(myDocument)); /* END CONVERSION CODE * */ outputStream.closeOutput(); outputStream.close(); inputStream.closeInput(); inputStream.close(); } catch (Exception e) { logger.info("Exception = " + e.getMessage()); } }

public HashMap populateHashMap(stcgen.fcxotd.http___localhost_12000_repository_repository6u1_CA1487746138.RequestD ocument input) throws Exception { HashMap hm = new HashMap(); hm.put("Name", input.getRequest().getName()); hm.put("Street", input.getRequest().getStreet()); hm.put("City", input.getRequest().getCity()); hm.put("PostCode", input.getRequest().getPostCode()); hm.put("State", input.getRequest().getState()); return hm; } }

References Java ODT Help http://www.oooforum.org/forum/viewtopic.phtml?t=61271 Developers Guide as ODT (PDF Download does not work) http://wiki.services.openoffice.org/wiki/Documentation/Wiki_Books Open Office Java API http://weblogs.java.net/blog/tchangu/archive/2005/12/open_office_jav_1.html Example Java create, populate, save template-based document http://www.oooforum.org/forum/viewtopic.phtml?t=61386 [Java solution] Using XInputStream and XOutputStream http://user.services.openoffice.org/en/forum/viewtopic.php?f=44&t=3801 List of Filters for OpenOffice http://wiki.services.openoffice.org/wiki/Framework/Article/Filter/FilterList_OOo_3_0 Creating a Simple Web Service from a JCD http://blogs.sun.com/jcapsuser/entry/creating_a_simple_web_service Online base64 decoder http://www.motobit.com/util/base64-decoder-encoder.asp SOAPUI Web Service testing tool http://www.soapui.org Open Office http://www.openoffice.org Star Office http://www.sun.com/software/staroffice/index.jsp

Suggest Documents