* @param context
*/
public void dispatch(HttpServletRequest request, HttpServletResponse response, ServletContext context) throws ServletException {
try {
ITextRenderer renderer = new ITextRenderer();
//This will be an attachment
response.setHeader("Content-Disposition", "attachment; filename=" + filename);
response.setHeader("Expires", "0");
response.setHeader("Cache-Control", "must-revalidate, post-check=0, pre-check=0");
response.setHeader("Pragma", "public");
String author = entry.getUser().getName();
String title = entry.getTitle();
String subtitle = entry.getSubtitle();
String body = entry.getBody();
String blogName = entry.getBlog().getName();
String entryPermalink = entry.getPermalink();
String entryDescription = entry.getBlog().getDescription();
//Some of the HTML entities need to be escaped to Unicode notation \\uXXXX for XHTML markup to validate
title = StringUtils.transformHTML(title);
subtitle = StringUtils.transformHTML(subtitle);
body = StringUtils.unescapeHTMLEntities(body);
//Build absolute path to: <pebble_root>/themes/_pebble/fonts/
String webApplicationRoot = PebbleContext.getInstance().getWebApplicationRoot() + SEP + THEMES_PATH;
//<pebble_root> + / + themes + / + _pebble + / + fonts
String fontDirAbsolutePath = webApplicationRoot + SEP + SYSTEM_THEME_PATH + SEP + FONTS_PATH;
File fontDir = new File(fontDirAbsolutePath);
//Get blog entry tags for PDF metadata 'keywords'
StringBuffer tags = new StringBuffer();
Iterator<Tag> currentEntryTags = entry.getAllTags().iterator();
//Build a string out of blog entry tags and seperate them by comma
while (currentEntryTags.hasNext()) {
Tag currentTag = currentEntryTags.next();
if (currentTag.getName() != null && !currentTag.getName().equals("")) {
tags.append(currentTag.getName());
if (currentEntryTags.hasNext()) {
tags.append(",");
}
}
}
//Build valid XHTML source from blog entry for parsing
StringBuffer buf = new StringBuffer();
buf.append("<html>");
buf.append("<head>");
buf.append("<meta name=\"title\" content=\"" + title + " - " + blogName + "\"/>");
buf.append("<meta name=\"subject\" content=\"" + title + "\"/>");
buf.append("<meta name=\"keywords\" content=\"" + tags.toString().trim() + "\"/>");
buf.append("<meta name=\"author\" content=\"" + author + "\"/>");
buf.append("<meta name=\"creator\" content=\"Pebble (by pebble.sourceforge.net)\"/>");
buf.append("<meta name=\"producer\" content=\"Flying Saucer (by xhtmlrenderer.dev.java.net)\"/>");
buf.append("<link rel='stylesheet' type='text/css' href='" + entry.getBlog().getUrl() +
THEMES_PATH + SEP +
SYSTEM_THEME_PATH + SEP +
PDF_CSS + "' media='print' />");
buf.append("</head>");
buf.append("<body>");
buf.append("<div id=\"header\" style=\"\">" + blogName + " - " + entryDescription + "</div>");
buf.append("<p>");
//Gets TTF or OTF font file from the font directory in the system theme folder
if (fontDir.isDirectory()) {
File[] files = fontDir.listFiles(new FilenameFilter() {
public boolean accept(File dir, String name) {
String lower = name.toLowerCase();
//Load TTF or OTF files
return lower.endsWith(".otf") || lower.endsWith(".ttf");
}
});
if (files.length > 0) {
String fontFamilyName = "";
//You should always embed TrueType fonts.
renderer.getFontResolver().addFont(files[0].getAbsolutePath(), BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
log.info("Added font: " + files[0].getAbsolutePath());
//Get font family name from the BaseFont object. All this work just to get font family name
BaseFont font = BaseFont.createFont(files[0].getAbsolutePath(), BaseFont.IDENTITY_H , BaseFont.NOT_EMBEDDED);
fontFamilyName = TrueTypeUtil.getFamilyName(font);
if (!fontFamilyName.equals("")) {
//Wrap DIV with font family name around the content of the blog entry
author = "<div style=\"font-family: " + fontFamilyName + ";\">" + author + "</div>";
title = "<div style=\"font-family: " + fontFamilyName + ";\">" + title + "</div>";
subtitle = "<div style=\"font-family: " + fontFamilyName + ";\">" + subtitle + "</div>";
body = "<div style=\"font-family: " + fontFamilyName + ";\">" + body + "</div>";
log.info("PDFGenerator - Added font family: '" + fontFamilyName + "' to PDF content");
}
}
}
buf.append("<h1>" + title + "</h1>");
buf.append("<h2>" + subtitle + "</h2>");
buf.append("</p>");
buf.append("<p>" + body + "</p>");
buf.append("<p><br /><br /><br />");
buf.append("<i>Published by " + author + "</i><br />");
buf.append("<i>" + entry.getDate().toString() + "</i><br />");
buf.append("<i><a href=\"" + entryPermalink + "\" title=\"" + entryPermalink + "\">" + entryPermalink + "</a></i>");
buf.append("</p>");
buf.append("</body>");
buf.append("</html>");
byte[] bytes = buf.toString().getBytes(DEFAULT_ENCODING);
ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
InputSource is = new InputSource(bais);
Document doc = builder.parse(is);
//Listener that will parse HTML header meta tags, and will set them to PDF document as meta data
PebblePDFCreationListener pdfListener = new PebblePDFCreationListener();
pdfListener.parseMetaTags(doc);
renderer.setListener(pdfListener);
renderer.setDocument(doc, null);
renderer.layout();
BufferedOutputStream bufferedOutput = new BufferedOutputStream(response.getOutputStream());
renderer.createPDF(bufferedOutput);
bufferedOutput.flush();
bufferedOutput.close();
log.info("Successfully generated PDF document: " + filename);
}