001    package railo.runtime.tag;
002    
003    import java.io.OutputStream;
004    import java.util.Iterator;
005    import java.util.Map;
006    import java.util.Map.Entry;
007    
008    import javax.servlet.http.Cookie;
009    import javax.servlet.jsp.tagext.Tag;
010    
011    import railo.commons.io.DevNullOutputStream;
012    import railo.commons.lang.Pair;
013    import railo.commons.lang.StringUtil;
014    import railo.runtime.Component;
015    import railo.runtime.ComponentImpl;
016    import railo.runtime.ComponentWrap;
017    import railo.runtime.Page;
018    import railo.runtime.PageContext;
019    import railo.runtime.PageContextImpl;
020    import railo.runtime.PageSource;
021    import railo.runtime.component.ComponentLoader;
022    import railo.runtime.config.ConfigWeb;
023    import railo.runtime.config.ConfigWebImpl;
024    import railo.runtime.engine.ThreadLocalPageContext;
025    import railo.runtime.exp.ApplicationException;
026    import railo.runtime.exp.PageException;
027    import railo.runtime.ext.tag.DynamicAttributes;
028    import railo.runtime.op.Caster;
029    import railo.runtime.reflection.Reflector;
030    import railo.runtime.reflection.pairs.MethodInstance;
031    import railo.runtime.thread.ThreadUtil;
032    import railo.runtime.type.Collection;
033    import railo.runtime.type.Collection.Key;
034    import railo.runtime.type.KeyImpl;
035    import railo.runtime.type.Struct;
036    import railo.runtime.type.StructImpl;
037    import railo.runtime.type.UDFImpl;
038    import railo.runtime.type.util.ArrayUtil;
039    import railo.runtime.type.util.KeyConstants;
040    import railo.transformer.library.tag.TagLib;
041    import railo.transformer.library.tag.TagLibTag;
042    import railo.transformer.library.tag.TagLibTagAttr;
043    
044    public class TagUtil {
045            
046            public static final short ORIGINAL_CASE = 0;
047            public static final short UPPER_CASE = 1;
048            public static final short LOWER_CASE = 2;
049    
050            //private static final String "invalid call of the function ["+tlt.getName()+", you can not mix named on regular arguments]" = "invalid argument for function, only named arguments are allowed like struct(name:\"value\",name2:\"value2\")";
051    
052            public static void setAttributeCollection(PageContext pc,Tag tag, MissingAttribute[] missingAttrs, Struct attrs, int attrType) throws PageException {
053                    // check missing tags
054                    if(!ArrayUtil.isEmpty(missingAttrs)){
055                            Object value;
056                            for(int i=0;i<missingAttrs.length;i++) {
057                                    value=attrs.get(
058                                                    missingAttrs[i].getName()
059                                                    ,null);
060                                    if(value==null)
061                                            throw new ApplicationException("attribute "+missingAttrs[i].getName().getString()+" is required but missing");
062                                            //throw new ApplicationException("attribute "+missingAttrs[i].getName().getString()+" is required for tag "+tag.getFullName());
063                                    attrs.put(missingAttrs[i].getName(), Caster.castTo(pc, missingAttrs[i].getType(), value, false));
064                            }
065                    }
066                    
067                    
068                    //Key[] keys = attrs.keys();
069                    Iterator<Entry<Key, Object>> it;
070                    Entry<Key, Object> e;
071                    if(TagLibTag.ATTRIBUTE_TYPE_DYNAMIC==attrType) {
072                            DynamicAttributes da=(DynamicAttributes) tag;
073                            it = attrs.entryIterator();
074                            while(it.hasNext()) {
075                                    e = it.next();
076                                    da.setDynamicAttribute(null, e.getKey(),e.getValue());
077                            }
078                    }
079                    else if(TagLibTag.ATTRIBUTE_TYPE_FIXED==attrType) {
080                            Object value;
081                            it = attrs.entryIterator();
082                            while(it.hasNext()) {
083                                    e = it.next();
084                                    value=e.getValue();
085                                    if(value!=null)Reflector.callSetterEL(tag, e.getKey().getString(),value);
086                                    //}catch(PageException pe){}
087                            }       
088                    }
089                    else if(TagLibTag.ATTRIBUTE_TYPE_MIXED==attrType) {
090                            MethodInstance setter;
091                            it = attrs.entryIterator();
092                            while(it.hasNext()) {
093                                    e = it.next();
094                                    setter = Reflector.getSetter(tag, e.getKey().getString(),e.getValue(),null);
095                                    if(setter!=null) {
096                                            try {
097                                                    setter.invoke(tag);
098                                            } 
099                                            catch (Exception _e) {
100                                                    throw Caster.toPageException(_e);
101                                            }
102                                    }
103                                    else {
104                                            DynamicAttributes da=(DynamicAttributes) tag;
105                                            da.setDynamicAttribute(null, e.getKey(),e.getValue());
106                                    }
107                            }
108                    }
109            }
110    
111            /* *
112             * sets dynamic attributes
113             * @param attributes
114             * @param name
115             * @param value
116             * /
117            public static void setDynamicAttribute(StructImpl attributes,String name, Object value, short caseType) {
118                    if(LOWER_CASE==caseType)name=StringUtil.toLowerCase(name);
119                    else if(UPPER_CASE==caseType)name=StringUtil.toUpperCase(name);
120            if(name.equals("attributecollection")) {
121                if(value instanceof railo.runtime.type.Collection) {
122                    railo.runtime.type.Collection coll=(railo.runtime.type.Collection)value;
123                    Iterator<Entry<Key, Object>> it = coll.entryIterator();
124                    Entry<Key, Object> e;
125                    while(it.hasNext()) {
126                            e = it.next();
127                        if(attributes.get(e.getKey(),null)==null)
128                            attributes.setEL(e.getKey(),e.getValue());
129                    }
130                    return;
131                }
132                else if(value instanceof Map) {
133                    
134                    Map map=(Map) value;
135                                Iterator it = map.entrySet().iterator();
136                                Map.Entry entry;
137                                Key key;
138                                while(it.hasNext()) {
139                                    entry=(Entry) it.next();
140                                    key = UDFImpl.toKey(entry.getKey());
141                                    if(!attributes.containsKey(key)){
142                                            attributes.setEL(key,entry.getValue());
143                            }
144                        }
145                    return;
146                }
147            }
148            attributes.setEL(KeyImpl.getInstance(name), value);
149            }*/
150            
151    
152            public static void setDynamicAttribute(StructImpl attributes,Collection.Key name, Object value, short caseType) {
153                    if(name.equalsIgnoreCase(KeyConstants._attributecollection)) {
154                if(value instanceof railo.runtime.type.Collection) {
155                    railo.runtime.type.Collection coll=(railo.runtime.type.Collection)value;
156                    Iterator<Entry<Key, Object>> it = coll.entryIterator();
157                    Entry<Key, Object> e;
158                    while(it.hasNext()) {
159                            e = it.next();
160                        if(attributes.get(e.getKey(),null)==null)
161                            attributes.setEL(e.getKey(),e.getValue());
162                    }
163                    return;
164                }
165                else if(value instanceof Map) {
166                    
167                    Map map=(Map) value;
168                                Iterator it = map.entrySet().iterator();
169                                Map.Entry entry;
170                                Key key;
171                                while(it.hasNext()) {
172                                    entry=(Entry) it.next();
173                                    key = UDFImpl.toKey(entry.getKey());
174                                    if(!attributes.containsKey(key)){
175                                            attributes.setEL(key,entry.getValue());
176                            }
177                        }
178                    return;
179                }
180            }
181                    if(LOWER_CASE==caseType)name=KeyImpl.init(name.getLowerString());
182                    else if(UPPER_CASE==caseType)name=KeyImpl.init(name.getUpperString());
183            attributes.setEL(name, value);
184            }
185    
186            /**
187         * load metadata from cfc based custom tags and add the info to the tag
188         * @param cs
189         * @param config
190         */
191        public static void addTagMetaData(ConfigWebImpl cw) {
192            if(true) return;
193            
194            PageContextImpl pc=null;
195            try{
196                    pc = ThreadUtil.createPageContext(cw, DevNullOutputStream.DEV_NULL_OUTPUT_STREAM, 
197                                    "localhost", "/","", new Cookie[0], new Pair[0], new Pair[0], new StructImpl());
198                    
199            }
200            catch(Throwable t){
201                    return;
202            }
203            PageContext orgPC = ThreadLocalPageContext.get();
204            ThreadLocalPageContext.register(pc);
205            try{
206                    TagLibTagAttr attrFileName,attrIsWeb;
207                    String filename;
208                    Boolean isWeb;
209                    TagLibTag tlt;
210                    
211                    TagLib[] tlds = cw.getTLDs();
212                    for(int i=0;i<tlds.length;i++){
213                            Map<String, TagLibTag> tags = tlds[i].getTags();
214                            Iterator<TagLibTag> it = tags.values().iterator();
215                            while(it.hasNext()){
216                                    tlt = it.next();
217                                    if("railo.runtime.tag.CFTagCore".equals(tlt.getTagClassName())) {
218                                            attrFileName = tlt.getAttribute("__filename");
219                                            attrIsWeb = tlt.getAttribute("__isweb");
220                                            if(attrFileName!=null && attrIsWeb!=null) {
221                                                    filename = Caster.toString(attrFileName.getDefaultValue(),null);
222                                                    isWeb=Caster.toBoolean(attrIsWeb.getDefaultValue(),null);
223                                                    if(filename!=null && isWeb!=null) {
224                                                            addTagMetaData(pc, tlds[i], tlt, filename,isWeb.booleanValue());
225                                                    }
226                                            }
227                                    }
228                            }
229                    }
230            }
231            catch(Throwable t){
232                    //t.printStackTrace();
233            }
234            finally{
235                    pc.release();
236                    ThreadLocalPageContext.register(orgPC);
237            }
238            }
239    
240            private static void addTagMetaData(PageContext pc,TagLib tl, TagLibTag tlt, String filename, boolean isWeb) {
241            if(pc==null) return;
242                    try{
243                            ConfigWebImpl config=(ConfigWebImpl) pc.getConfig();
244                            PageSource ps = isWeb?
245                                            config.getTagMapping().getPageSource(filename):
246                                            config.getServerTagMapping().getPageSource(filename);
247                            
248                            Page p = ps.loadPage(pc);
249                            ComponentImpl c = ComponentLoader.loadComponent(pc, p, ps, filename, true,true);
250                            ComponentWrap cw = ComponentWrap.toComponentWrap(Component.ACCESS_PRIVATE,c);
251                            Struct meta = Caster.toStruct( cw.get(KeyConstants._metadata,null),null);
252    
253                            // TODO handle all metadata here and make checking at runtime useless
254                            if(meta!=null) {
255                                    
256                                    // parse body
257                                    boolean rtexprvalue=Caster.toBooleanValue(meta.get(KeyConstants._parsebody,Boolean.FALSE),false);
258                            tlt.setParseBody(rtexprvalue);
259                            
260                            // hint
261                            String hint=Caster.toString(meta.get(KeyConstants._hint,null),null);
262                            if(!StringUtil.isEmpty(hint))tlt.setDescription(hint);
263                            
264                            }
265                            
266                    } 
267                    catch (Throwable t) {
268                            //t.printStackTrace();
269                    }
270        }
271            
272    }