001    package railo.runtime.tag;
002    
003    import java.awt.Color;
004    import java.awt.image.BufferedImage;
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.HashMap;
012    import java.util.Iterator;
013    import java.util.Set;
014    
015    import org.apache.oro.text.regex.MalformedPatternException;
016    import org.pdfbox.exceptions.CryptographyException;
017    import org.pdfbox.exceptions.InvalidPasswordException;
018    
019    import railo.commons.io.IOUtil;
020    import railo.commons.io.res.Resource;
021    import railo.commons.io.res.filter.ExtensionResourceFilter;
022    import railo.commons.io.res.filter.ResourceFilter;
023    import railo.commons.io.res.util.ResourceUtil;
024    import railo.commons.io.res.util.WildCardFilter;
025    import railo.commons.lang.StringUtil;
026    import railo.runtime.exp.ApplicationException;
027    import railo.runtime.exp.CasterException;
028    import railo.runtime.exp.ExpressionException;
029    import railo.runtime.exp.PageException;
030    import railo.runtime.ext.tag.BodyTagImpl;
031    import railo.runtime.op.Caster;
032    import railo.runtime.op.Decision;
033    import railo.runtime.text.pdf.PDFDocument;
034    import railo.runtime.text.pdf.PDFUtil;
035    import railo.runtime.type.Array;
036    import railo.runtime.type.Collection.Key;
037    import railo.runtime.type.List;
038    import railo.runtime.type.Struct;
039    
040    import com.lowagie.text.DocumentException;
041    import com.lowagie.text.Image;
042    import com.lowagie.text.pdf.PdfContentByte;
043    import com.lowagie.text.pdf.PdfGState;
044    import com.lowagie.text.pdf.PdfImportedPage;
045    import com.lowagie.text.pdf.PdfReader;
046    import com.lowagie.text.pdf.PdfStamper;
047    import com.lowagie.text.pdf.PdfWriter;
048    import com.lowagie.text.pdf.SimpleBookmark;
049    
050    public class PDF extends BodyTagImpl  {
051    
052            private static final int ACTION_ADD_WATERMARK = 0;
053            private static final int ACTION_DELETE_PAGES = 1;
054            private static final int ACTION_GET_INFO = 2;
055            private static final int ACTION_MERGE = 3;
056            private static final int ACTION_PROCESSDDX = 5;
057            private static final int ACTION_PROTECT = 5;
058            private static final int ACTION_READ = 6;
059            private static final int ACTION_REMOVE_WATERMARK = 7;
060            private static final int ACTION_SET_INFO = 8;
061            private static final int ACTION_THUMBNAIL = 9;
062            private static final int ACTION_WRITE = 10;
063            private static final int ACTION_EXTRACT_TEXT = 11;
064    
065            
066            private static final String FORMAT_JPG ="jpg";
067            private static final String FORMAT_TIFF = "tiff";
068            private static final String FORMAT_PNG = "png";
069            
070            private static final int ORDER_TIME = 0;
071            private static final int ORDER_NAME = 1;
072            
073            private static final int RESOLUTION_HIGH = 0;
074            private static final int RESOLUTION_LOW = 1;
075    
076            private static final int SAVE_OPTION_FULL = 0;
077            private static final int SAVE_OPTION_INCREMENTAL = 1;
078            private static final int SAVE_OPTION_LINEAR = 2;
079            
080            private static final int TYPE_STRING = 1;
081            private static final int TYPE_XML = 2;
082        
083            
084            private static final ExtensionResourceFilter PDF_FILTER = new ExtensionResourceFilter("pdf");
085            private static final int UNDEFINED = Integer.MIN_VALUE;
086            
087            
088            
089            private int action=ACTION_PROCESSDDX;
090            private boolean ascending =false;
091            private Object copyFrom=null;
092            private String ddxFile=null;
093            private Resource destination=null;
094            private Resource directory=null;
095            private int encrypt=PDFUtil.ENCRYPT_RC4_128;
096            private boolean flatten=false;
097            private boolean foreground=false;
098            private String format=FORMAT_JPG;
099            private Object image=null;
100            private Struct info=null;
101            private Struct inputFiles=null;
102            private Struct outputFiles=null;
103            private boolean isBase64=false;
104            private boolean keepBookmark=false;
105            private String name=null;
106            private String newOwnerPassword=null;
107            private String newUserPassword=null;
108            private float opacity=0.3F;
109            private int order=ORDER_TIME;
110            private boolean overwrite=false;
111            private String pages=null;
112            private String password=null;
113            private int permissions=0;
114            private String position=null;
115            private int resolution=RESOLUTION_HIGH;
116            private float rotation=0;
117            private int saveOption=SAVE_OPTION_FULL;
118            private int scale=25;
119            private boolean showOnPrint=false;
120            private Object source =null;
121            private boolean stopOnError=false;
122            private boolean transparent=false;
123            private char version=0;
124            private java.util.List<PDFParamBean> params;
125            private ResourceFilter filter=null;
126            private String imagePrefix=null;
127            private int type=TYPE_XML;
128            
129            /**
130             * @see railo.runtime.ext.tag.BodyTagImpl#release()
131             */
132            public void release() {
133                    super.release();
134                    action=ACTION_PROCESSDDX;
135                    ascending =false;
136                    copyFrom=null;
137                    ddxFile=null;
138                    destination=null;
139                    directory=null;
140                    encrypt=PDFUtil.ENCRYPT_RC4_128;
141                    flatten=false;
142                    foreground=false;
143                    format=FORMAT_JPG;
144                    image=null;
145                    info=null;
146                    inputFiles=null;
147                    outputFiles=null;
148                    isBase64=false;
149                    keepBookmark=false;
150                    name=null;
151                    newOwnerPassword=null;
152                    newUserPassword=null;
153                    opacity=0.3F;
154                    order=ORDER_TIME;
155                    overwrite=false;
156                    pages=null;
157                    password=null;
158                    permissions=0;
159                    position=null;
160                    resolution=RESOLUTION_HIGH;
161                    rotation=0;
162                    saveOption=SAVE_OPTION_FULL;
163                    scale=25;
164                    showOnPrint=false;
165                    source =null;
166                    stopOnError=false;
167                    transparent=false;
168                    version=0;
169                    params=null;
170                    filter=null;
171                    imagePrefix=null;
172                    type=TYPE_XML;
173            }
174            
175            
176            
177            /**
178             * @param imagePrefix the imagePrefix to set
179             */
180            public void setImageprefix(String imagePrefix) {
181                    this.imagePrefix = imagePrefix;
182            }
183    
184    
185    
186            /**
187             * @param action the action to set
188             * @throws ApplicationException 
189             */
190            public void setAction(String strAction) throws ApplicationException {
191                    
192                    strAction=StringUtil.toLowerCase(strAction.trim());
193                    if("addwatermark".equals(strAction))                            action=ACTION_ADD_WATERMARK;
194                    else if("add-watermark".equals(strAction))                      action=ACTION_ADD_WATERMARK;
195                    else if("add_watermark".equals(strAction))                      action=ACTION_ADD_WATERMARK;
196                    else if("deletepages".equals(strAction))                        action=ACTION_DELETE_PAGES;
197                    else if("delete-pages".equals(strAction))                       action=ACTION_DELETE_PAGES;
198                    else if("delete_pages".equals(strAction))                       action=ACTION_DELETE_PAGES;
199                    else if("deletepage".equals(strAction))                         action=ACTION_DELETE_PAGES;
200                    else if("delete-page".equals(strAction))                        action=ACTION_DELETE_PAGES;
201                    else if("delete_page".equals(strAction))                        action=ACTION_DELETE_PAGES;
202                    else if("getinfo".equals(strAction))                            action=ACTION_GET_INFO;
203                    else if("get-info".equals(strAction))                           action=ACTION_GET_INFO;
204                    else if("get_info".equals(strAction))                           action=ACTION_GET_INFO;
205                    else if("merge".equals(strAction))                                      action=ACTION_MERGE;
206                    //else if("processddx".equals(strAction))                               action=ACTION_PROCESSDDX;
207                    //else if("process-ddx".equals(strAction))                      action=ACTION_PROCESSDDX;
208                    //else if("process_ddx".equals(strAction))                      action=ACTION_PROCESSDDX;
209                    else if("protect".equals(strAction))                            action=ACTION_PROTECT;
210                    else if("read".equals(strAction))                                       action=ACTION_READ;
211                    else if("removewatermark".equals(strAction))            action=ACTION_REMOVE_WATERMARK;
212                    else if("removewater-mark".equals(strAction))           action=ACTION_REMOVE_WATERMARK;
213                    else if("removewater_mark".equals(strAction))           action=ACTION_REMOVE_WATERMARK;
214                    else if("setinfo".equals(strAction))                            action=ACTION_SET_INFO;
215                    else if("set-info".equals(strAction))                           action=ACTION_SET_INFO;
216                    else if("set_info".equals(strAction))                           action=ACTION_SET_INFO;
217                    else if("thumbnail".equals(strAction))                          action=ACTION_THUMBNAIL;
218                    else if("write".equals(strAction))                                      action=ACTION_WRITE;
219                    else if("extracttext".equals(strAction))                                        action=ACTION_EXTRACT_TEXT;
220                    else if("extract-text".equals(strAction))                                       action=ACTION_EXTRACT_TEXT;
221                    else if("extract_text".equals(strAction))                                       action=ACTION_EXTRACT_TEXT;
222                    
223                    else throw new ApplicationException("invalid action definition ["+strAction+"], valid actions definitions are " +
224                                    "[addWatermark,deletePages,getInfo,merge,protect,read,removeWatermark,setInfo,thumbnail,write]");
225                    
226            }
227            
228    
229            public void setType(String strType) throws ApplicationException {
230                    
231                    strType=StringUtil.toLowerCase(strType.trim());
232                    if("string".equals(strType))                            type=TYPE_STRING;
233                    else if("text".equals(strType))                         type=TYPE_STRING;
234                    else if("plain".equals(strType))                                type=TYPE_STRING;
235                    else if("xml".equals(strType))                          type=TYPE_XML;
236                    
237                    else throw new ApplicationException("invalid type definition ["+strType+"], valid type definitions are " +
238                                    "[string,xml]");
239                    
240            }
241            
242            /** 
243            *  sets a filter pattern
244            * @param pattern
245             * @throws PageException 
246            **/
247            public void setFilter(String pattern) throws PageException      {
248                if(pattern.trim().length()>0) {
249                try {
250                    this.filter=new WildCardFilter(pattern);
251                } 
252                catch (MalformedPatternException e) {
253                    throw Caster.toPageException(e);
254                }
255            }
256            }
257            
258            /**
259             * @param ascending the ascending to set
260             */
261            public void setAscending(boolean ascending) {
262                    this.ascending = ascending;
263            }
264            /**
265             * @param copyFrom the copyFrom to set
266             * @throws ExpressionException 
267             */
268            public void setCopyfrom(Object copyFrom) throws ExpressionException {
269                    this.copyFrom = copyFrom;//ResourceUtil.toResourceExisting(pageContext, copyFrom);
270            }
271            /**
272             * @param ddxFile the ddxFile to set
273             */
274            public void setDdxfile(String ddxFile) {
275                    this.ddxFile = ddxFile;// MUST
276            }
277            /**
278             * @param destination the destination to set
279             */
280            public void setDestination(String destination) {
281                    this.destination = ResourceUtil.toResourceNotExisting(pageContext, destination);
282            }
283            /**
284             * @param directory the directory to set
285             * @throws ExpressionException 
286             */
287            public void setDirectory(String directory) throws ExpressionException {
288                    this.directory = ResourceUtil.toResourceExisting(pageContext, directory);
289            }
290            /**
291             * @param encrypt the encrypt to set
292             * @throws ApplicationException 
293             */
294            public void setEncrypt(String strEncrypt) throws ApplicationException {
295    
296                    strEncrypt=StringUtil.toLowerCase(strEncrypt.trim());
297                    if("aes128".equals(strEncrypt))                         encrypt=PDFUtil.ENCRYPT_AES_128;        
298                    else if("aes-128".equals(strEncrypt))           encrypt=PDFUtil.ENCRYPT_AES_128;        
299                    else if("aes_128".equals(strEncrypt))           encrypt=PDFUtil.ENCRYPT_AES_128;        
300                    else if("none".equals(strEncrypt))                      encrypt=PDFUtil.ENCRYPT_NONE;           
301                    else if("".equals(strEncrypt))                          encrypt=PDFUtil.ENCRYPT_NONE;           
302                    else if("rc4128".equals(strEncrypt))            encrypt=PDFUtil.ENCRYPT_RC4_128;                
303                    else if("rc4-128".equals(strEncrypt))           encrypt=PDFUtil.ENCRYPT_RC4_128;                
304                    else if("rc4_128".equals(strEncrypt))           encrypt=PDFUtil.ENCRYPT_RC4_128;                
305                    else if("rc4128m".equals(strEncrypt))           encrypt=PDFUtil.ENCRYPT_RC4_128M;               
306                    else if("rc4-128m".equals(strEncrypt))          encrypt=PDFUtil.ENCRYPT_RC4_128M;               
307                    else if("rc4_128m".equals(strEncrypt))          encrypt=PDFUtil.ENCRYPT_RC4_128M;               
308                    else if("rc440".equals(strEncrypt))                     encrypt=PDFUtil.ENCRYPT_RC4_40;         
309                    else if("rc4-40".equals(strEncrypt))            encrypt=PDFUtil.ENCRYPT_RC4_40;         
310                    else if("rc4_40".equals(strEncrypt))            encrypt=PDFUtil.ENCRYPT_RC4_40;         
311                    
312                    
313                    else throw new ApplicationException("invalid encrypt definition ["+strEncrypt+"], valid encrypt definitions are " +
314                                    "[aes_128,none,rc4_128,rc4_128m,rc4_40]");
315            }
316            /**
317             * @param flatten the flatten to set
318             */
319            public void setFlatten(boolean flatten) {
320                    this.flatten = flatten;
321            }
322            /**
323             * @param foreground the foreground to set
324             */
325            public void setForeground(boolean foreground) {
326                    this.foreground = foreground;
327            }
328            /**
329             * @param format the format to set
330             * @throws ApplicationException 
331             */
332            public void setFormat(String strFormat) throws ApplicationException {
333                    strFormat=StringUtil.toLowerCase(strFormat.trim());
334                    if("jpg".equals(strFormat))                                     format=FORMAT_JPG;      
335                    else if("jpeg".equals(strFormat))                       format=FORMAT_JPG;      
336                    else if("jpe".equals(strFormat))                        format=FORMAT_JPG;      
337                    else if("tiff".equals(strFormat))                       format=FORMAT_TIFF;
338                    else if("tif".equals(strFormat))                        format=FORMAT_TIFF;     
339                    else if("png".equals(strFormat))                        format=FORMAT_PNG;      
340                    
341                    else throw new ApplicationException("invalid format definition ["+strFormat+"], valid format definitions are " +
342                                    "[jpg,tiff,png]");
343            }
344            /**
345             * @param image the image to set
346             */
347            public void setImage(Object image) {
348                    this.image = image;// MUST
349            }
350            /**
351             * @param prefix the prefix to set
352             */
353            public void setPrefix(String prefix) {
354                    this.imagePrefix = prefix;
355            }
356            /**
357             * @param info the info to set
358             */
359            public void setInfo(Struct info) {
360                    this.info = info;
361            }
362            /**
363             * @param inputFiles the inputFiles to set
364             */
365            public void setInputfiles(Struct inputFiles) {
366                    this.inputFiles = inputFiles;
367            }
368            /**
369             * @param outputFiles the outputFiles to set
370             */
371            public void setOutputfiles(Struct outputFiles) {
372                    this.outputFiles = outputFiles;
373            }
374            /**
375             * @param isBase64 the isBase64 to set
376             */
377            public void setIsbase64(boolean isBase64) {
378                    this.isBase64 = isBase64;
379            }
380            /**
381             * @param keepBookmark the keepBookmark to set
382             */
383            public void setKeepbookmark(boolean keepBookmark) {
384                    this.keepBookmark = keepBookmark;
385            }
386            /**
387             * @param name the name to set
388             */
389            public void setName(String name) {
390                    this.name = name;
391            }
392            /**
393             * @param newOwnerPassword the newOwnerPassword to set
394             */
395            public void setNewownerpassword(String newOwnerPassword) {
396                    this.newOwnerPassword = newOwnerPassword;
397            }
398            /**
399             * @param newUserPassword the newUserPassword to set
400             */
401            public void setNewuserpassword(String newUserPassword) {
402                    this.newUserPassword = newUserPassword;
403            }
404            /**
405             * @param opacity the opacity to set
406             * @throws ApplicationException 
407             */
408            public void setOpacity(double opacity) throws ApplicationException {
409                    if(opacity<0 || opacity>10) 
410                            throw new ApplicationException("invalid opacity definition ["+Caster.toString(opacity)+"], value should be in range from 0 to 10");
411                    this.opacity = (float) (opacity/10);
412            }
413            /**
414             * @param order the order to set
415             * @throws ApplicationException 
416             */
417            public void setOrder(String strOrder) throws ApplicationException {
418                    strOrder=StringUtil.toLowerCase(strOrder.trim());
419                    if("name".equals(strOrder))                                     order=ORDER_NAME;       
420                    else if("time".equals(strOrder))                        order=ORDER_TIME;       
421                    
422                    else throw new ApplicationException("invalid order definition ["+strOrder+"], valid order definitions are " +
423                                    "[name,time]");
424            }
425            /**
426             * @param overwrite the overwrite to set
427             */
428            public void setOverwrite(boolean overwrite) {
429                    this.overwrite = overwrite;
430            }
431            /**
432             * @param pages the pages to set
433             */
434            public void setPages(String pages) {
435                    this.pages = pages;
436            }
437            /**
438             * @param password the password to set
439             */
440            public void setPassword(String password) {
441                    this.password = password;
442            }
443            /**
444             * @param permissions the permissions to set
445             * @throws PageException 
446             */
447            public void setPermissions(String strPermissions) throws PageException {
448                    permissions=PDFUtil.toPermissions(strPermissions);
449            }       
450            /**
451             * @param position the position to set
452             */
453            public void setPosition(String position) {
454                    this.position = position;//MUST
455            }
456            /**
457             * @param resolution the resolution to set
458             * @throws ApplicationException 
459             */
460            public void setResolution(String strResolution) throws ApplicationException {
461                    strResolution=StringUtil.toLowerCase(strResolution.trim());
462                    if("low".equals(strResolution))                 resolution=RESOLUTION_LOW;      
463                    else if("high".equals(strResolution))   resolution=RESOLUTION_HIGH;     
464                    
465                    else throw new ApplicationException("invalid resolution definition ["+strResolution+"], valid resolution definitions are " +
466                                    "[low,high]");
467            }
468            
469            /**
470             * @param rotation the rotation to set
471             */
472            public void setRotation(double rotation) {
473                    rotation=rotation%360D;
474                    //rotation=rotation/360*6.28318525;
475                    
476                    this.rotation = (float) rotation;
477            }
478            
479            /**
480             * @param saveOption the saveOption to set
481             * @throws ApplicationException 
482             */
483            public void setSaveoption(String strSaveOption) throws ApplicationException {
484                    strSaveOption=StringUtil.toLowerCase(strSaveOption.trim());
485                    if("full".equals(strSaveOption))                        saveOption=SAVE_OPTION_FULL;    
486                    else if("incremental".equals(strSaveOption))saveOption=SAVE_OPTION_INCREMENTAL; 
487                    else if("linear".equals(strSaveOption))         saveOption=SAVE_OPTION_LINEAR;  
488                    
489                    else throw new ApplicationException("invalid saveOption definition ["+strSaveOption+"], valid saveOption definitions are " +
490                                    "[full,linear,incremental]");
491            }
492            
493            /**
494             * @param scale the scale to set
495             * @throws ApplicationException 
496             */
497            public void setScale(double scale) throws ApplicationException {
498                    //if(scale<1 || scale>1000)  this check is now done inside PDF2IMage implementation
499                    //      throw new ApplicationException("invalid scale definition ["+Caster.toString(scale)+"], value should be in range from 1 to 100");
500                    this.scale = (int) scale;
501            }
502            
503            /**
504             * @param showOnPrint the showOnPrint to set
505             */
506            public void setShowonprint(boolean showOnPrint) {
507                    this.showOnPrint = showOnPrint;
508            }
509            
510            /**
511             * @param source the source to set
512             */
513            public void setSource(Object source) {
514                    this.source = source;
515            }
516            /**
517             * @param stopOnError the stopOnError to set
518             */
519            public void setStoponerror(boolean stopOnError) {
520                    this.stopOnError = stopOnError;
521            }
522            /**
523             * @param transparent the transparent to set
524             */
525            public void setTransparent(boolean transparent) {
526                    this.transparent = transparent;
527            }
528            /**
529             * @param version the version to set
530             * @throws ApplicationException 
531             */
532            public void setVersion(double version) throws ApplicationException {
533                    if(1.1 == version)                      this.version='1';       
534                    else if(1.2 == version)         this.version=PdfWriter.VERSION_1_2;     
535                    else if(1.3 == version)         this.version=PdfWriter.VERSION_1_3;     
536                    else if(1.4 == version)         this.version=PdfWriter.VERSION_1_4;     
537                    else if(1.5 == version)         this.version=PdfWriter.VERSION_1_5;     
538                    else if(1.6 == version)         this.version=PdfWriter.VERSION_1_6;     
539                    
540                    else throw new ApplicationException("invalid version definition ["+Caster.toString(version)+"], valid version definitions are " +
541                                    "[1.1, 1.2, 1.3, 1.4, 1.5, 1.6]");
542            }
543            
544            /**
545            * @throws PageException 
546         * @see javax.servlet.jsp.tagext.Tag#doStartTag()
547            */
548            public int doStartTag() throws PageException    {
549                    // RR SerialNumber sn = pageContext.getConfig().getSerialNumber();
550                //if(sn.getVersion()==SerialNumber.VERSION_COMMUNITY)
551                //    throw new SecurityException("no access to this functionality with the "+sn.getStringVersion()+" version of railo");
552                
553                return EVAL_BODY_BUFFERED;
554            }
555    
556            /**
557            * @see javax.servlet.jsp.tagext.BodyTag#doInitBody()
558            */
559            public void doInitBody()        {
560                    
561            }
562            
563            /**
564            * @see javax.servlet.jsp.tagext.BodyTag#doAfterBody()
565            */
566            public int doAfterBody()        {
567                    return SKIP_BODY;
568            }
569            
570            /**
571             *
572             * @throws IOException 
573             * @throws InvalidParameterException 
574             * @see railo.runtime.ext.tag.TagImpl#doEndTag()
575             */
576            public int doEndTag() throws PageException {
577                    try {
578    
579                            if(ACTION_ADD_WATERMARK==action)                        doActionAddWatermark();
580                            else if(ACTION_REMOVE_WATERMARK==action)        doActionRemoveWatermark();
581                            else if(ACTION_READ==action)                            doActionRead();
582                            else if(ACTION_WRITE==action)                           doActionWrite();
583                            else if(ACTION_GET_INFO==action)                        doActionGetInfo();
584                            else if(ACTION_SET_INFO==action)                        doActionSetInfo();
585                            else if(ACTION_MERGE==action)                           doActionMerge();
586                            else if(ACTION_DELETE_PAGES==action)            doActionDeletePages();
587                            else if(ACTION_PROTECT==action)                         doActionProtect();
588                            else if(ACTION_THUMBNAIL==action)                       doActionThumbnail();
589                            else if(ACTION_EXTRACT_TEXT==action)            {
590                                    if(true)throw new ApplicationException("not supported yet, see https://issues.jboss.org/browse/RAILO-1559");
591                                    doActionExtractText();
592                            }
593                            
594                            //else if(ACTION_PROCESSDDX==action)    throw new ApplicationException("action [processddx] not supported");
595                            
596                            
597                            
598                    }
599                    catch (Exception e) {
600                            throw Caster.toPageException(e);
601                    }       
602                    return EVAL_PAGE;
603            }
604            
605            
606            
607            
608            private void doActionWrite() throws PageException, IOException, DocumentException {
609                    required("pdf", "write", "source", source);
610                    required("pdf", "write", "destination", destination);
611                    
612                    if(destination.exists() && !overwrite)
613                            throw new ApplicationException("destination file ["+destination+"] already exists");
614                    
615                    PDFDocument doc = toPDFDocument(source, password, null);
616                    //PdfReader pr = doc.getPdfReader();
617                    // output
618                    boolean destIsSource = doc.getResource()!=null && destination.equals(doc.getResource());
619                    
620                    OutputStream os=null;
621                    if(destIsSource){
622                            os=new ByteArrayOutputStream();
623                    }
624                    else if(destination!=null) {
625                            os=destination.getOutputStream();
626                    }
627                    
628                    try {   
629                            PDFUtil.concat(new PDFDocument[]{doc}, os, true, true, true,version);
630                    }
631                    finally {
632                            IOUtil.closeEL(os);
633                            if(os instanceof ByteArrayOutputStream) {
634                                    if(destination!=null)IOUtil.copy(new ByteArrayInputStream(((ByteArrayOutputStream)os).toByteArray()), destination,true);// MUST overwrite
635                            }
636                    }
637                    
638    /*      
639                    // flatten = "yes|no"
640                // must saveOption = "linear|incremental|full"
641    */
642            }
643    
644    
645    
646            private void doActionThumbnail() throws PageException, IOException, DocumentException {
647                    required("pdf", "thumbnail", "source", source);
648    
649                    PDFDocument doc = toPDFDocument(source, password, null);
650                    PdfReader pr = doc.getPdfReader();
651                    boolean isEnc=pr.isEncrypted();
652                    pr.close();
653                    if(isEnc) {
654                            ByteArrayOutputStream baos = new ByteArrayOutputStream();
655                            //PDFUtil.concat(new PDFDocument[]{doc}, baos, true, true, true, (char)0);
656                            PDFUtil.encrypt(doc,baos,null,null,0,PDFUtil.ENCRYPT_NONE);
657                            baos.close();
658                            doc = new PDFDocument(baos.toByteArray(),doc.getResource(),null);
659                    }
660                    
661                    doc.setPages(pages);
662                    
663                    // scale
664                    if(scale<1)
665                            throw new ApplicationException("value of attribute scale ["+scale+"] should be at least 1");
666                    
667                    // destination
668                    if(destination==null)
669                            destination=ResourceUtil.toResourceNotExisting(pageContext, "thumbnails");
670                    
671                    // imagePrefix
672                    if(imagePrefix==null){
673                            Resource res = doc.getResource();
674                            if(res!=null){
675                                    String n = res.getName();
676                                    int index=n.lastIndexOf('.');
677                                    if(index!=-1)imagePrefix=n.substring(0,index);
678                                    else imagePrefix=n;
679                            }
680                            else imagePrefix="memory";
681                    }
682                    
683                    // MUST password
684                    PDFUtil.writeImages(doc.getRaw(), doc.getPages(), destination, imagePrefix, format, scale,overwrite,
685                                    resolution==RESOLUTION_HIGH,transparent);
686                    
687                    
688                    
689            }
690            
691            
692            
693            
694            private void doActionAddWatermark() throws PageException, IOException, DocumentException {
695                    required("pdf", "addWatermark", "source", source);
696                    if(copyFrom==null && image==null)
697                            throw new ApplicationException("at least one of the following attributes must be defined " +
698                                            "[copyFrom,image]");
699                    
700                    if(destination!=null && destination.exists() && !overwrite)
701                            throw new ApplicationException("destination file ["+destination+"] already exists");
702                    
703                    
704                    // image
705                    Image img=null;
706                    if(image!=null) {
707                            railo.runtime.img.Image ri = railo.runtime.img.Image.createImage(pageContext,image,false,false,true);
708                            img=Image.getInstance(ri.getBufferedImage(),null,false);
709                    }
710                    // copy From
711                    else {
712                            byte[] barr;
713                            try{
714                                    Resource res = Caster.toResource(pageContext, copyFrom, true);
715                                    barr=IOUtil.toBytes(res);
716                            }
717                            catch(ExpressionException ee) {
718                                    barr=Caster.toBinary(copyFrom);
719                            }
720                            img=Image.getInstance(PDFUtil.toImage(barr, 1).getBufferedImage(),null,false);
721                            
722                    }
723                    
724                    // position
725                    float x=UNDEFINED,y=UNDEFINED;
726                    if(!StringUtil.isEmpty(position)) {
727                            int index=position.indexOf(',');
728                            if(index==-1)
729                                    throw new ApplicationException("attribute [position] has a invalid value ["+position+"]," +
730                                                    "value should follow one of the following pattern [40,50], [40,] or [,50]");
731                            String strX = position.substring(0,index).trim();
732                            String strY = position.substring(index+1).trim();
733                            if(!StringUtil.isEmpty(strX))x = Caster.toIntValue(strX);
734                            if(!StringUtil.isEmpty(strY))y = Caster.toIntValue(strY);
735                            
736                    }
737                    
738                    
739                    PDFDocument doc = toPDFDocument(source, password, null);
740                    doc.setPages(pages);
741                    PdfReader reader = doc.getPdfReader();
742                    reader.consolidateNamedDestinations();
743                    boolean destIsSource = destination!=null && doc.getResource()!=null && destination.equals(doc.getResource());
744                    java.util.List bookmarks = SimpleBookmark.getBookmark(reader);
745                ArrayList master = new ArrayList(); 
746                    if(bookmarks!=null)master.addAll(bookmarks);
747                
748                    // output
749                    OutputStream os=null;
750                    if(!StringUtil.isEmpty(name) || destIsSource){
751                            os=new ByteArrayOutputStream();
752                    }
753                    else if(destination!=null) {
754                            os=destination.getOutputStream();
755                    }
756                    
757                    try {
758                            
759                            int len = reader.getNumberOfPages();
760                        PdfStamper stamp = new PdfStamper(reader, os);
761                        
762                        if(len >0){
763                            if(x==UNDEFINED || y==UNDEFINED) {
764                                    PdfImportedPage first = stamp.getImportedPage(reader, 1);
765                                    if(y==UNDEFINED)y=(first.getHeight()-img.getHeight())/2;
766                                    if(x==UNDEFINED)x=(first.getWidth()-img.getWidth())/2;          
767                            }
768                            img.setAbsolutePosition(x, y);
769                            //img.setAlignment(Image.ALIGN_JUSTIFIED); ration geht nicht anhand mitte
770                            
771                        }
772                        
773                            // rotation
774                            if(rotation!=0) {
775                                    img.setRotationDegrees(rotation);
776                            }
777                            
778                            Set _pages = doc.getPages();
779                        for (int i=1;i<=len;i++) {
780                            if(_pages!=null && !_pages.contains(Integer.valueOf(i))) continue;
781                            PdfContentByte cb =foreground? stamp.getOverContent(i):stamp.getUnderContent(i);
782                            PdfGState gs1 = new PdfGState();
783                            //print.out("op:"+opacity);
784                            gs1.setFillOpacity(opacity);
785                            //gs1.setStrokeOpacity(opacity);
786                            cb.setGState(gs1);
787                            cb.addImage(img);
788                        }
789                        if(bookmarks!=null)stamp.setOutlines(master);
790                        stamp.close();
791                    }
792                    finally {
793                            IOUtil.closeEL(os);
794                            if(os instanceof ByteArrayOutputStream) {
795                                    if(destination!=null)IOUtil.copy(new ByteArrayInputStream(((ByteArrayOutputStream)os).toByteArray()), destination,true);// MUST overwrite
796                                    if(!StringUtil.isEmpty(name)){
797                                            pageContext.setVariable(name,new PDFDocument(((ByteArrayOutputStream)os).toByteArray(),password));
798                                    }
799                            }
800                    }
801            }
802            
803            private void doActionRemoveWatermark() throws PageException, IOException, DocumentException {
804                    required("pdf", "removeWatermark", "source", source);
805                    
806                    if(destination!=null && destination.exists() && !overwrite)
807                            throw new ApplicationException("destination file ["+destination+"] already exists");
808                    
809                    railo.runtime.img.Image ri = new railo.runtime.img.Image(1,1,BufferedImage.TYPE_INT_RGB,Color.BLACK);
810                    Image img = Image.getInstance(ri.getBufferedImage(),null,false);
811                    img.setAbsolutePosition(1,1);
812                    
813                    
814                    PDFDocument doc = toPDFDocument(source, password, null);
815                    doc.setPages(pages);
816                    PdfReader reader = doc.getPdfReader();
817    
818                    boolean destIsSource = destination!=null && doc.getResource()!=null && destination.equals(doc.getResource());
819                    java.util.List bookmarks = SimpleBookmark.getBookmark(reader);
820                ArrayList master = new ArrayList(); 
821                    if(bookmarks!=null)master.addAll(bookmarks);
822                
823                    // output
824                    OutputStream os=null;
825                    if(!StringUtil.isEmpty(name) || destIsSource){
826                            os=new ByteArrayOutputStream();
827                    }
828                    else if(destination!=null) {
829                            os=destination.getOutputStream();
830                    }
831                    
832                    try {
833                            int len = reader.getNumberOfPages();
834                        PdfStamper stamp = new PdfStamper(reader, os);
835                            
836                            Set _pages = doc.getPages();
837                        for (int i=1;i<=len;i++) {
838                            if(_pages!=null && !_pages.contains(Integer.valueOf(i))) continue;
839                            PdfContentByte cb =foreground? stamp.getOverContent(i):stamp.getUnderContent(i);
840                            PdfGState gs1 = new PdfGState();
841                            gs1.setFillOpacity(0);
842                            cb.setGState(gs1);
843                            cb.addImage(img);
844                        }
845                        if(bookmarks!=null)stamp.setOutlines(master);
846                        stamp.close();
847                    }
848                    finally {
849                            IOUtil.closeEL(os);
850                            if(os instanceof ByteArrayOutputStream) {
851                                    if(destination!=null)IOUtil.copy(new ByteArrayInputStream(((ByteArrayOutputStream)os).toByteArray()), destination,true);// MUST overwrite
852                                    if(!StringUtil.isEmpty(name)){
853                                            pageContext.setVariable(name,new PDFDocument(((ByteArrayOutputStream)os).toByteArray(),password));
854                                    }
855                            }
856                    }
857            }
858            
859            private void doActionDeletePages() throws PageException, IOException, DocumentException {
860                    required("pdf", "deletePage", "pages", pages,true);
861                    required("pdf", "deletePage", "source", source);
862                    
863                    PDFDocument doc = toPDFDocument(source, password, null);
864                    doc.setPages(pages);
865                    
866                    
867                    if(destination==null && StringUtil.isEmpty(name)){
868                            if(doc.getResource()==null)
869                                    throw new ApplicationException("source is not based on a resource, destination attribute is required");
870                            destination=doc.getResource();
871                    }
872                    else if(destination!=null && destination.exists() && !overwrite)
873                            throw new ApplicationException("destination file ["+destination+"] already exists");
874                    
875                    boolean destIsSource = destination!=null && doc.getResource()!=null && destination.equals(doc.getResource());
876                    
877                    // output
878                    OutputStream os=null;
879                    if(!StringUtil.isEmpty(name) || destIsSource){
880                            os=new ByteArrayOutputStream();
881                    }
882                    else if(destination!=null) {
883                            os=destination.getOutputStream();
884                    }
885                    
886                    try {
887                            PDFUtil.concat(new PDFDocument[]{doc}, os, true, true,true,version);
888                    }
889                    finally {
890                            //if(document!=null)document.close();
891                            IOUtil.closeEL(os);
892                            if(os instanceof ByteArrayOutputStream) {
893                                    if(destination!=null)IOUtil.copy(new ByteArrayInputStream(((ByteArrayOutputStream)os).toByteArray()), destination,true);// MUST overwrite
894                                    if(!StringUtil.isEmpty(name)){
895                                            pageContext.setVariable(name,new PDFDocument(((ByteArrayOutputStream)os).toByteArray(),password));
896                                    }
897                            }
898                    }
899            }
900            
901            
902            private void doActionMerge() throws ApplicationException, PageException, IOException, DocumentException {
903                    
904                    if(source==null && params==null && directory==null)
905                            throw new ApplicationException("at least one of the following constellation must be defined" +
906                                            " attribute source, attribute directory or cfpdfparam child tags");
907                    if(destination==null && StringUtil.isEmpty(name,true))
908                            throw new ApplicationException("at least one of the following attributes must be defined " +
909                                            "[destination,name]");
910                    if(destination!=null && !overwrite)
911                            throw new ApplicationException("destination file ["+destination+"] already exists");
912                    
913                    ArrayList docs = new ArrayList();
914                    PDFDocument doc;
915                    boolean isListing=false;
916                    
917                    // source
918                    if(source!=null) {
919                            if(Decision.isArray(source)) {
920                                    Array arr = Caster.toArray(source);
921                                    int len = arr.size();
922                                    for(int i=1;i<=len;i++) {
923                                            docs.add(doc=toPDFDocument(arr.getE(i),password,null));
924                                            doc.setPages(pages);
925                                    }
926                            }
927                            else if(source instanceof String) {
928                                    String[] sources = List.toStringArrayTrim(List.listToArrayRemoveEmpty((String)source, ','));
929                                    for(int i=0;i<sources.length;i++) {
930                                            docs.add(doc=toPDFDocument(sources[i],password,null));
931                                            doc.setPages(pages);
932                                    }
933                            }
934                            else docs.add(toPDFDocument(source,password,null));
935                            
936                    }
937                    boolean destIsSource = false;
938                    
939                    // params
940                    if(directory!=null && !directory.isDirectory()) {
941                            if(!directory.exists())
942                                    throw new ApplicationException("defined attribute directory does not exist");
943                            throw new ApplicationException("defined attribute directory is not a directory");
944                    }
945                    if(params!=null) {
946                            Iterator it = params.iterator();
947                            PDFParamBean param;
948                            while(it.hasNext()) {
949                                    param=(PDFParamBean) it.next();
950                                    docs.add(doc=toPDFDocument(param.getSource(), param.getPassword(),directory));
951                                    doc.setPages(param.getPages());
952                            }
953                    }
954                    else if(directory!=null) {
955                            isListing=true;
956                            Resource[] children = ResourceUtil.listResources(directory, filter);
957                            
958                            if(ascending) {
959                                    for(int i=children.length-1;i>=0;i--) {
960                                            if(destination!=null && children[i].equals(destination))        destIsSource=true;
961                                            docs.add(doc=toPDFDocument(children[i],password,null));
962                                            doc.setPages(pages);
963                                    }
964                            }
965                            else {
966                                    for(int i=0;i<children.length;i++) {
967                                            if(destination!=null && children[i].equals(destination))        destIsSource=true;
968                                            docs.add(doc=toPDFDocument(children[i],password,null));
969                                            doc.setPages(pages);
970                                    }
971                            }
972                            
973                    }
974                    
975                    int doclen=docs.size();
976                    if(doclen==0)
977                            throw new ApplicationException("you have to define at leat 1 pdf file");
978                    
979                    // output
980                    OutputStream os=null;
981                    if(!StringUtil.isEmpty(name) || destIsSource){
982                            os=new ByteArrayOutputStream();
983                    }
984                    else if(destination!=null) {
985                            os=destination.getOutputStream();
986                    }
987                    
988                    
989                    /*com.lowagie.text.Document document=null;
990                    PdfCopy copy=null;
991                    PdfReader pr;
992                    Set pages;
993                    int size;*/
994                    
995                    
996                    try {
997                            if(!isListing)stopOnError=true;
998                            PDFUtil.concat((PDFDocument[]) docs.toArray(new PDFDocument[docs.size()]), os, keepBookmark, false,stopOnError,version);
999                            /*
1000                            boolean init=false;
1001                            for(int d=0;d<doclen;d++) {
1002                                    doc=(PDFDocument) docs.get(d);
1003                                    pages=doc.getPages();
1004                                    try {
1005                                            pr=doc.getPdfReader();
1006                                            print.out(pr.getCatalog().getKeys());
1007                                            
1008                                    }
1009                                    catch(Throwable t) {
1010                                            if(isListing && !stopOnError)continue;
1011                                            throw Caster.toPageException(t);
1012                                    }
1013                                    print.out("d+"+d);
1014                                    if(!init) {
1015                                            init=true;
1016                                            print.out("set");
1017                                            document = new com.lowagie.text.Document(pr.getPageSizeWithRotation(1));
1018                                            copy = new PdfCopy(document,os);
1019                                            document.open();
1020                                    }
1021                                    size=pr.getNumberOfPages();
1022                                    print.out("pages:"+size);
1023                                    for(int page=1;page<=size;page++) {
1024                                            if(pages==null || pages.contains(Constants.Integer(page))) {
1025                                                    copy.addPage(copy.getImportedPage(pr, page));
1026                                            }
1027                                    }
1028                            }*/
1029                    }
1030                    finally {
1031                            //if(document!=null)document.close();
1032                            IOUtil.closeEL(os);
1033                            if(os instanceof ByteArrayOutputStream) {
1034                                    if(destination!=null)IOUtil.copy(new ByteArrayInputStream(((ByteArrayOutputStream)os).toByteArray()), destination,true);// MUST overwrite
1035                                    if(!StringUtil.isEmpty(name))pageContext.setVariable(name, ((ByteArrayOutputStream)os).toByteArray());
1036                            }
1037                            
1038                    }
1039                    
1040                    
1041            }
1042            private void doActionRead() throws PageException, IOException {
1043                    required("pdf", "read", "name", name,true);
1044                    required("pdf", "read", "source", source);
1045                    
1046                    pageContext.setVariable(name, toPDFDocument(source,password,null));
1047            }
1048            
1049            private void doActionProtect() throws PageException, IOException, DocumentException {
1050                    required("pdf", "protect", "source", source);
1051                    
1052                    if(StringUtil.isEmpty(newUserPassword) && StringUtil.isEmpty(newOwnerPassword))
1053                            throw new ApplicationException("at least one of the following attributes must be defined [newUserPassword,newOwnerPassword]");
1054            
1055                    
1056                    PDFDocument doc = toPDFDocument(source,password,null);
1057                    
1058                    if(destination==null){
1059                            destination=doc.getResource();
1060                            if(destination==null)
1061                                    throw new ApplicationException("source is not based on a resource, destination file is required");
1062                    }
1063                    else if(destination.exists() && !overwrite)
1064                            throw new ApplicationException("destination file ["+destination+"] already exists");
1065                    
1066                    boolean destIsSource = doc.getResource()!=null && destination.equals(doc.getResource());
1067                    
1068                    // output
1069                    OutputStream os=null;
1070                    if(destIsSource){
1071                            os=new ByteArrayOutputStream();
1072                    }
1073                    else {
1074                            os=destination.getOutputStream();
1075                    }
1076                    
1077                    
1078                    try{
1079                            PDFUtil.encrypt(doc,os,newUserPassword,newOwnerPassword,permissions,encrypt);
1080                    }
1081                    finally {
1082                            IOUtil.closeEL(os);
1083                            if(os instanceof ByteArrayOutputStream) {
1084                                    IOUtil.copy(new ByteArrayInputStream(((ByteArrayOutputStream)os).toByteArray()), destination,true);// MUST overwrite
1085                            }
1086                            
1087                    }
1088                    
1089            }
1090            
1091    
1092            
1093    
1094            private void doActionSetInfo() throws PageException, IOException, DocumentException {
1095                    required("pdf", "setInfo", "info", info);
1096                    required("pdf", "getInfo", "source", source);
1097                    
1098                    PDFDocument doc = toPDFDocument(source,password,null);
1099                    PdfReader pr = doc.getPdfReader();
1100                    OutputStream os=null;
1101                    try {
1102                            if(destination==null){
1103                                    if(doc.getResource()==null)
1104                                            throw new ApplicationException("source is not based on a resource, destination file is required");
1105                                    destination=doc.getResource();
1106                            }
1107                            else if(destination.exists() && !overwrite)
1108                                    throw new ApplicationException("destination file ["+destination+"] already exists");
1109                            
1110                            PdfStamper stamp = new PdfStamper(pr, os=destination.getOutputStream());
1111                            HashMap moreInfo = new HashMap();
1112                
1113                            Key[] keys = info.keys();
1114                            for(int i=0;i<keys.length;i++) {
1115                                    moreInfo.put(StringUtil.ucFirst(keys[i].getLowerString()), Caster.toString(info.get(keys[i])));
1116                            }
1117                            // author
1118                            Object value = info.get("author", null);        
1119                            if(value!=null)moreInfo.put("Author", Caster.toString(value));
1120                            // keywords
1121                            value = info.get("keywords", null);     
1122                            if(value!=null)moreInfo.put("Keywords", Caster.toString(value));
1123                            // title
1124                            value = info.get("title", null);        
1125                            if(value!=null)moreInfo.put("Title", Caster.toString(value));
1126                            // subject
1127                            value = info.get("subject", null);      
1128                            if(value!=null)moreInfo.put("Subject", Caster.toString(value));
1129                            // creator
1130                            value = info.get("creator", null);      
1131                            if(value!=null)moreInfo.put("Creator", Caster.toString(value));
1132                            // trapped
1133                            value = info.get("Trapped", null);      
1134                            if(value!=null)moreInfo.put("Trapped", Caster.toString(value));
1135                            // Created
1136                            value = info.get("Created", null);      
1137                            if(value!=null)moreInfo.put("Created", Caster.toString(value));
1138                            // Language
1139                            value = info.get("Language", null);     
1140                            if(value!=null)moreInfo.put("Language", Caster.toString(value));
1141                            
1142                            
1143                            stamp.setMoreInfo(moreInfo);
1144                            stamp.close();
1145                            
1146                    }
1147                    finally {
1148                            IOUtil.closeEL(os);
1149                            pr.close();
1150                    }
1151            }
1152            
1153    
1154            private void doActionGetInfo() throws PageException, IOException {
1155                    required("pdf", "getInfo", "name", name,true);
1156                    required("pdf", "getInfo", "source", source);
1157                    
1158                    PDFDocument doc = toPDFDocument(source,password,null);
1159                    pageContext.setVariable(name, doc.getInfo());
1160                    
1161            }
1162            private void doActionExtractText() throws PageException, IOException, CryptographyException, InvalidPasswordException {
1163                    required("pdf", "extractText", "name", name,true);
1164                    
1165                    PDFDocument doc = toPDFDocument(source,password,null);
1166                    doc.setPages(pages);
1167                    
1168                    pageContext.setVariable(name, PDFUtil.extractText(doc,doc.getPages()));
1169                    /*
1170                     <cfpdf 
1171     required 
1172        action="extracttext" <!---extract all the words in the PDF.---> 
1173        ***source= "absolute or relative path of the PDF file|PDF document variable| 
1174                cfdocument variable" 
1175        pages = "*" <!----page numbers from where the text needs to be extracted from the 
1176                    PDF document---> 
1177    
1178    optional 
1179        addquads = "add the position or quadrants for the text in the PDF" 
1180        honourspaces = "true|false" 
1181        overwrite = "true" <!---Overwrite the specified object in the PDF document---> 
1182        ***password = "" <!--- PDF document password---> 
1183        type = "string|xml" <!---format in which the text needs to be extracted---> 
1184        one of the following: 
1185        destination = "PDF output file pathname" 
1186        name = "PDF document variable" 
1187        usestructure = "true|false" 
1188                     * */
1189            }
1190            
1191            private Object allowed(boolean encrypted, int permissions, int permission) {
1192                    return (!encrypted || (permissions&permission)>0)?"Allowed":"Not Allowed";
1193            }
1194            
1195    
1196            private PDFDocument toPDFDocument(Object source,String password, Resource directory) throws PageException, IOException {
1197                    
1198                    if(source instanceof PDFDocument) 
1199                            return (PDFDocument)source;
1200                    if(Decision.isBinary(source)){
1201                            return new PDFDocument(Caster.toBinary(source),password);
1202                    }
1203                    if(source instanceof Resource){ 
1204                            return new PDFDocument((Resource) source,password);
1205                    }
1206                    if(source instanceof String){
1207                            if(directory!=null) {
1208                                    Resource res = directory.getRealResource((String)source);
1209                                    if(!res.isFile()){
1210                                            Resource res2 = ResourceUtil.toResourceNotExisting(pageContext, (String)source);
1211                                            if(res2.isFile())
1212                                                    res=res2;
1213                                            else 
1214                                                    throw new ExpressionException("file or directory "+res+" not exist");
1215                                    }
1216                                    return new PDFDocument(res,password);   
1217                            }
1218                            return new PDFDocument(ResourceUtil.toResourceExisting(pageContext, (String)source),password);  
1219                    }
1220                    
1221                    throw new CasterException(source,PdfReader.class);
1222            }
1223            
1224            /*private byte[] toBinary(Object source) throws ExpressionException, IOException {
1225                    
1226                    if(source instanceof PDFDocument) 
1227                            return toBinary(((PDFDocument)source).getResource());
1228                    if(Decision.isBinary(source)){
1229                            return Caster.toBinary(source);
1230                    }
1231                    if(source instanceof Resource){ 
1232                            return IOUtil.toBytes((Resource)source);
1233                    }
1234                    if(source instanceof String){
1235                            if(directory!=null) {
1236                                    Resource res = directory.getRealResource((String)source);
1237                                    if(!res.isFile()){
1238                                            Resource res2 = ResourceUtil.toResourceNotExisting(pageContext, (String)source);
1239                                            if(res2.isFile())
1240                                                    res=res2;
1241                                            else 
1242                                                    throw new ExpressionException("file or directory "+res+" not exist");
1243                                    }
1244                                    return IOUtil.toBytes(res);     
1245                            }
1246                            return IOUtil.toBytes(ResourceUtil.toResourceExisting(pageContext, (String)source));    
1247                    }
1248                    
1249                    throw new CasterException(source,PdfReader.class);
1250            }*/
1251            
1252            protected void setParam(PDFParamBean param) {
1253                    if(params==null)
1254                            params=new ArrayList<PDFParamBean>();
1255                    params.add(param);
1256            }
1257            
1258            
1259            
1260    
1261    }