/* * =========================================================================== * PD4ML: HTML to PDF Converter for Java. * DXL-to-PDF converting agent * * http://pd4ml.com, 2007 * =========================================================================== */ import java.awt.Dimension; import java.awt.Insets; import java.io.BufferedInputStream; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.StringReader; import java.io.StringWriter; import java.net.MalformedURLException; import java.net.URL; import lotus.domino.AgentBase; import lotus.domino.AgentContext; import lotus.domino.Database; import lotus.domino.Document; import lotus.domino.DocumentCollection; import lotus.domino.DxlExporter; import lotus.domino.EmbeddedObject; import lotus.domino.RichTextItem; import lotus.domino.Session; import org.xml.sax.SAXException; import org.zefer.pd4ml.PD4Constants; import org.zefer.pd4ml.PD4ML; import org.zefer.pd4ml.PD4PageMark; import com.lotus.xml.xml4j2dom.XML4JLiaison4dom; import com.lotus.xsl.XSLProcessor; import com.lotus.xsl.XSLTInputSource; import com.lotus.xsl.XSLTResultTarget; public class PdfAgent extends AgentBase { private final static String xslName = "dxl4pd4ml.xsl"; /* configuration switch: XSL location */ private final static boolean readXslFromJar = false; private final static String xslDocumentFormName = "XSL4PD4ML"; private final static String xslDocumentFieldName = "XSLT"; public void NotesMain() { try { Session session = getSession(); AgentContext agentContext = session.getAgentContext(); // System.out.println("AGENT start."); Database db = agentContext.getCurrentDatabase(); String xsl = null; if (readXslFromJar) { xsl = getXsl(); // the method uses Java ClassLoader to read XSL. Works for v6.5.4, but fails for older versions // (according to some reports) } else { // bulky, but a standard for Domino way to store XSL documents. // useful for debug and XSL refining DocumentCollection dcx = db.search("@Contains(Form; \"" + xslDocumentFormName + "\")"); Document xsldoc = dcx.getFirstDocument(); if (xsldoc != null) { xsl = xsldoc.getItemValueString(xslDocumentFieldName); } else { // looks like there is no form named XSL4PD4ML // try to read XSL from JAR file throw new IOException( "Can not find " ); } } // System.out.println("XSL: " + xsl); // collect selected documents DocumentCollection dc = agentContext.getUnprocessedDocuments(); Document doc = dc.getFirstDocument(); while (doc != null) { Document tmp = db.createDocument(); RichTextItem rti = tmp.createRichTextItem("PD4MLBody"); doc.renderToRTItem(rti); DxlExporter dxl = session.createDxlExporter(); dxl.setConvertNotesBitmapsToGIF(true); dxl.setOutputDOCTYPE(false); String xml = dxl.exportDxl(tmp); // System.out.println("DXL FORM: " + xml); String html = transformXML(xml, xsl); // System.out.println("HTML: " + html); File pdf = File.createTempFile("pd4ml", ".pdf"); java.io.FileOutputStream fos = new java.io.FileOutputStream(pdf); generatePDF( html, fos, PD4Constants.A4, "java:/fonts", // the reference points to a fonts collection packed to a JAR. // an alternative would be to reference a local font directory: "c:/windows/fonts" // read more about font directory configuration: http://pd4ml.com/reference.htm#7.1 "DXL to PDF convesion result. $[page] of $[total]"); doc.removeItem("PdfAttachment"); doc.save(true, true); RichTextItem obj = (RichTextItem) doc.getFirstItem("PdfAttachment"); if (obj == null) { RichTextItem attx = doc.createRichTextItem("PdfAttachment"); attx.embedObject(EmbeddedObject.EMBED_ATTACHMENT, null, pdf.getAbsolutePath(), "pdfattachment"); fos.flush(); fos.close(); } doc.save(true, true); pdf.delete(); doc = dc.getNextDocument(); } // System.out.println("AGENT done."); } catch (SAXException e) { e.printStackTrace(); } catch (Exception e) { e.printStackTrace(); } } public static final void generatePDF(String inputHTML, OutputStream fos, Dimension format, String fontsDir, String footerBody) throws Exception { // the method uses only basic PD4ML API calls // more info: // Reference: http://pd4ml.com/reference.htm // Javadoc: http://pd4ml.com/api/index.html PD4ML pd4ml = new PD4ML(); pd4ml.setPageInsets(new Insets(20, 10, 10, 10)); pd4ml.setHtmlWidth(1000); pd4ml.setPageSize(format); if (fontsDir != null && fontsDir.length() > 0) { pd4ml.useTTF(fontsDir, true); } if (footerBody != null && footerBody.length() > 0) { PD4PageMark footer = new PD4PageMark(); footer.setAreaHeight(-1); footer.setHtmlTemplate(footerBody); pd4ml.setPageFooter(footer); } // pd4ml.enableDebugInfo(); // in Lotus environment the debug info appears under File->Tools->Show Java Debug Console pd4ml.render(new StringReader(inputHTML), fos, new URL("file:."), "utf-8"); fos.flush(); fos.close(); } public static final String transformXML(String xml, String xsl) throws SAXException, MalformedURLException, IOException { XSLProcessor xp = new XSLProcessor(new XML4JLiaison4dom()); StringReader xmlSource2 = new StringReader(xml); StringReader xslSource2 = new StringReader(xsl); StringWriter sw = new StringWriter(); XSLTInputSource xs = new XSLTInputSource(xmlSource2); XSLTInputSource xt = new XSLTInputSource(xslSource2); XSLTResultTarget tout = new XSLTResultTarget(sw); xp.process(xs, xt, tout); return sw.toString(); } public String getXsl() throws IOException { ByteArrayOutputStream fos = new ByteArrayOutputStream(); byte buffer[] = new byte[2048]; InputStream is = getClass().getClassLoader().getResourceAsStream(xslName); BufferedInputStream bis = new BufferedInputStream(is); int read; do { read = bis.read(buffer, 0, buffer.length); if (read > 0) { fos.write(buffer, 0, read); } } while (read > -1); fos.close(); bis.close(); is.close(); return new String(fos.toByteArray()); } /* * The two methods below are useful for offline debug. In order to run the Java class * offline you need in the classpath the following: * * pd4ml.jar (or pd4ml_demo.jar) * ss_css2.jar * xml4j.jar * lotusXSL.jar * notes.jar * * Please do not forget to pre-configure fonts dir with the command line call: * java -jar pd4ml.jar -configure.fonts c:/windows/fonts * * */ public static void main( String args[] ) { try { String xml = readFile("dxl_sample.xml"); String xsl = readFile(xslName); String html = transformXML(xml, xsl); System.out.println("HTML: " + html); File pdf = File.createTempFile("pd4ml", ".pdf"); java.io.FileOutputStream fos = new java.io.FileOutputStream(pdf); generatePDF( html, fos, PD4Constants.A4, "c:/windows/fonts", "DXL to PDF convesion result. $[page] of $[total]"); Runtime.getRuntime().exec( "C:\\Program Files\\Adobe\\Acrobat 7.0\\Reader\\AcroRd32.exe " + pdf.getAbsolutePath() ); } catch (Exception e) { e.printStackTrace(); } } private final static String readFile( String path ) throws Exception { File f = new File( path ); FileInputStream is = new FileInputStream(f); BufferedInputStream bis = new BufferedInputStream(is); ByteArrayOutputStream fos = new ByteArrayOutputStream(); byte buffer[] = new byte[2048]; int read; do { read = is.read(buffer, 0, buffer.length); if (read > 0) { // something to put down fos.write(buffer, 0, read); } } while (read > -1); fos.close(); bis.close(); is.close(); return fos.toString(); } }