001    package railo.runtime.reflection.storage;
002    
003    import java.lang.reflect.Method;
004    import java.util.Map;
005    
006    import org.apache.commons.collections.map.ReferenceMap;
007    
008    import railo.runtime.type.Array;
009    import railo.runtime.type.ArrayImpl;
010    import railo.runtime.type.Collection;
011    import railo.runtime.type.Collection.Key;
012    import railo.runtime.type.KeyImpl;
013    import railo.runtime.type.Struct;
014    import railo.runtime.type.StructImpl;
015    
016    /**
017     * Method Storage Class
018     */
019    public final class WeakMethodStorage {
020            private Map<Class,Struct> map=new ReferenceMap(ReferenceMap.SOFT,ReferenceMap.SOFT);
021            
022            /**
023             * returns a methods matching given criteria or null if method doesn't exist
024             * @param clazz clazz to get methods from
025             * @param methodName Name of the Method to get
026             * @param count wished count of arguments
027             * @return matching Methods as Array
028             */
029            public synchronized Method[] getMethods(Class clazz,Collection.Key methodName, int count) {
030                    Struct methodsMap = map.get(clazz); 
031                    if(methodsMap==null) 
032                            methodsMap=store(clazz);
033                    
034                    Object o = methodsMap.get(methodName,null);
035                    if(o==null) return null;
036                    Array methods=(Array) o;
037                    o=methods.get(count+1,null);
038                    if(o==null) return null;
039                    return (Method[]) o;
040            }
041    
042    
043            /**
044             * store a class with his methods
045             * @param clazz
046             * @return returns stored struct
047             */
048            private StructImpl store(Class clazz) {
049                    Method[] methodsArr=clazz.getMethods();
050                    StructImpl methodsMap=new StructImpl();
051                    for(int i=0;i<methodsArr.length;i++) {
052                            storeMethod(methodsArr[i],methodsMap);
053                            
054                    }
055                    map.put(clazz,methodsMap);
056                    return methodsMap;
057            }
058    
059            /**
060             * stores a single method
061             * @param method
062             * @param methodsMap
063             */
064            private void storeMethod(Method method, StructImpl methodsMap) {
065                    Key methodName = KeyImpl.init(method.getName());
066                    
067                    
068                    Object o=methodsMap.get(methodName,null);
069                    Array methodArgs;
070                    if(o==null) {
071                            methodArgs=new ArrayImpl();
072                            methodsMap.setEL(methodName,methodArgs);
073                    }
074                    else methodArgs=(Array) o;
075                    storeArgs(method,methodArgs);
076                    //Modifier.isStatic(method.getModifiers());
077            }
078    
079            /**
080             * stores arguments of a method
081             * @param method
082             * @param methodArgs
083             */
084            private void storeArgs(Method method, Array methodArgs) {
085                    
086                    Class[] pmt = method.getParameterTypes();
087                    Object o=methodArgs.get(pmt.length+1,null);
088                    Method[] args;
089                    if(o==null) {
090                            args=new Method[1];
091                            methodArgs.setEL(pmt.length+1,args);
092                    }
093                    else {
094                            Method[] ms = (Method[]) o;
095                            args = new Method[ms.length+1];
096                            for(int i=0;i<ms.length;i++) {
097                                    args[i]=ms[i];
098                            }
099                            methodArgs.setEL(pmt.length+1,args);
100                    }
101                    args[args.length-1]=method;
102            }
103    }