Package railo.commons.pdf

Source Code of railo.commons.pdf.PDFDocument

package railo.commons.pdf;

import java.awt.Dimension;
import java.awt.Insets;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.StringReader;
import java.net.MalformedURLException;
import java.net.URL;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

import railo.commons.io.CharsetUtil;
import railo.commons.io.IOUtil;
import railo.commons.io.SystemUtil;
import railo.commons.io.res.ContentType;
import railo.commons.io.res.Resource;
import railo.commons.io.res.util.ResourceUtil;
import railo.commons.lang.HTMLEntities;
import railo.commons.lang.StringUtil;
import railo.commons.net.HTTPUtil;
import railo.commons.net.http.HTTPEngine;
import railo.commons.net.http.HTTPResponse;
import railo.runtime.Info;
import railo.runtime.PageContext;
import railo.runtime.config.ConfigWeb;
import railo.runtime.exp.ExpressionException;
import railo.runtime.exp.PageException;
import railo.runtime.functions.system.ContractPath;
import railo.runtime.functions.system.GetDirectoryFromPath;
import railo.runtime.net.http.ReqRspUtil;
import railo.runtime.net.proxy.ProxyData;
import railo.runtime.net.proxy.ProxyDataImpl;
import railo.runtime.op.Caster;
import railo.runtime.text.xml.XMLCaster;
import railo.runtime.text.xml.XMLUtil;
import railo.runtime.type.scope.CGIImpl;
import railo.runtime.type.util.ListUtil;
import railo.runtime.util.URLResolver;

public final class PDFDocument {

  // PageType
    public static final Dimension PAGETYPE_ISOB5 = new Dimension(501, 709);
    public static final Dimension PAGETYPE_ISOB4 = new Dimension(709, 1002);
    public static final Dimension PAGETYPE_ISOB3 = new Dimension(1002, 1418);
    public static final Dimension PAGETYPE_ISOB2 = new Dimension(1418, 2004);
    public static final Dimension PAGETYPE_ISOB1 = new Dimension(2004, 2836);
    public static final Dimension PAGETYPE_ISOB0 = new Dimension(2836, 4008);
    public static final Dimension PAGETYPE_HALFLETTER = new Dimension(396, 612);
    public static final Dimension PAGETYPE_LETTER = new Dimension(612, 792);
    public static final Dimension PAGETYPE_TABLOID = new Dimension(792, 1224);
    public static final Dimension PAGETYPE_LEDGER = new Dimension(1224, 792);
    public static final Dimension PAGETYPE_NOTE = new Dimension(540, 720);
    public static final Dimension PAGETYPE_LEGAL = new Dimension(612, 1008);
 
    public static final Dimension PAGETYPE_A10 = new Dimension(74, 105);
    public static final Dimension PAGETYPE_A9 = new Dimension(105, 148);
    public static final Dimension PAGETYPE_A8 = new Dimension(148, 210);
    public static final Dimension PAGETYPE_A7 = new Dimension(210, 297);
    public static final Dimension PAGETYPE_A6 = new Dimension(297, 421);
    public static final Dimension PAGETYPE_A5 = new Dimension(421, 595);
    public static final Dimension PAGETYPE_A4 = new Dimension(595, 842);
    public static final Dimension PAGETYPE_A3 = new Dimension(842, 1190);
    public static final Dimension PAGETYPE_A2 = new Dimension(1190, 1684);
    public static final Dimension PAGETYPE_A1 = new Dimension(1684, 2384);
    public static final Dimension PAGETYPE_A0 = new Dimension(2384, 3370);
 
 
  public static final Dimension PAGETYPE_B4=new Dimension(708,1000);
  public static final Dimension PAGETYPE_B5=new Dimension(499,708);
  public static final Dimension PAGETYPE_B4_JIS=new Dimension(728,1031);
  public static final Dimension PAGETYPE_B5_JIS=new Dimension(516,728);
  public static final Dimension PAGETYPE_CUSTOM=new Dimension(1,1);
     
  // encryption
  public static final int ENC_NONE=0;
  public static final int ENC_40BIT=1;
  public static final int ENC_128BIT=2;
 
  //  fontembed
  public static final int FONT_EMBED_NO=0;
  public static final int FONT_EMBED_YES=1;
  public static final int FONT_EMBED_SELECCTIVE=FONT_EMBED_YES;

  // unit
  public static final double UNIT_FACTOR_CM=85d/3d;// =28.333333333333333333333333333333333333333333;
  public static final double UNIT_FACTOR_IN=UNIT_FACTOR_CM*2.54;
  public static final double UNIT_FACTOR_POINT=1;
   
  // margin init
  private static final int MARGIN_INIT=36;

  // mimetype
  private static final int MIMETYPE_TEXT_HTML = 0;
  private static final int MIMETYPE_TEXT = 1;
  private static final int MIMETYPE_IMAGE = 2
  private static final int MIMETYPE_APPLICATION = 3;
  private static final int MIMETYPE_OTHER = -1;
  private static final String USER_AGENT = "Railo "+Info.getVersionAsString()+" "+Info.getStateAsString();
 
   
  private double margintop=-1;
  private double marginbottom=-1;
  private double marginleft=-1;
  private double marginright=-1;

  private int mimetype=MIMETYPE_TEXT_HTML;
  private String strMimetype=null;
  private String strCharset=null;

  private boolean backgroundvisible;
  private boolean fontembed=true;
  private PDFPageMark header;
  private PDFPageMark footer;
 
  private String proxyserver;
  private int proxyport=80;
  private String proxyuser=null;
  private String proxypassword="";

  private String src=null;
  private Resource srcfile=null;
  private String body;
  //private boolean isEvaluation;
  private String name;
  private String authUser;
  private String authPassword;
  private String userAgent=USER_AGENT;
  private boolean localUrl;
  private boolean bookmark;
  private boolean htmlBookmark;
 
 
 
  public PDFDocument(){
    //this.isEvaluation=isEvaluation;
     
  }


  public void setHeader(PDFPageMark header) {
    this.header=header;
  }

  public void setFooter(PDFPageMark footer) {
    this.footer=footer;
  }
 

  /**
   * @param marginbottom the marginbottom to set
   */
  public void setMarginbottom(double marginbottom) {
    this.marginbottom = marginbottom;
  }

  /**
   * @param marginleft the marginleft to set
   */
  public void setMarginleft(double marginleft) {
    this.marginleft = marginleft;
  }

  /**
   * @param marginright the marginright to set
   */
  public void setMarginright(double marginright) {
    this.marginright = marginright;
  }

  /**
   * @param margintop the margintop to set
   */
  public void setMargintop(double margintop) {
    this.margintop = margintop;
  }
 
  /**
   * @param strMimetype the mimetype to set
   */
  public void setMimetype(String strMimetype) {
    strMimetype = strMimetype.toLowerCase().trim();
    this.strMimetype=strMimetype;
    // mimetype
    if(strMimetype.startsWith("text/html"))      mimetype=MIMETYPE_TEXT_HTML;
    else if(strMimetype.startsWith("text/"))    mimetype=MIMETYPE_TEXT;
    else if(strMimetype.startsWith("image/"))    mimetype=MIMETYPE_IMAGE;
    else if(strMimetype.startsWith("application/"))    mimetype=MIMETYPE_APPLICATION;
    else mimetype=MIMETYPE_OTHER;
   
    // charset
    String[] arr = ListUtil.listToStringArray(strMimetype, ';');
    if(arr.length>=2) {
      this.strMimetype=arr[0].trim();
      for(int i=1;i<arr.length;i++) {
        String[] item = ListUtil.listToStringArray(arr[i], '=');
        if(item.length==1) {
          strCharset=item[0].trim();
          break;
        }
        else if(item.length==2 && item[0].trim().equals("charset")) {
          strCharset=item[1].trim();
          break;
        }
      }
    }
  }
 
  /** set the value proxyserver
  *  Host name or IP address of a proxy server.
  * @param proxyserver value to set
  **/
  public void setProxyserver(String proxyserver)  {
    this.proxyserver=proxyserver;
  }
 
  /** set the value proxyport
  *  The port number on the proxy server from which the object is requested. Default is 80. When
  *   used with resolveURL, the URLs of retrieved documents that specify a port number are automatically
  *   resolved to preserve links in the retrieved document.
  * @param proxyport value to set
  **/
  public void setProxyport(int proxyport)  {
    this.proxyport=proxyport;
  }

  /** set the value username
  *  When required by a proxy server, a valid username.
  * @param proxyuser value to set
  **/
  public void setProxyuser(String proxyuser)  {
    this.proxyuser=proxyuser;
  }

  /** set the value password
  *  When required by a proxy server, a valid password.
  * @param proxypassword value to set
  **/
  public void setProxypassword(String proxypassword)  {
    this.proxypassword=proxypassword;
  }

  /**
   * @param src
   * @throws PDFException
   */
  public void setSrc(String src) throws PDFException {
    if(srcfile!=null) throw new PDFException("You cannot specify both the src and srcfile attributes");
    this.src = src;
  }
 

  /**
   * @param srcfile the srcfile to set
   * @throws PDFException
   */
  public void setSrcfile(Resource srcfile) throws PDFException {
    if(src!=null) throw new PDFException("You cannot specify both the src and srcfile attributes");
    this.srcfile=srcfile;
  }

  public void setBody(String body) {
    this.body=body;
  }

  public byte[] render(Dimension dimension,double unitFactor, PageContext pc,boolean generateOutlines) throws PageException, IOException {
    ConfigWeb config = pc.getConfig();
    PDF pd4ml = new PDF(config);
    pd4ml.generateOutlines(generateOutlines);
    pd4ml.enableTableBreaks(true);
    pd4ml.interpolateImages(true);
    // MUSTMUST DO NOT ENABLE, why this was disabled
    pd4ml.adjustHtmlWidth();
   
    //check size
    int mTop =   toPoint(margintop,unitFactor);
    int mLeft = toPoint(marginleft,unitFactor);
    int mBottom=toPoint(marginbottom,unitFactor);
    int mRight=toPoint(marginright,unitFactor);
    if((mLeft+mRight)>dimension.getWidth())
      throw new ExpressionException("current document width ("+Caster.toString(dimension.getWidth())+" point) is smaller that specified horizontal margin  ("+Caster.toString(mLeft+mRight)+" point).",
          "1 in = "+Math.round(1*UNIT_FACTOR_IN)+" point and 1 cm = "+Math.round(1*UNIT_FACTOR_CM)+" point");
    if((mTop+mBottom)>dimension.getHeight())
      throw new ExpressionException("current document height ("+Caster.toString(dimension.getHeight())+" point) is smaller that specified vertical margin  ("+Caster.toString(mTop+mBottom)+" point).",
          "1 in = "+Math.round(1*UNIT_FACTOR_IN)+" point and 1 cm = "+Math.round(1*UNIT_FACTOR_CM)+" point");
   
    // Size
    pd4ml.setPageInsets(new Insets(mTop,mLeft,mBottom,mRight));
    pd4ml.setPageSize(dimension);
   
    // header
    if(header!=null) pd4ml.setPageHeader(header);
    // footer
    if(footer!=null) pd4ml.setPageFooter(footer);
   
    // content
    ByteArrayOutputStream baos=new ByteArrayOutputStream();
    try {
      content(pd4ml,pc,baos);
     
    }
    finally {
      IOUtil.closeEL(baos);
    }
    return baos.toByteArray();
  }

  private void content(PDF pd4ml, PageContext pc, OutputStream os) throws PageException, IOException {
    ConfigWeb config = pc.getConfig();
    pd4ml.useTTF("java:fonts", fontembed);
   
    // body
      if(!StringUtil.isEmpty(body,true)) {
        // optimize html
        URL base = getBase(pc);
        try {
          body=beautifyHTML(new InputSource(new StringReader(body)),base);
      }catch (Throwable t) {}
     
        pd4ml.render(body, os,base);
     
      }
      // srcfile
      else if(srcfile!=null) {
        if(StringUtil.isEmpty(strCharset))strCharset=pc.getConfig().getResourceCharset();
       
      // mimetype
      if(StringUtil.isEmpty(strMimetype)) {
        String mt = ResourceUtil.getMimeType(srcfile,null);
        if(mt!=null) setMimetype(mt);
      }
      InputStream is = srcfile.getInputStream();
        try {
         
          URL base = new URL("file://"+srcfile);
          if(!localUrl){
            //PageContext pc = Thread LocalPageContext.get();
           
              String abs = srcfile.getAbsolutePath();
              String contract = ContractPath.call(pc, abs);
              if(!abs.equals(contract)) {
                base=HTTPUtil.toURL(CGIImpl.getDomain(pc.getHttpServletRequest())+contract,true);
              }

          }
         
          //URL base = localUrl?new URL("file://"+srcfile):getBase();
          render(pd4ml, is,os,base);
      }
        catch (Throwable t) {}
        finally {
          IOUtil.closeEL(is);
        }
      }
      // src
      else if(src!=null) {
        if(StringUtil.isEmpty(strCharset))strCharset="iso-8859-1";
        URL url = HTTPUtil.toURL(src,true);
     
      // set Proxy
      if(StringUtil.isEmpty(proxyserver) && config.isProxyEnableFor(url.getHost())) {
        ProxyData pd = config.getProxyData();
        proxyserver=pd==null?null:pd.getServer();
        proxyport=pd==null?0:pd.getPort();
        proxyuser=pd==null?null:pd.getUsername();
        proxypassword=pd==null?null:pd.getPassword();
      }
     
      HTTPResponse method = HTTPEngine.get(url, authUser, authPassword, -1,HTTPEngine.MAX_REDIRECT, null, userAgent,
          ProxyDataImpl.getInstance(proxyserver, proxyport, proxyuser, proxypassword),null);
     
      // mimetype
      if(StringUtil.isEmpty(strMimetype)) {
        ContentType ct = method.getContentType();
        if(ct!=null)
          setMimetype(ct.toString());
       
      }
      InputStream is = new ByteArrayInputStream(method.getContentAsByteArray());
      try {
       
        render(pd4ml, is, os,url);
      }
      finally {
        IOUtil.closeEL(is);
      }
      }
      else {
        pd4ml.render("<html><body> </body></html>", os,null);
      }
  }

  private static String beautifyHTML(InputSource is,URL base) throws ExpressionException, SAXException, IOException {
    Document xml = XMLUtil.parse(is,null,true);
    patchPD4MLProblems(xml);
   
    if(base!=null)URLResolver.getInstance().transform(xml, base);
    String html = XMLCaster.toHTML(xml);
    return html;
  }

  private static void patchPD4MLProblems(Document xml) {
    Element b = XMLUtil.getChildWithName("body", xml.getDocumentElement());
    if(!b.hasChildNodes()){
      b.appendChild(xml.createTextNode(" "));
    }
  }


  private static URL getBase(PageContext pc) throws MalformedURLException {
    //PageContext pc = Thread LocalPageContext.get();
    if(pc==null)return null;
   
    String userAgent = pc.getHttpServletRequest().getHeader("User-Agent");
    // bug in pd4ml-> html badse definition create a call
    if(!StringUtil.isEmpty(userAgent) && userAgent.startsWith("Java"))return null;
   
    return HTTPUtil.toURL(GetDirectoryFromPath.call(pc, ReqRspUtil.getRequestURL(pc.getHttpServletRequest(), false)),true);
  }


  private void render(PDF pd4ml, InputStream is,OutputStream os, URL base) throws IOException, PageException {
    try {
     
      // text/html
      if(mimetype==MIMETYPE_TEXT_HTML) {
        body="";
       
        try {
          InputSource input = new InputSource(IOUtil.getReader(is,CharsetUtil.toCharset(strCharset)));
          body=beautifyHTML(input,base);
        }
        catch (Throwable t) {}
        //else if(body==null)body =IOUtil.toString(is,strCharset);
        pd4ml.render(body, os,base);
      }
      // text
      else if(mimetype==MIMETYPE_TEXT) {
        body =IOUtil.toString(is,strCharset);
        body="<html><body><pre>"+HTMLEntities.escapeHTML(body)+"</pre></body></html>";
        pd4ml.render(body, os,null);
      }
      // image
      else if(mimetype==MIMETYPE_IMAGE) {
        Resource tmpDir= SystemUtil.getTempDirectory();
        Resource tmp = tmpDir.getRealResource(this+"-"+Math.random());
        IOUtil.copy(is, tmp,true);
        body="<html><body><img src=\"file://"+tmp+"\"></body></html>";
        try {
          pd4ml.render(body, os,null);
        }
        finally {
          tmp.delete();
       
      }
      // Application
      else if(mimetype==MIMETYPE_APPLICATION && "application/pdf".equals(strMimetype)) {
        IOUtil.copy(is, os,true,true);
      }
      else pd4ml.render(new InputStreamReader(is), os);
    }
    finally {
      IOUtil.closeEL(is,os);
    }
  }

  public static int toPoint(double value,double unitFactor) {
    if(value<0) return MARGIN_INIT;
    return (int)Math.round(value*unitFactor);
    //return r;
  }

  public PDFPageMark getHeader() {
    return header;
  }
  public PDFPageMark getFooter() {
    return footer;
  }

  public void setFontembed(int fontembed) {
    this.fontembed=fontembed!=FONT_EMBED_NO;
  }


  /**
   * @return the name
   */
  public String getName() {
    return name;
  }


  /**
   * @param name the name to set
   */
  public void setName(String name) {
    this.name = name;
  }


  /**
   * @return the authUser
   */
  public String getAuthUser() {
    return authUser;
  }


  /**
   * @param authUser the authUser to set
   */
  public void setAuthUser(String authUser) {
    this.authUser = authUser;
  }


  /**
   * @return the authPassword
   */
  public String getAuthPassword() {
    return authPassword;
  }


  /**
   * @param authPassword the authPassword to set
   */
  public void setAuthPassword(String authPassword) {
    this.authPassword = authPassword;
  }


  /**
   * @return the userAgent
   */
  public String getUserAgent() {
    return userAgent;
  }


  /**
   * @param userAgent the userAgent to set
   */
  public void setUserAgent(String userAgent) {
    this.userAgent = userAgent;
  }


  /**
   * @return the proxyserver
   */
  public String getProxyserver() {
    return proxyserver;
  }


  /**
   * @return the proxyport
   */
  public int getProxyport() {
    return proxyport;
  }


  /**
   * @return the proxyuser
   */
  public String getProxyuser() {
    return proxyuser;
  }


  /**
   * @return the proxypassword
   */
  public String getProxypassword() {
    return proxypassword;
  }


  public boolean hasProxy() {
    return !StringUtil.isEmpty(proxyserver);
  }


  /**
   * @return the localUrl
   */
  public boolean getLocalUrl() {
    return localUrl;
  }


  /**
   * @param localUrl the localUrl to set
   */
  public void setLocalUrl(boolean localUrl) {
    this.localUrl = localUrl;
  }


  /**
   * @return the bookmark
   */
  public boolean getBookmark() {
    return bookmark;
  }


  /**
   * @param bookmark the bookmark to set
   */
  public void setBookmark(boolean bookmark) {
    this.bookmark = bookmark;
  }


  /**
   * @return the htmlBookmark
   */
  public boolean getHtmlBookmark() {
    return htmlBookmark;
  }


  /**
   * @param htmlBookmark the htmlBookmark to set
   */
  public void setHtmlBookmark(boolean htmlBookmark) {
    this.htmlBookmark = htmlBookmark;
  }

}
TOP

Related Classes of railo.commons.pdf.PDFDocument

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.