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