001/**
002 *
003 * Copyright (c) 2014, the Railo Company Ltd. All rights reserved.
004 *
005 * This library is free software; you can redistribute it and/or
006 * modify it under the terms of the GNU Lesser General Public
007 * License as published by the Free Software Foundation; either 
008 * version 2.1 of the License, or (at your option) any later version.
009 * 
010 * This library is distributed in the hope that it will be useful,
011 * but WITHOUT ANY WARRANTY; without even the implied warranty of
012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
013 * Lesser General Public License for more details.
014 * 
015 * You should have received a copy of the GNU Lesser General Public 
016 * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
017 * 
018 **/
019package lucee.runtime.reflection.storage;
020
021import java.lang.reflect.Constructor;
022import java.util.WeakHashMap;
023
024import lucee.runtime.type.Array;
025import lucee.runtime.type.ArrayImpl;
026
027import org.apache.commons.collections.map.ReferenceMap;
028
029/**
030 * Constructor Storage Class
031 */
032public final class WeakConstructorStorage {
033        private WeakHashMap map=new WeakHashMap(ReferenceMap.SOFT,ReferenceMap.SOFT);
034        
035        /**
036         * returns a constructor matching given criteria or null if Constructor doesn't exist
037         * @param clazz Class to get Constructor for
038         * @param count count of arguments for the constructor
039         * @return returns the constructors
040         */
041        public synchronized Constructor[] getConstructors(Class clazz,int count) {
042                Object o=map.get(clazz);
043                Array con;
044                if(o==null) {
045                        con=store(clazz);
046                }
047                else con=(Array) o;
048
049                o=con.get(count+1,null);
050                if(o==null) return null;
051                return (Constructor[]) o;
052        }
053
054        /**
055         * stores the constructors for a Class
056         * @param clazz 
057         * @return stored structure
058         */
059        private Array store(Class clazz) {
060                        Constructor[] conArr=clazz.getConstructors();
061                        Array args=new ArrayImpl();
062                        for(int i=0;i<conArr.length;i++) {
063                                storeArgs(conArr[i],args);
064                        }
065                        map.put(clazz,args);
066                        return args;
067                
068        }
069
070        /**
071         * seperate and store the different arguments of one constructor
072         * @param constructor
073         * @param conArgs
074         */
075        private void storeArgs(Constructor constructor, Array conArgs) {
076                Class[] pmt = constructor.getParameterTypes();
077                Object o=conArgs.get(pmt.length+1,null);
078                Constructor[] args;
079                if(o==null) {
080                        args=new Constructor[1];
081                        conArgs.setEL(pmt.length+1,args);
082                }
083                else {
084                        Constructor[] cs=(Constructor[]) o;
085                        args = new Constructor[cs.length+1];
086                        for(int i=0;i<cs.length;i++) {
087                                args[i]=cs[i];
088                        }
089                        conArgs.setEL(pmt.length+1,args);
090                }
091                args[args.length-1]=constructor;
092                
093        }
094}