pdfview.java

### File Source: pdfview.java

             /*
        P/P   *  Method: void net.sourceforge.pebble.web.view.PdfView$1(PdfView)
              */
         1  /*
         2   * Copyright (c) 2003-2006, Simon Brown
         3   * All rights reserved.
         4   *
         5   * Redistribution and use in source and binary forms, with or without
         6   * modification, are permitted provided that the following conditions are met:
         7   *
         8   *   - Redistributions of source code must retain the above copyright
         9   *     notice, this list of conditions and the following disclaimer.
        10   *
        11   *   - Redistributions in binary form must reproduce the above copyright
        12   *     notice, this list of conditions and the following disclaimer in
        13   *     the documentation and/or other materials provided with the
        14   *     distribution.
        15   *
        16   *   - Neither the name of Pebble nor the names of its contributors may
        17   *     be used to endorse or promote products derived from this software
        18   *     without specific prior written permission.
        19   *
        20   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
        21   * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
        22   * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
        23   * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
        24   * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
        25   * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
        26   * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
        27   * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
        28   * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
        29   * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
        30   * POSSIBILITY OF SUCH DAMAGE.
        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
             /*
        P/P   *  Method: void net.sourceforge.pebble.web.view.PdfView(BlogEntry, String)
              *
              *  Postconditions:
              *    this.entry == entry
              *    init'ed(this.entry)
              *    this.filename == filename
              *    init'ed(this.filename)
              *    this.length == 0
              */
        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   * Represents a binary view component and prepares the model for display.
        75   *
        76   * @author    Alexander Zagniotov
        77   */
        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
        94    public PdfView(BlogEntry entry, String filename) {
        95  	this.entry = entry;
        96      this.filename = filename;
        97    }
        98
        99    /**
       100     * Gets the title of this view.
       101     *
       102     * @return the title as a String
       103     */
               /*
        P/P     *  Method: String getContentType()
                *
                *  Postconditions:
                *    return_value == &"application.pdf"
                */
       104    public String getContentType() {
       105      return "application/pdf";
       106    }
       107
               /*
        P/P     *  Method: long getContentLength()
                *
                *  Preconditions:
                *    init'ed(this.length)
                *
                *  Postconditions:
                *    return_value == this.length
                *    init'ed(return_value)
                */
       108    public long getContentLength() {
       109      return length;
       110    }
       111
       112    /**
       113     * Dispatches this view.
       114     *
       115     * @param request  the HttpServletRequest instance
       116     * @param response the HttpServletResponse instance
       117     * @param context
       118     */
       119    public void dispatch(HttpServletRequest request, HttpServletResponse response, ServletContext context) throws ServletException {
       120
       121  			try {
            				 /*
        P/P 				  *  Method: void dispatch(HttpServletRequest, HttpServletResponse, ServletContext)
            				  *
            				  *  Preconditions:
            				  *    log != null
            				  *    (soft) init'ed(net.sourceforge.pebble.PebbleContext__static_init.new PebbleContext(PebbleContext__static_init#1).webApplicationRoot)
            				  *    (soft) net/sourceforge/pebble/web/listener/PebblePDFCreationListener.log != null
            				  *    (soft) response != null
            				  *    (soft) this.entry != null
            				  *    (soft) init'ed(this.filename)
            				  *
            				  *  Presumptions:
            				  *    files[0]@187 != null
            				  *    java.io.File:listFiles(...)@187 != null
            				  *    java.util.Iterator:next(...)@157 != null
            				  *    javax.xml.parsers.DocumentBuilder:parse(...)@234 != null
            				  *    javax.xml.parsers.DocumentBuilderFactory:newDocumentBuilder(...)@232 != null
            				  *    ...
            				  *
            				  *  Test Vectors:
            				  *    files.length@187: {0}, {1..+Inf}
            				  *    java.io.File:isDirectory(...)@186: {0}, {1}
            				  *    java.lang.String:equals(...)@158: {1}, {0}
            				  *    java.lang.String:equals(...)@206: {1}, {0}
            				  *    java.util.Iterator:hasNext(...)@156: {1}, {0}
            				  *    java.util.Iterator:hasNext(...)@160: {0}, {1}
            				  */
       122  				ITextRenderer renderer = new ITextRenderer();
       123
       124  				//This will be an attachment
       125  				response.setHeader("Content-Disposition", "attachment; filename=" + filename);
       126  				response.setHeader("Expires", "0");
       127  				response.setHeader("Cache-Control", "must-revalidate, post-check=0, pre-check=0");
       128  				response.setHeader("Pragma", "public");
       129
       130  				String author = entry.getUser().getName();
       131  				String title = entry.getTitle();
       132  				String subtitle = entry.getSubtitle();
       133  				String body = entry.getBody();
       134  				String blogName = entry.getBlog().getName();
       135  				String entryPermalink = entry.getPermalink();
       136  				String entryDescription = entry.getBlog().getDescription();
       137
       138  				//Some of the HTML entities need to be escaped to Unicode notation \\uXXXX for XHTML markup to validate
       139  				title = StringUtils.transformHTML(title);
       140  				subtitle = StringUtils.transformHTML(subtitle);
       141  				body = StringUtils.unescapeHTMLEntities(body);
       142
       143  				//Build absolute path to: <pebble_root>/themes/_pebble/fonts/
       144  				String webApplicationRoot = PebbleContext.getInstance().getWebApplicationRoot() + SEP + THEMES_PATH;
       145
       146  				//<pebble_root> + / + themes + / + _pebble + / + fonts
       147  				String fontDirAbsolutePath = webApplicationRoot + SEP + SYSTEM_THEME_PATH + SEP + FONTS_PATH;
       148  				File fontDir = new File(fontDirAbsolutePath);
       149
       150
       151  				//Get blog entry tags for PDF metadata 'keywords'
       152  				StringBuffer tags = new StringBuffer();
       153  				Iterator<Tag> currentEntryTags = entry.getAllTags().iterator();
       154
       155  				//Build a string out of blog entry tags and seperate them by comma
       156  				while (currentEntryTags.hasNext()) {
       157  					Tag currentTag = currentEntryTags.next();
       158  					if (currentTag.getName() != null && !currentTag.getName().equals("")) {
       159  						 tags.append(currentTag.getName());
       160  						 if (currentEntryTags.hasNext()) {
       161  							tags.append(",");
       162  						}
       163  					}
       164  				}
       165
       166  				//Build valid XHTML source from blog entry for parsing
       167  				StringBuffer buf = new StringBuffer();
       168  				buf.append("<html>");
       169  				buf.append("<head>");
       170  				buf.append("<meta name=\"title\" content=\"" + title + " - " + blogName + "\"/>");
       171  				buf.append("<meta name=\"subject\" content=\"" + title + "\"/>");
       172  				buf.append("<meta name=\"keywords\" content=\"" + tags.toString().trim() + "\"/>");
       173  				buf.append("<meta name=\"author\" content=\"" + author + "\"/>");
       174  				buf.append("<meta name=\"creator\" content=\"Pebble (by pebble.sourceforge.net)\"/>");
       175  				buf.append("<meta name=\"producer\" content=\"Flying Saucer (by xhtmlrenderer.dev.java.net)\"/>");
       176  				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  				buf.append("</head>");
       181  				buf.append("<body>");
       182  				buf.append("<div id=\"header\" style=\"\">" + blogName + " - " + entryDescription + "</div>");
       183  				buf.append("<p>");
       184
       185  				//Gets TTF or OTF font file from the font directory in the system theme folder
       186  				 if (fontDir.isDirectory()) {
       187  						File[] files = fontDir.listFiles(new FilenameFilter() {
       188  							public boolean accept(File dir, String name) {
            								 /*
        P/P 								  *  Method: bool accept(File, String)
            								  *
            								  *  Preconditions:
            								  *    name != null
            								  *
            								  *  Postconditions:
            								  *    init'ed(return_value)
            								  *
            								  *  Test Vectors:
            								  *    java.lang.String:endsWith(...)@192: {1}, {0}
            								  */
       189  								String lower = name.toLowerCase();
       190
       191  								//Load TTF or OTF files
       192  								return lower.endsWith(".otf") || lower.endsWith(".ttf");
       193  							}
       194  						});
       195
       196  						if (files.length > 0) {
    +  197  							String fontFamilyName = "";
       198  							//You should always embed TrueType fonts.
       199  							renderer.getFontResolver().addFont(files[0].getAbsolutePath(), BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
       200  							log.info("Added font: " + files[0].getAbsolutePath());
       201
       202  							//Get font family name from the BaseFont object. All this work just to get font family name
       203  							BaseFont font = BaseFont.createFont(files[0].getAbsolutePath(), BaseFont.IDENTITY_H , BaseFont.NOT_EMBEDDED);
       204  							fontFamilyName = TrueTypeUtil.getFamilyName(font);
       205
       206  							if (!fontFamilyName.equals("")) {
       207  								//Wrap DIV with font family name around the content of the blog entry
       208  								author = "<div style=\"font-family: " + fontFamilyName + ";\">" + author + "</div>";
       209  								title = "<div style=\"font-family: " + fontFamilyName + ";\">" + title + "</div>";
       210  								subtitle = "<div style=\"font-family: " + fontFamilyName + ";\">" + subtitle + "</div>";
       211  								body = "<div style=\"font-family: " + fontFamilyName + ";\">" + body + "</div>";
       212  								log.info("PDFGenerator - Added font family: '" + fontFamilyName + "' to PDF content");
       213  							}
       214  						}
       215  				 }
       216
       217  				buf.append("<h1>" + title  + "</h1>");
       218  				buf.append("<h2>" + subtitle + "</h2>");
       219  				buf.append("</p>");
       220  				buf.append("<p>" + body + "</p>");
       221  				buf.append("<p><br /><br /><br />");
       222  				buf.append("<i>Published by " + author + "</i><br />");
       223  				buf.append("<i>" + entry.getDate().toString() + "</i><br />");
       224  				buf.append("<i><a href=\"" + entryPermalink + "\" title=\"" + entryPermalink + "\">" + entryPermalink + "</a></i>");
       225  				buf.append("</p>");
       226  				buf.append("</body>");
       227  				buf.append("</html>");
       228
       229  				byte[] bytes = buf.toString().getBytes(DEFAULT_ENCODING);
       230
       231  				ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
       232  				DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
       233  				InputSource is = new InputSource(bais);
       234  				Document doc = builder.parse(is);
       235
       236  				//Listener that will parse HTML header meta tags, and will set them to PDF document as meta data
       237  				PebblePDFCreationListener pdfListener = new PebblePDFCreationListener();
       238  				pdfListener.parseMetaTags(doc);
       239  				renderer.setListener(pdfListener);
       240  				renderer.setDocument(doc, null);
       241  				renderer.layout();
       242
       243  				BufferedOutputStream bufferedOutput = new BufferedOutputStream(response.getOutputStream());
       244
       245  				renderer.createPDF(bufferedOutput);
       246  				bufferedOutput.flush();
       247  				bufferedOutput.close();
       248
       249  				log.info("Successfully generated PDF document: " + filename);
       250  			}
       251
       252  			catch (ParserConfigurationException e)  {
       253  				log.error("Could not create PDF, could not get new instance of DocumentBuilder: " + e);
       254  			}
       255
       256  			catch (SAXException e)  {
       257  				log.error("Could not create PDF, could not parse InputSource: " + e);
       258  			}
       259
       260  			catch (IOException e)  {
       261  				log.error("Could not create PDF: " + e);
       262  			}
       263
       264  			catch (DocumentException e)  {
       265  				log.error("iText could not create PDF document: " + e);
       266  			}
       267
       268  			catch (Exception e)  {
       269  				log.error("Could not create PDF: " + e);
       270  			}
       271  		}
       272  	}

SofCheck Inspector Build Version : 2.22510

pdfview.java | 2010-Jun-25 19:40:32
pdfview.class | 2010-Jul-19 20:23:38
pdfview$1.class | 2010-Jul-19 20:23:38