| 1 |
|
|
| 2 |
|
|
| 3 |
|
|
| 4 |
|
|
| 5 |
|
|
| 6 |
|
|
| 7 |
|
|
| 8 |
|
|
| 9 |
|
|
| 10 |
|
|
| 11 |
|
|
| 12 |
|
|
| 13 |
|
|
| 14 |
|
|
| 15 |
|
|
| 16 |
|
|
| 17 |
|
|
| 18 |
|
|
| 19 |
|
|
| 20 |
|
|
| 21 |
|
|
| 22 |
|
|
| 23 |
|
|
| 24 |
|
|
| 25 |
|
|
| 26 |
|
|
| 27 |
|
|
| 28 |
|
|
| 29 |
|
|
| 30 |
|
|
| 31 |
|
|
| 32 |
|
package net.sourceforge.pebble.web.view; |
| 33 |
|
|
| 34 |
|
import java.io.ByteArrayInputStream; |
| 35 |
|
import java.io.BufferedOutputStream; |
| 36 |
|
import java.io.IOException; |
| 37 |
|
import java.io.File; |
| 38 |
|
import java.io.FilenameFilter; |
| 39 |
|
|
| 40 |
|
import org.xml.sax.InputSource; |
| 41 |
|
import org.xml.sax.SAXException; |
| 42 |
|
|
| 43 |
|
import org.w3c.dom.Document; |
| 44 |
|
|
| 45 |
|
import javax.xml.parsers.DocumentBuilder; |
| 46 |
|
import javax.xml.parsers.DocumentBuilderFactory; |
| 47 |
|
import javax.xml.parsers.ParserConfigurationException; |
| 48 |
|
|
| 49 |
|
import net.sourceforge.pebble.PebbleContext; |
| 50 |
|
import net.sourceforge.pebble.domain.Tag; |
| 51 |
|
import net.sourceforge.pebble.domain.BlogEntry; |
| 52 |
|
import net.sourceforge.pebble.util.StringUtils; |
| 53 |
|
import net.sourceforge.pebble.web.listener.PebblePDFCreationListener; |
| 54 |
|
|
| 55 |
|
import javax.servlet.ServletContext; |
| 56 |
|
import javax.servlet.ServletException; |
| 57 |
|
import javax.servlet.http.HttpServletRequest; |
| 58 |
|
import javax.servlet.http.HttpServletResponse; |
| 59 |
|
|
| 60 |
|
import java.util.Iterator; |
| 61 |
|
|
| 62 |
|
import org.apache.commons.logging.Log; |
| 63 |
|
import org.apache.commons.logging.LogFactory; |
| 64 |
|
|
| 65 |
|
import com.lowagie.text.pdf.PdfWriter; |
| 66 |
|
import com.lowagie.text.pdf.BaseFont; |
| 67 |
|
import com.lowagie.text.DocumentException; |
| 68 |
|
|
| 69 |
|
import org.xhtmlrenderer.pdf.ITextRenderer; |
| 70 |
|
import org.xhtmlrenderer.pdf.TrueTypeUtil; |
| 71 |
|
|
| 72 |
|
|
| 73 |
|
|
| 74 |
|
|
| 75 |
|
|
| 76 |
|
@author |
| 77 |
|
|
|
|
|
| 4,6% |
Uncovered Elements: 104 (109) |
Complexity: 17 |
Complexity Density: 0,18 |
|
| 78 |
|
public class PdfView extends BinaryView { |
| 79 |
|
|
| 80 |
|
|
| 81 |
|
private static Log log = LogFactory.getLog(PdfView.class); |
| 82 |
|
|
| 83 |
|
private static final String SEP = "/"; |
| 84 |
|
private static final String FONTS_PATH = "fonts"; |
| 85 |
|
private static final String THEMES_PATH = "themes"; |
| 86 |
|
private static final String DEFAULT_ENCODING = "UTF-8"; |
| 87 |
|
private static final String PDF_CSS = "pdf.css"; |
| 88 |
|
private static final String SYSTEM_THEME_PATH = HtmlView.SYSTEM_THEME; |
| 89 |
|
|
| 90 |
|
private String filename = "default.pdf"; |
| 91 |
|
private BlogEntry entry; |
| 92 |
|
private long length = 0; |
| 93 |
|
|
|
|
|
| 100% |
Uncovered Elements: 0 (2) |
Complexity: 1 |
Complexity Density: 0,5 |
|
| 94 |
4
|
public PdfView(BlogEntry entry, String filename) {... |
| 95 |
4
|
this.entry = entry; |
| 96 |
4
|
this.filename = filename; |
| 97 |
|
} |
| 98 |
|
|
| 99 |
|
|
| 100 |
|
|
| 101 |
|
|
| 102 |
|
@return |
| 103 |
|
|
|
|
|
| 100% |
Uncovered Elements: 0 (1) |
Complexity: 1 |
Complexity Density: 1 |
|
| 104 |
4
|
public String getContentType() {... |
| 105 |
4
|
return "application/pdf"; |
| 106 |
|
} |
| 107 |
|
|
|
|
|
| 0% |
Uncovered Elements: 1 (1) |
Complexity: 1 |
Complexity Density: 1 |
|
| 108 |
0
|
public long getContentLength() {... |
| 109 |
0
|
return length; |
| 110 |
|
} |
| 111 |
|
|
| 112 |
|
|
| 113 |
|
|
| 114 |
|
|
| 115 |
|
@param |
| 116 |
|
@param |
| 117 |
|
@param |
| 118 |
|
|
|
|
|
| 0% |
Uncovered Elements: 98 (98) |
Complexity: 13 |
Complexity Density: 0,15 |
|
| 119 |
0
|
public void dispatch(HttpServletRequest request, HttpServletResponse response, ServletContext context) throws ServletException {... |
| 120 |
|
|
| 121 |
0
|
try { |
| 122 |
0
|
ITextRenderer renderer = new ITextRenderer(); |
| 123 |
|
|
| 124 |
|
|
| 125 |
0
|
response.setHeader("Content-Disposition", "attachment; filename=" + filename); |
| 126 |
0
|
response.setHeader("Expires", "0"); |
| 127 |
0
|
response.setHeader("Cache-Control", "must-revalidate, post-check=0, pre-check=0"); |
| 128 |
0
|
response.setHeader("Pragma", "public"); |
| 129 |
|
|
| 130 |
0
|
String author = entry.getUser().getName(); |
| 131 |
0
|
String title = entry.getTitle(); |
| 132 |
0
|
String subtitle = entry.getSubtitle(); |
| 133 |
0
|
String body = entry.getBody(); |
| 134 |
0
|
String blogName = entry.getBlog().getName(); |
| 135 |
0
|
String entryPermalink = entry.getPermalink(); |
| 136 |
0
|
String entryDescription = entry.getBlog().getDescription(); |
| 137 |
|
|
| 138 |
|
|
| 139 |
0
|
title = StringUtils.transformHTML(title); |
| 140 |
0
|
subtitle = StringUtils.transformHTML(subtitle); |
| 141 |
0
|
body = StringUtils.unescapeHTMLEntities(body); |
| 142 |
|
|
| 143 |
|
|
| 144 |
0
|
String webApplicationRoot = PebbleContext.getInstance().getWebApplicationRoot() + SEP + THEMES_PATH; |
| 145 |
|
|
| 146 |
|
|
| 147 |
0
|
String fontDirAbsolutePath = webApplicationRoot + SEP + SYSTEM_THEME_PATH + SEP + FONTS_PATH; |
| 148 |
0
|
File fontDir = new File(fontDirAbsolutePath); |
| 149 |
|
|
| 150 |
|
|
| 151 |
|
|
| 152 |
0
|
StringBuffer tags = new StringBuffer(); |
| 153 |
0
|
Iterator<Tag> currentEntryTags = entry.getAllTags().iterator(); |
| 154 |
|
|
| 155 |
|
|
| 156 |
0
|
while (currentEntryTags.hasNext()) { |
| 157 |
0
|
Tag currentTag = currentEntryTags.next(); |
| 158 |
0
|
if (currentTag.getName() != null && !currentTag.getName().equals("")) { |
| 159 |
0
|
tags.append(currentTag.getName()); |
| 160 |
0
|
if (currentEntryTags.hasNext()) { |
| 161 |
0
|
tags.append(","); |
| 162 |
|
} |
| 163 |
|
} |
| 164 |
|
} |
| 165 |
|
|
| 166 |
|
|
| 167 |
0
|
StringBuffer buf = new StringBuffer(); |
| 168 |
0
|
buf.append("<html>"); |
| 169 |
0
|
buf.append("<head>"); |
| 170 |
0
|
buf.append("<meta name=\"title\" content=\"" + title + " - " + blogName + "\"/>"); |
| 171 |
0
|
buf.append("<meta name=\"subject\" content=\"" + title + "\"/>"); |
| 172 |
0
|
buf.append("<meta name=\"keywords\" content=\"" + tags.toString().trim() + "\"/>"); |
| 173 |
0
|
buf.append("<meta name=\"author\" content=\"" + author + "\"/>"); |
| 174 |
0
|
buf.append("<meta name=\"creator\" content=\"Pebble (by pebble.sourceforge.net)\"/>"); |
| 175 |
0
|
buf.append("<meta name=\"producer\" content=\"Flying Saucer (by xhtmlrenderer.dev.java.net)\"/>"); |
| 176 |
0
|
buf.append("<link rel='stylesheet' type='text/css' href='" + entry.getBlog().getUrl() + |
| 177 |
|
THEMES_PATH + SEP + |
| 178 |
|
SYSTEM_THEME_PATH + SEP + |
| 179 |
|
PDF_CSS + "' media='print' />"); |
| 180 |
0
|
buf.append("</head>"); |
| 181 |
0
|
buf.append("<body>"); |
| 182 |
0
|
buf.append("<div id=\"header\" style=\"\">" + blogName + " - " + entryDescription + "</div>"); |
| 183 |
0
|
buf.append("<p>"); |
| 184 |
|
|
| 185 |
|
|
| 186 |
0
|
if (fontDir.isDirectory()) { |
| 187 |
0
|
File[] files = fontDir.listFiles(new FilenameFilter() { |
|
|
|
| 0% |
Uncovered Elements: 2 (2) |
Complexity: 1 |
Complexity Density: 0,5 |
|
| 188 |
0
|
public boolean accept(File dir, String name) {... |
| 189 |
0
|
String lower = name.toLowerCase(); |
| 190 |
|
|
| 191 |
|
|
| 192 |
0
|
return lower.endsWith(".otf") || lower.endsWith(".ttf"); |
| 193 |
|
} |
| 194 |
|
}); |
| 195 |
|
|
| 196 |
0
|
if (files.length > 0) { |
| 197 |
0
|
String fontFamilyName = ""; |
| 198 |
|
|
| 199 |
0
|
renderer.getFontResolver().addFont(files[0].getAbsolutePath(), BaseFont.IDENTITY_H, BaseFont.EMBEDDED); |
| 200 |
0
|
log.info("Added font: " + files[0].getAbsolutePath()); |
| 201 |
|
|
| 202 |
|
|
| 203 |
0
|
BaseFont font = BaseFont.createFont(files[0].getAbsolutePath(), BaseFont.IDENTITY_H , BaseFont.NOT_EMBEDDED); |
| 204 |
0
|
fontFamilyName = TrueTypeUtil.getFamilyName(font); |
| 205 |
|
|
| 206 |
0
|
if (!fontFamilyName.equals("")) { |
| 207 |
|
|
| 208 |
0
|
author = "<div style=\"font-family: " + fontFamilyName + ";\">" + author + "</div>"; |
| 209 |
0
|
title = "<div style=\"font-family: " + fontFamilyName + ";\">" + title + "</div>"; |
| 210 |
0
|
subtitle = "<div style=\"font-family: " + fontFamilyName + ";\">" + subtitle + "</div>"; |
| 211 |
0
|
body = "<div style=\"font-family: " + fontFamilyName + ";\">" + body + "</div>"; |
| 212 |
0
|
log.info("PDFGenerator - Added font family: '" + fontFamilyName + "' to PDF content"); |
| 213 |
|
} |
| 214 |
|
} |
| 215 |
|
} |
| 216 |
|
|
| 217 |
0
|
buf.append("<h1>" + title + "</h1>"); |
| 218 |
0
|
buf.append("<h2>" + subtitle + "</h2>"); |
| 219 |
0
|
buf.append("</p>"); |
| 220 |
0
|
buf.append("<p>" + body + "</p>"); |
| 221 |
0
|
buf.append("<p><br /><br /><br />"); |
| 222 |
0
|
buf.append("<i>Published by " + author + "</i><br />"); |
| 223 |
0
|
buf.append("<i>" + entry.getDate().toString() + "</i><br />"); |
| 224 |
0
|
buf.append("<i><a href=\"" + entryPermalink + "\" title=\"" + entryPermalink + "\">" + entryPermalink + "</a></i>"); |
| 225 |
0
|
buf.append("</p>"); |
| 226 |
0
|
buf.append("</body>"); |
| 227 |
0
|
buf.append("</html>"); |
| 228 |
|
|
| 229 |
0
|
byte[] bytes = buf.toString().getBytes(DEFAULT_ENCODING); |
| 230 |
|
|
| 231 |
0
|
ByteArrayInputStream bais = new ByteArrayInputStream(bytes); |
| 232 |
0
|
DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder(); |
| 233 |
0
|
InputSource is = new InputSource(bais); |
| 234 |
0
|
Document doc = builder.parse(is); |
| 235 |
|
|
| 236 |
|
|
| 237 |
0
|
PebblePDFCreationListener pdfListener = new PebblePDFCreationListener(); |
| 238 |
0
|
pdfListener.parseMetaTags(doc); |
| 239 |
0
|
renderer.setListener(pdfListener); |
| 240 |
0
|
renderer.setDocument(doc, null); |
| 241 |
0
|
renderer.layout(); |
| 242 |
|
|
| 243 |
0
|
BufferedOutputStream bufferedOutput = new BufferedOutputStream(response.getOutputStream()); |
| 244 |
|
|
| 245 |
0
|
renderer.createPDF(bufferedOutput); |
| 246 |
0
|
bufferedOutput.flush(); |
| 247 |
0
|
bufferedOutput.close(); |
| 248 |
|
|
| 249 |
0
|
log.info("Successfully generated PDF document: " + filename); |
| 250 |
|
} |
| 251 |
|
|
| 252 |
|
catch (ParserConfigurationException e) { |
| 253 |
0
|
log.error("Could not create PDF, could not get new instance of DocumentBuilder: " + e); |
| 254 |
|
} |
| 255 |
|
|
| 256 |
|
catch (SAXException e) { |
| 257 |
0
|
log.error("Could not create PDF, could not parse InputSource: " + e); |
| 258 |
|
} |
| 259 |
|
|
| 260 |
|
catch (IOException e) { |
| 261 |
0
|
log.error("Could not create PDF: " + e); |
| 262 |
|
} |
| 263 |
|
|
| 264 |
|
catch (DocumentException e) { |
| 265 |
0
|
log.error("iText could not create PDF document: " + e); |
| 266 |
|
} |
| 267 |
|
|
| 268 |
|
catch (Exception e) { |
| 269 |
0
|
log.error("Could not create PDF: " + e); |
| 270 |
|
} |
| 271 |
|
} |
| 272 |
|
} |