001    package railo.transformer.cfml.evaluator.impl;
002    
003    import java.io.ByteArrayInputStream;
004    import java.io.ByteArrayOutputStream;
005    import java.io.IOException;
006    import java.util.zip.ZipEntry;
007    import java.util.zip.ZipInputStream;
008    
009    import railo.commons.io.IOUtil;
010    import railo.commons.io.res.Resource;
011    import railo.commons.io.res.util.ResourceUtil;
012    import railo.commons.lang.Md5;
013    import railo.commons.lang.StringUtil;
014    import railo.commons.lang.SystemOut;
015    import railo.loader.util.Util;
016    import railo.runtime.PageSource;
017    import railo.runtime.config.Config;
018    import railo.runtime.config.ConfigImpl;
019    import railo.runtime.config.ConfigWebUtil;
020    import railo.runtime.exp.TemplateException;
021    import railo.transformer.bytecode.statement.tag.Attribute;
022    import railo.transformer.bytecode.statement.tag.Tag;
023    import railo.transformer.bytecode.statement.tag.TagImport;
024    import railo.transformer.bytecode.util.ASMUtil;
025    import railo.transformer.cfml.evaluator.EvaluatorException;
026    import railo.transformer.cfml.evaluator.EvaluatorSupport;
027    import railo.transformer.library.function.FunctionLib;
028    import railo.transformer.library.tag.CustomTagLib;
029    import railo.transformer.library.tag.TagLib;
030    import railo.transformer.library.tag.TagLibException;
031    import railo.transformer.library.tag.TagLibFactory;
032    import railo.transformer.library.tag.TagLibTag;
033    import railo.transformer.util.CFMLString;
034    
035    
036    /**
037     * 
038     */
039    public final class Import extends EvaluatorSupport {
040            
041            public void evaluate(Tag tag,TagLibTag libTag) throws EvaluatorException {
042            }
043            
044        
045            //�
046        /**
047         * @see railo.transformer.cfml.evaluator.Evaluator#execute(railo.runtime.config.Config, org.w3c.dom.Element, railo.transformer.library.tag.TagLibTag, railo.transformer.library.function.FunctionLib[], railo.transformer.util.CFMLString)
048         */
049            public TagLib execute(Config config,Tag tag, TagLibTag libTag, FunctionLib[] flibs,CFMLString cfml) throws TemplateException { 
050                    TagImport ti=(TagImport) tag;
051                    Attribute p = tag.getAttribute("prefix");
052                    Attribute t = tag.getAttribute("taglib");
053                    Attribute path = tag.getAttribute("path");
054                    
055                    if(p!=null || t!=null){
056                            if(p==null)
057                                    throw new TemplateException(cfml,"Wrong Context, missing attribute [prefix] for tag "+tag.getFullname());
058                            if(t==null)
059                                    throw new TemplateException(cfml,"Wrong Context, missing attribute [taglib] for tag "+tag.getFullname());
060                            
061                            if(path!=null)
062                                    throw new TemplateException(cfml,"Wrong context, you have an invalid attributes constellation for the tag "+tag.getFullname()+", " +
063                                                    "you cannot mix attribute [path] with attributes [taglib] and [prefix]");
064                            
065                            return executePT(config, tag, libTag, flibs, cfml);
066                    }
067                    if(path==null) throw new TemplateException(cfml,"Wrong context, you have an invalid attributes constellation for the tag "+tag.getFullname()+", " +
068                                    "you need to define the attributes [prefix] and [taglib], the attribute [path] or simply define a attribute value");
069                    
070                    String strPath=ASMUtil.getAttributeString(tag,"path",null);
071            if(strPath==null) throw new TemplateException(cfml,"attribute [path] must be a constant value");
072            ti.setPath(strPath);
073            
074                    return null;
075                    
076            }
077            
078        private TagLib executePT(Config config,Tag tag, TagLibTag libTag, FunctionLib[] flibs,CFMLString cfml) throws TemplateException { 
079            
080            // Attribute prefix 
081            String nameSpace=ASMUtil.getAttributeString(tag,"prefix",null);
082            if(nameSpace==null) throw new TemplateException(cfml,"attribute [prefix] must be a constant value");
083            nameSpace=nameSpace.trim();
084            String nameSpaceSeparator=StringUtil.isEmpty(nameSpace)?"":":";
085            
086            
087            // Attribute taglib  
088            String textTagLib=ASMUtil.getAttributeString(tag,"taglib",null);
089            if(textTagLib==null) throw new TemplateException(cfml,"attribute [taglib] must be a constant value");
090            
091            textTagLib=textTagLib.replace('\\','/');
092            textTagLib=ConfigWebUtil.replacePlaceholder(textTagLib, config);
093            // File TagLib
094            String ext=ResourceUtil.getExtension(textTagLib,null);
095            boolean hasTldExtension="tld".equalsIgnoreCase(ext);
096            
097            Resource absFile=config.getResource(textTagLib);
098                // TLD
099                    if(absFile.isFile()) return _executeTLD(config,absFile,nameSpace,nameSpaceSeparator,cfml);
100                    // CTD
101                    //else if(absFile.isDirectory()) return _executeCTD(absFile,textPrefix);
102                    
103            
104                    // Second Change            
105                    if(textTagLib.startsWith("/")){
106                //config.getPhysical(textTagLib);
107                        PageSource ps = ((ConfigImpl)config).getPageSourceExisting(null,null,textTagLib,false,false,true,false);
108                        
109                        //config.getConfigDir()
110                        if(ps!=null) {
111                            if(ps.physcalExists()) {
112                                    Resource file = ps.getPhyscalFile();
113                                            // TLD
114                                    if(file.isFile()) return _executeTLD(config,file,nameSpace,nameSpaceSeparator,cfml);
115                            }
116                                    // CTD
117                                    if(!hasTldExtension)return _executeCTD(textTagLib,nameSpace,nameSpaceSeparator);
118                        }
119                    }
120                    else {
121                            Resource sourceFile=cfml.getSourceFile().getPhyscalFile();
122                        if(sourceFile!=null) {
123                            Resource file = sourceFile.getParentResource().getRealResource(textTagLib);
124                                    // TLD
125                            if(file.isFile()) return _executeTLD(config,file,nameSpace,nameSpaceSeparator,cfml);
126                                    // CTD
127                            if(!hasTldExtension)return _executeCTD(textTagLib,nameSpace,nameSpaceSeparator);
128                        }
129                    }
130                throw new TemplateException(cfml,"invalid definition of the attribute taglib ["+textTagLib+"]"); 
131        }
132    
133        /**
134         * @param fileTagLib
135         * @return
136         * @throws EvaluatorException
137         */
138        private TagLib _executeTLD(Config config, Resource fileTagLib,String nameSpace,String nameSpaceSeparator, CFMLString cfml) throws TemplateException {
139            // change extesnion
140            String ext=ResourceUtil.getExtension(fileTagLib,null);
141            if("jar".equalsIgnoreCase(ext)) {
142                // check anchestor file
143                    Resource newFileTagLib = ResourceUtil.changeExtension(fileTagLib,"tld");
144                if(newFileTagLib.exists())fileTagLib=newFileTagLib;
145                // check inside jar
146                else {
147                    Resource tmp = getTLDFromJarAsFile(config,fileTagLib);
148                    if(tmp!=null)fileTagLib=tmp;
149                }
150            }
151            
152            try {
153                    
154                TagLib taglib = TagLibFactory.loadFromFile(fileTagLib);
155                taglib.setNameSpace(nameSpace);
156                taglib.setNameSpaceSeperator(nameSpaceSeparator);
157                return taglib;
158            } 
159            catch (TagLibException e) {
160                    
161                throw new TemplateException(cfml,e.getMessage());
162            }
163        }
164        
165        private Resource getTLDFromJarAsFile(Config config, Resource jarFile) {
166            Resource jspTagLibDir = config.getTempDirectory().getRealResource("jsp-taglib");
167            if(!jspTagLibDir.exists())jspTagLibDir.mkdirs();
168            
169            String filename=null;
170            try {
171                            filename=Md5.getDigestAsString(ResourceUtil.getCanonicalPathEL(jarFile)+jarFile.lastModified());
172                    } catch (IOException e) {}
173            
174                    Resource tldFile = jspTagLibDir.getRealResource(filename+".tld");
175            if(tldFile.exists() ) return tldFile;
176            
177            
178            byte[] barr = getTLDFromJarAsBarr(config,jarFile);
179            if(barr==null)return null;
180            
181            try {
182                            IOUtil.copy(new ByteArrayInputStream(barr), tldFile,true);
183                    } 
184            catch (IOException e) {}
185            return tldFile;
186        }
187            
188        
189        private byte[] getTLDFromJarAsBarr(Config c,Resource jarFile) {  
190            ZipInputStream zis = null;
191            try {
192                zis = new ZipInputStream(IOUtil.toBufferedInputStream(jarFile.getInputStream()));
193                
194                byte[] buffer = new byte[0xffff];
195                int bytes_read;
196              
197                ZipEntry ze;
198                byte[] barr;
199                while((ze = zis.getNextEntry()) != null) {
200                    if (!ze.isDirectory() && StringUtil.endsWithIgnoreCase(ze.getName(),".tld")) {
201                        SystemOut.printDate(c.getOutWriter(),"found tld in file ["+jarFile+"] at position "+ze.getName());
202                        ByteArrayOutputStream baos=new ByteArrayOutputStream();
203                        while((bytes_read = zis.read(buffer)) != -1)
204                            baos.write(buffer, 0, bytes_read);
205                        //String name = ze.getName().replace('\\', '/');
206                        barr=baos.toByteArray();
207                        zis.closeEntry();
208                        baos.close();
209                        return barr;
210                    }
211                }
212            }
213            catch (IOException ioe) {}
214            finally {
215                Util.closeEL(zis);
216            }   
217            return null;
218        }
219        
220        
221        /**
222         * @param textTagLib
223         * @param nameSpace
224         * @return
225         */
226        private TagLib _executeCTD(String textTagLib, String nameSpace, String nameSpaceSeparator) {
227            return new CustomTagLib(textTagLib,nameSpace,nameSpaceSeparator);
228        }
229      
230    }