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.Field;
022import java.util.WeakHashMap;
023
024import lucee.runtime.type.Struct;
025import lucee.runtime.type.StructImpl;
026
027import org.apache.commons.collections.map.ReferenceMap;
028
029/**
030 * Method Storage Class
031 */
032public final class WeakFieldStorage {
033        private WeakHashMap map=new WeakHashMap(ReferenceMap.SOFT,ReferenceMap.SOFT);
034        
035        /**
036         * returns all fields matching given criteria or null if field does exist
037         * @param clazz clazz to get field from
038         * @param fieldname Name of the Field to get
039         * @return matching Fields as Array
040         */
041        public synchronized Field[] getFields(Class clazz,String fieldname) {
042                Object o=map.get(clazz);
043                Struct fieldMap;
044                if(o==null) {
045                        fieldMap=store(clazz);
046                }
047                else fieldMap=(Struct) o;
048                
049                o=fieldMap.get(fieldname,null);
050                if(o==null) return null;
051                return (Field[]) o;
052                
053        }
054
055
056        /**
057         * store a class with his methods
058         * @param clazz
059         * @return returns stored Struct
060         */
061        private StructImpl store(Class clazz) {
062                Field[] fieldsArr=clazz.getFields();
063                StructImpl fieldsMap=new StructImpl();
064                for(int i=0;i<fieldsArr.length;i++) {
065                        storeField(fieldsArr[i],fieldsMap);
066                }
067                map.put(clazz,fieldsMap);
068                return fieldsMap;
069        }
070
071        /**
072         * stores a single method
073         * @param field
074         * @param fieldsMap
075         */
076        private void storeField(Field field, StructImpl fieldsMap) {
077                String fieldName=field.getName();
078                Object o=fieldsMap.get(fieldName,null);         
079                Field[] args;
080                if(o==null) {
081                        args=new Field[1];
082                        fieldsMap.setEL(fieldName,args);
083                }
084                else {
085                        Field[] fs = (Field[]) o;
086                        args = new Field[fs.length+1];
087                        for(int i=0;i<fs.length;i++) {
088                            fs[i].setAccessible(true);
089                                args[i]=fs[i];
090                        }
091                        fieldsMap.setEL(fieldName,args);
092                }
093                args[args.length-1]=field;
094        }
095
096}