/*
* ===========================================================================
* 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();
}
}