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