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