001    package railo.runtime.tag;
002    
003    
004    import java.awt.Dimension;
005    import java.io.ByteArrayInputStream;
006    import java.io.ByteArrayOutputStream;
007    import java.io.IOException;
008    import java.io.OutputStream;
009    import java.util.ArrayList;
010    import java.util.Iterator;
011    import java.util.Map;
012    
013    import javax.servlet.http.HttpServletResponse;
014    import javax.servlet.jsp.JspException;
015    
016    import railo.commons.io.IOUtil;
017    import railo.commons.io.res.Resource;
018    import railo.commons.io.res.util.ResourceUtil;
019    import railo.commons.lang.StringUtil;
020    import railo.commons.pdf.PDFDocument;
021    import railo.commons.pdf.PDFException;
022    import railo.commons.pdf.PDFPageMark;
023    import railo.runtime.Info;
024    import railo.runtime.PageContextImpl;
025    import railo.runtime.exp.ApplicationException;
026    import railo.runtime.exp.PageException;
027    import railo.runtime.exp.TemplateException;
028    import railo.runtime.ext.tag.BodyTagImpl;
029    import railo.runtime.op.Caster;
030    import railo.runtime.text.pdf.PDFUtil;
031    import railo.runtime.type.ReadOnlyStruct;
032    
033    import com.lowagie.text.DocumentException;
034    import com.lowagie.text.pdf.PdfCopy;
035    import com.lowagie.text.pdf.PdfImportedPage;
036    import com.lowagie.text.pdf.PdfReader;
037    import com.lowagie.text.pdf.SimpleBookmark;
038    
039    public final class Document extends BodyTagImpl {
040    
041            
042            //private static final String STYLE_BG_INVISIBLE = "background-color: transparent; background-image: none;";
043            
044    
045            
046            private Resource filename=null;
047            private boolean overwrite=false;
048            private String name=null;
049            private Dimension pagetype=PDFDocument.PAGETYPE_LETTER;
050            private double pageheight=0;
051            private double pagewidth=0;
052            private boolean isLandscape=false;
053    
054            
055            private double unitFactor=PDFDocument.UNIT_FACTOR_IN;
056            private int encryption=PDFDocument.ENC_NONE;
057    
058            private String ownerpassword=null;
059            private String userpassword="empty";
060            private int scale=-1;
061    
062            // TODO impl. tag Document backgroundvisible,fontembed,scale
063            private boolean backgroundvisible;
064            private int fontembed=PDFDocument.FONT_EMBED_YES;
065            
066            private int permissions=0;
067            private PDFDocument _document;
068    
069    
070    
071            private ArrayList<PDFDocument> documents=new ArrayList<PDFDocument>(); 
072            
073            public Document() {
074                    this._document=null;
075            }
076            
077            @Override
078            public void release() {
079                    super.release();
080                    filename=null;
081                    overwrite=false;
082                    name=null;
083                    pagetype=PDFDocument.PAGETYPE_LETTER;
084                    pageheight=0;
085                    pagewidth=0;
086                    isLandscape=false;
087                    unitFactor=PDFDocument.UNIT_FACTOR_IN;
088                    encryption=PDFDocument.ENC_NONE;
089                    ownerpassword=null;
090                    userpassword="empty";
091                    permissions=0;
092                    scale=-1;
093                    documents.clear();
094                    _document=null;
095                    backgroundvisible=false;
096                    fontembed=PDFDocument.FONT_EMBED_YES;
097    
098                    
099                    
100            }
101            
102            private PDFDocument getDocument() {
103                    //SerialNumber sn = pageContext.getConfig().getSerialNumber();
104                    if(_document==null){
105                            _document=new PDFDocument();
106                    }
107                    return _document;
108            }
109            
110            
111    
112            /** set the value proxyserver
113            *  Host name or IP address of a proxy server.
114            * @param proxyserver value to set
115            **/
116            public void setProxyserver(String proxyserver)  {
117                    getDocument().setProxyserver(proxyserver);
118            }
119            public void setProxyhost(String proxyserver)    {
120                    getDocument().setProxyserver(proxyserver);
121            }
122            
123            /** set the value proxyport
124            *  The port number on the proxy server from which the object is requested. Default is 80. When 
125            *       used with resolveURL, the URLs of retrieved documents that specify a port number are automatically 
126            *       resolved to preserve links in the retrieved document.
127            * @param proxyport value to set
128            **/
129            public void setProxyport(double proxyport)      {
130                    getDocument().setProxyport((int)proxyport);
131            }
132    
133            /** set the value username
134            *  When required by a proxy server, a valid username.
135            * @param proxyuser value to set
136            **/
137            public void setProxyuser(String proxyuser)      {
138                    getDocument().setProxyuser(proxyuser);
139            }
140    
141            /** set the value password
142            *  When required by a proxy server, a valid password.
143            * @param proxypassword value to set
144            **/
145            public void setProxypassword(String proxypassword)      {
146                    getDocument().setProxypassword(proxypassword);
147            }
148    
149            public void setSaveasname(String saveAsName) {
150                    // TODO impl
151            }
152            
153            /**
154             * @param authUser the authUser to set
155             */
156            public void setAuthuser(String authUser) {
157                    getDocument().setAuthUser(authUser);
158            }
159    
160            /**
161             * @param authPassword the authPassword to set
162             */
163            public void setAuthpassword(String authPassword) {
164                    getDocument().setAuthPassword(authPassword);
165            }
166    
167            /**
168             * @param userAgent the userAgent to set
169             */
170            public void setUseragent(String userAgent) {
171                    getDocument().setUserAgent(userAgent);
172            }
173            
174            /**
175             * @param format the format to set
176             * @throws ApplicationException 
177             */
178            public void setFormat(String format) throws ApplicationException {
179                    format = StringUtil.toLowerCase(format.trim());
180                    if(!"pdf".equals(format))
181                            throw new ApplicationException("invalid format ["+format+"], only the following format is supported [pdf]");
182            }
183    
184            /**
185             * @param filename the filename to set
186             * @throws PageException 
187             */
188            public void setFilename(String filename) throws PageException {
189                    this.filename = ResourceUtil.toResourceNotExisting(pageContext, filename);
190                    pageContext.getConfig().getSecurityManager().checkFileLocation(this.filename);
191            }
192    
193            /**
194             * @param overwrite the overwrite to set
195             */
196            public void setOverwrite(boolean overwrite) {
197                    this.overwrite = overwrite;
198            }
199    
200            /**
201             * @param name the name to set
202             */
203            public void setName(String name) {
204                    this.name = name;
205            }
206    
207            /**
208             * @param pagetype the pagetype to set
209             * @throws ApplicationException 
210             */
211            public void setPagetype(String strPagetype) throws ApplicationException {
212                    strPagetype=StringUtil.toLowerCase(strPagetype.trim());
213                    if("legal".equals(strPagetype))                 pagetype=PDFDocument.PAGETYPE_LEGAL;
214                    else if("letter".equals(strPagetype))   pagetype=PDFDocument.PAGETYPE_LETTER;
215                    else if("a4".equals(strPagetype))               pagetype=PDFDocument.PAGETYPE_A4;
216                    else if("a5".equals(strPagetype))               pagetype=PDFDocument.PAGETYPE_A5;
217                    else if("b4".equals(strPagetype))               pagetype=PDFDocument.PAGETYPE_B4;
218                    else if("b5".equals(strPagetype))               pagetype=PDFDocument.PAGETYPE_B5;
219                    else if("b4-jis".equals(strPagetype))   pagetype=PDFDocument.PAGETYPE_B4_JIS;
220                    else if("b4 jis".equals(strPagetype))   pagetype=PDFDocument.PAGETYPE_B4_JIS;
221                    else if("b4_jis".equals(strPagetype))   pagetype=PDFDocument.PAGETYPE_B4_JIS;
222                    else if("b4jis".equals(strPagetype))    pagetype=PDFDocument.PAGETYPE_B4_JIS;
223                    else if("b5-jis".equals(strPagetype))   pagetype=PDFDocument.PAGETYPE_B5_JIS;
224                    else if("b5 jis".equals(strPagetype))   pagetype=PDFDocument.PAGETYPE_B5_JIS;
225                    else if("b5_jis".equals(strPagetype))   pagetype=PDFDocument.PAGETYPE_B5_JIS;
226                    else if("b5jis".equals(strPagetype))    pagetype=PDFDocument.PAGETYPE_B5_JIS;
227                    else if("custom".equals(strPagetype))   pagetype=PDFDocument.PAGETYPE_CUSTOM;
228                    else throw new ApplicationException("invalid page type ["+strPagetype+"], valid page types are [legal,letter,a4,a5,b4,b5,b4-jis,b5-jis,custom]");
229                    
230                    
231            }
232    
233            /**
234             * @param pageheight the pageheight to set
235             * @throws ApplicationException 
236             */
237            public void setPageheight(double pageheight) throws ApplicationException {
238                    if(pageheight<1) throw new ApplicationException("pageheight must be a positive number");
239                    this.pageheight = pageheight;
240            }
241    
242            /**
243             * @param pagewidth the pagewidth to set
244             * @throws ApplicationException 
245             */
246            public void setPagewidth(double pagewidth) throws ApplicationException {
247                    if(pagewidth<1) throw new ApplicationException("pagewidth must be a positive number");
248                    this.pagewidth = pagewidth;
249            }
250    
251            /**
252             * @param orientation the orientation to set
253             * @throws ApplicationException 
254             */
255            public void setOrientation(String strOrientation) throws ApplicationException {
256                    strOrientation=StringUtil.toLowerCase(strOrientation.trim());
257                    if("portrait".equals(strOrientation))           isLandscape=false;
258                    else if("landscape".equals(strOrientation))     isLandscape=true;
259                    else throw new ApplicationException("invalid orientation ["+strOrientation+"], valid orientations are [portrait,landscape]");
260                    
261            }
262    
263            /**
264             * @param marginbottom the marginbottom to set
265             */
266            public void setMarginbottom(double marginbottom) {
267                    getDocument().setMarginbottom(marginbottom);
268            }
269    
270            /**
271             * @param marginleft the marginleft to set
272             */
273            public void setMarginleft(double marginleft) {
274                    getDocument().setMarginleft(marginleft);
275            }
276    
277            /**
278             * @param marginright the marginright to set
279             */
280            public void setMarginright(double marginright) {
281                    getDocument().setMarginright(marginright);
282            }
283    
284            /**
285             * @param margintop the margintop to set
286             */
287            public void setMargintop(double margintop) {
288                    getDocument().setMargintop(margintop);
289            }
290    
291            /**
292             * @param bookmark the bookmark to set
293             */
294            public void setBookmark(boolean bookmark) {
295                    getDocument().setBookmark(bookmark);
296            }
297    
298            public void setHtmlbookmark(boolean bookmark) {
299                    getDocument().setHtmlBookmark(bookmark);
300            }
301    
302            /**
303             * @param localUrl the localUrl to set
304             */
305            public void setLocalurl(boolean localUrl) {
306                    getDocument().setLocalUrl(localUrl);
307            }
308    
309            /**
310             * @param unitFactor the unit to set
311             * @throws ApplicationException 
312             */
313            public void setUnit(String strUnit) throws ApplicationException {
314                    strUnit=StringUtil.toLowerCase(strUnit.trim());
315                    if("in".equals(strUnit))                unitFactor=PDFDocument.UNIT_FACTOR_IN;
316                    else if("cm".equals(strUnit))   unitFactor=PDFDocument.UNIT_FACTOR_CM;
317                    else if("point".equals(strUnit))        unitFactor=PDFDocument.UNIT_FACTOR_POINT;
318                    else throw new ApplicationException("invalid unit ["+strUnit+"], valid units are [cm,in,point]");
319            }
320    
321            /**
322             * @param encryption the encryption to set
323             * @throws ApplicationException 
324             */
325            public void setEncryption(String strEncryption) throws ApplicationException {
326                    strEncryption=StringUtil.toLowerCase(strEncryption.trim());
327                    if("none".equals(strEncryption))                        encryption=PDFDocument.ENC_NONE;
328                    else if("40-bit".equals(strEncryption))         encryption=PDFDocument.ENC_40BIT;
329                    else if("40bit".equals(strEncryption))          encryption=PDFDocument.ENC_40BIT;
330                    else if("40 bit".equals(strEncryption))         encryption=PDFDocument.ENC_40BIT;
331                    else if("40_bit".equals(strEncryption))         encryption=PDFDocument.ENC_40BIT;
332                    else if("128-bit".equals(strEncryption))        encryption=PDFDocument.ENC_128BIT;
333                    else if("128bit".equals(strEncryption))         encryption=PDFDocument.ENC_128BIT;
334                    else if("128 bit".equals(strEncryption))        encryption=PDFDocument.ENC_128BIT;
335                    else if("128_bit".equals(strEncryption))        encryption=PDFDocument.ENC_128BIT;
336                    else throw new ApplicationException("invalid encryption ["+strEncryption+"], valid encryption values are [none, 40-bit, 128-bit]");
337            }
338    
339            /**
340             * @param ownerpassword the ownerpassword to set
341             * @throws ApplicationException 
342             */
343            public void setOwnerpassword(String ownerpassword) {
344                    this.ownerpassword = ownerpassword;
345            }
346    
347            /**
348             * @param userpassword the userpassword to set
349             */
350            public void setUserpassword(String userpassword) {
351                    this.userpassword = userpassword;
352            }
353    
354            /**
355             * @param permissions the permissions to set
356             * @throws PageException 
357             */
358            public void setPermissions(String strPermissions) throws PageException {
359                    permissions=PDFUtil.toPermissions(strPermissions);
360            }
361    
362            /**
363             * @param scale the scale to set
364             * @throws ApplicationException 
365             */
366            public void setScale(double scale) throws ApplicationException {
367                    if(scale<0) throw new ApplicationException("scale must be a positive number");
368                    if(scale>100) throw new ApplicationException("scale must be a number less or equal than 100");
369                    this.scale = (int) scale;
370            }
371    
372            /**
373             * @param src the src to set
374             * @throws ApplicationException 
375             */
376            public void setSrc(String src) throws ApplicationException {
377                    try {
378                            getDocument().setSrc(src);
379                    } catch (PDFException e) {
380                            throw new ApplicationException(e.getMessage());
381                    }
382            }
383    
384            /**
385             * @param srcfile the srcfile to set
386             * @throws PageException 
387             * @throws  
388             */
389            public void setSrcfile(String strSrcfile) throws PageException {
390                    Resource srcfile = ResourceUtil.toResourceExisting(pageContext, strSrcfile);
391                    pageContext.getConfig().getSecurityManager().checkFileLocation(srcfile);
392                    try {
393                            getDocument().setSrcfile(srcfile);
394                    } catch (PDFException e) {
395                            throw new ApplicationException(e.getMessage());
396                    }
397            }
398    
399            /**
400             * @param mimetype the mimetype to set
401             */
402            public void setMimetype(String strMimetype) {
403                    getDocument().setMimetype(strMimetype);
404                    strMimetype = strMimetype.toLowerCase().trim();
405            }
406            
407    
408            public void setHeader(PDFPageMark header) {
409                    getDocument().setHeader(header);
410            }
411    
412            public void setFooter(PDFPageMark footer) {
413                    getDocument().setFooter(footer);
414            }
415            
416    
417            public void setBackgroundvisible(boolean backgroundvisible) {
418                    this.backgroundvisible=backgroundvisible;
419            }
420    
421            public void setFontembed(String fontembed) throws PDFException {
422                    Boolean fe=Caster.toBoolean(fontembed,null);
423                    if(fe==null) {
424                            fontembed=StringUtil.toLowerCase(fontembed.trim());
425                            if("selective".equals(fontembed))
426                                    this.fontembed=PDFDocument.FONT_EMBED_SELECCTIVE;
427                            else throw new PDFException("invalid value for fontembed ["+fontembed+"], valid values for fontembed are [yes,no,selective]");
428                            
429                    }
430                    else if(fe.booleanValue())this.fontembed=PDFDocument.FONT_EMBED_YES;
431                    else this.fontembed=PDFDocument.FONT_EMBED_NO;
432                    getDocument().setFontembed(this.fontembed);
433            }
434    
435            public void addPDFDocument(PDFDocument document) {
436                    // set proxy settings
437                    if(_document!=null)     {
438                            if(_document.hasProxy()) {
439                                    document.setProxyserver(_document.getProxyserver());
440                                    document.setProxyport(_document.getProxyport());
441                                    document.setProxyuser(_document.getProxyuser());
442                                    document.setProxypassword(_document.getProxypassword());
443                            }
444                            document.setBookmark(_document.getBookmark());
445                            document.setLocalUrl(_document.getLocalUrl());
446                    }
447                    
448                    
449                    documents.add(document);
450            }
451    
452        @Override
453            public int doStartTag() throws PageException    {
454                    // SerialNumber sn = pageContext.getConfig().getSerialNumber();
455                //if(sn.getVersion()==SerialNumber.VERSION_COMMUNITY)
456                //    throw new SecurityException("no access to this functionality with the "+sn.getStringVersion()+" version of railo");
457    
458                
459                ReadOnlyStruct cfdoc=new ReadOnlyStruct();
460                cfdoc.setEL("currentpagenumber", "{currentpagenumber}");
461                cfdoc.setEL("totalpagecount", "{totalpagecount}");
462                cfdoc.setEL("totalsectionpagecount", "{totalsectionpagecount}");
463                cfdoc.setEL("currentsectionpagenumber", "{currentsectionpagenumber}");
464                cfdoc.setReadOnly(true);
465                pageContext.variablesScope().setEL("cfdocument", cfdoc);
466    
467                return EVAL_BODY_BUFFERED;
468            }
469    
470            @Override
471            public void doInitBody()        {
472                    
473            }
474            
475            @Override
476            public int doAfterBody()        {
477                    getDocument().setBody(bodyContent.getString());
478                    
479                    return SKIP_BODY;
480            }
481            
482            @Override
483            public int doEndTag() throws PageException {
484                    try {
485                            _doEndTag();
486                    }
487                    catch (Exception e) {
488                            throw Caster.toPageException(e);
489                    }       
490                    return EVAL_PAGE;
491            }
492            
493            public void _doEndTag() throws JspException, IOException, DocumentException { 
494                    // set root header/footer to sections
495                    boolean doBookmarks=false;
496                    boolean doHtmlBookmarks=false;
497                    if(_document!=null){
498                            PDFPageMark header = _document.getHeader();
499                            PDFPageMark footer = _document.getFooter();
500                            boolean hasHeader=header!=null;
501                            boolean hasFooter=footer!=null;
502                            if(hasFooter || hasHeader) {
503                                    Iterator<PDFDocument> it = documents.iterator();
504                                    PDFDocument doc;
505                                    while(it.hasNext()){
506                                            doc=it.next();
507                                            if(hasHeader && doc.getHeader()==null) doc.setHeader(header);
508                                            if(hasFooter && doc.getFooter()==null) doc.setFooter(footer);
509                                    }
510                            }
511                            doBookmarks=_document.getBookmark();
512                            doHtmlBookmarks=_document.getHtmlBookmark();
513                    }
514                    
515                    
516                    if(filename!=null)  {
517                            if(filename.exists() && !overwrite)
518                            throw new ApplicationException("file ["+filename+"] already exist","to allow overwrite the resource, set attribute [overwrite] to [true]");
519                    
520                    OutputStream os= null;
521                    try {
522                            os= filename.getOutputStream();
523                                    render(os,doBookmarks,doHtmlBookmarks);
524                            } 
525                    finally {
526                                    IOUtil.closeEL(os);
527                            }
528                    
529                }
530                    else if(!StringUtil.isEmpty(name)) {
531                            render(null,doBookmarks,doHtmlBookmarks);
532                    }
533                else  {
534                    HttpServletResponse rsp = pageContext. getHttpServletResponse();
535                        if(rsp.isCommitted())
536                        throw new ApplicationException("content is already flushed","you can't rewrite head of response after part of the page is flushed");
537                    rsp.setContentType("application/pdf");
538                
539                    
540                    OutputStream os=getOutputStream();   
541                        try {
542                            render(os,doBookmarks,doHtmlBookmarks);
543                        } 
544                        finally {
545                            IOUtil.flushEL(os);
546                            IOUtil.closeEL(os);
547                            ((PageContextImpl)pageContext).getRootOut().setClosed(true);
548                        }
549                        throw new railo.runtime.exp.Abort(railo.runtime.exp.Abort.SCOPE_REQUEST);
550                }
551           
552            }
553    
554    
555    
556            private void render(OutputStream os, boolean doBookmarks, boolean doHtmlBookmarks) throws IOException, PageException, DocumentException {
557                    byte[] pdf=null;
558                    // merge multiple docs to 1
559                    if(documents.size()>1) {
560                            PDFDocument[] pdfDocs=new PDFDocument[documents.size()];
561                            PdfReader[] pdfReaders = new PdfReader[pdfDocs.length];
562                            Iterator<PDFDocument> it = documents.iterator();
563                            int index=0;
564                            // generate pdf with pd4ml
565                            while(it.hasNext()) {
566                                    pdfDocs[index]=it.next();
567                                    pdfReaders[index]=
568                                            new PdfReader(pdfDocs[index].render(getDimension(),unitFactor,pageContext,doHtmlBookmarks));
569                                    index++;
570                            }
571                            
572                            // collect together
573                            ByteArrayOutputStream baos = new ByteArrayOutputStream();
574                            com.lowagie.text.Document document = 
575                                    new com.lowagie.text.Document(pdfReaders[0].getPageSizeWithRotation(1));
576                            PdfCopy copy = new PdfCopy(document,baos);
577                            document.open();
578                            String name;
579                            ArrayList bookmarks=doBookmarks?new ArrayList():null;
580                            try {
581                                    int size,totalPage=0;
582                                    Map parent;
583                                    for(int doc=0;doc<pdfReaders.length;doc++) {
584                                            size=pdfReaders[doc].getNumberOfPages();
585                                            
586                                            PdfImportedPage ip;
587                                            
588                                            // bookmarks
589                                            if(doBookmarks) {
590                                                    name=pdfDocs[doc].getName();
591                                                    if(!StringUtil.isEmpty(name)) {
592                                                            bookmarks.add(parent=PDFUtil.generateGoToBookMark(name, totalPage+1));
593                                                    }
594                                                    else parent=null;
595                                                    
596                                                    if(doHtmlBookmarks) {
597                                                            java.util.List pageBM = SimpleBookmark.getBookmark(pdfReaders[doc]);
598                                                            if(pageBM!=null) {
599                                                                    if(totalPage>0)SimpleBookmark.shiftPageNumbers(pageBM, totalPage, null);
600                                                                    if(parent!=null)PDFUtil.setChildBookmarks(parent,pageBM);
601                                                                    else bookmarks.addAll(pageBM);
602                                                            }
603                                                    }
604                                            }
605                                            
606                                            totalPage++;
607                                            for(int page=1;page<=size;page++) {
608                                                    if(page>1)totalPage++;
609                                                    ip = copy.getImportedPage(pdfReaders[doc], page);
610                                                    
611                                                    //ip.getPdfDocument().setHeader(arg0);
612                                                    //ip.getPdfDocument().setFooter(arg0);
613                                                    copy.addPage(ip);
614                                            }
615                                    }
616                                    if (doBookmarks && !bookmarks.isEmpty())copy.setOutlines(bookmarks);
617                            }
618                            finally {
619                                    document.close();
620                            }
621                            pdf=baos.toByteArray();
622                    }
623                    else if(documents.size()==1){
624                            pdf=(documents.get(0)).render(getDimension(),unitFactor,pageContext,doHtmlBookmarks);
625                    }
626                    else {
627                            pdf=getDocument().render(getDimension(),unitFactor,pageContext,doHtmlBookmarks);
628                    }
629                    
630                    // permission/encryption
631                    if(PDFDocument.ENC_NONE!=encryption) {
632                            PdfReader reader = new PdfReader(pdf);
633                            com.lowagie.text.Document document = new com.lowagie.text.Document(reader.getPageSize(1));
634                            document.addCreator("Railo "+Info.getVersionAsString()+" "+Info.getStateAsString());
635                            ByteArrayOutputStream baos = new ByteArrayOutputStream();
636                            PdfCopy copy = new PdfCopy(document,baos);
637                            //PdfWriter writer = PdfWriter.getInstance(document, pdfOut);
638                            copy.setEncryption(PDFDocument.ENC_128BIT==encryption , userpassword , ownerpassword , permissions);
639                            document.open();
640                            int size=reader.getNumberOfPages();
641                            for(int page=1;page<=size;page++) {
642                                    copy.addPage(copy.getImportedPage(reader, page));
643                            }
644                            document.close();
645                            pdf=baos.toByteArray();
646                    }
647                    
648                    // write out
649                    if(os!=null)IOUtil.copy(new ByteArrayInputStream(pdf), os,true,false);
650                    if(!StringUtil.isEmpty(name)) {
651                            pageContext.setVariable(name,pdf);
652                    }
653            }
654    
655            private OutputStream getOutputStream() throws PageException, IOException {
656            try {
657                    return ((PageContextImpl)pageContext).getResponseStream();
658            } 
659            catch(IllegalStateException ise) {
660                throw new TemplateException("content is already send to user, flush");
661            }
662        }
663            
664    
665            private Dimension getDimension() throws ApplicationException {
666                    // page size custom
667                    if(isCustom(pagetype)) {
668                            if(pageheight==0 || pagewidth==0)
669                                    throw new ApplicationException("when attribute pagetype has value [custom], the attributes [pageheight, pagewidth] must have a positive numeric value");
670                            pagetype=new Dimension(PDFDocument.toPoint(pagewidth,unitFactor),PDFDocument.toPoint(pageheight,unitFactor));
671                    }
672                    // page orientation
673                    if(isLandscape)pagetype=new Dimension(pagetype.height, pagetype.width);
674                    return pagetype;
675            }
676            
677    
678            private boolean isCustom(Dimension d) throws ApplicationException {
679                    if(d.height<=0 || d.width<=0)
680                            throw new ApplicationException("if you define pagetype as custom, you have to define attribute pageheight and pagewith with a positive numeric value");
681                    
682                    
683                    return (d.width+d.height)==2;
684            }
685            
686            /**
687             * sets if has body or not
688             * @param hasBody
689             */
690            public void hasBody(boolean hasBody) {
691                
692            }
693    
694    
695    
696    }
697            
698