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.Method; 022import java.util.Map; 023import java.util.concurrent.ConcurrentHashMap; 024 025import lucee.runtime.type.Array; 026import lucee.runtime.type.ArrayImpl; 027import lucee.runtime.type.Collection; 028import lucee.runtime.type.Collection.Key; 029import lucee.runtime.type.KeyImpl; 030 031import org.apache.commons.collections.map.ReferenceMap; 032 033/** 034 * Method Storage Class 035 */ 036public final class SoftMethodStorage { 037 private Map<Class,Map<Key,Array>> map=new ReferenceMap(ReferenceMap.SOFT,ReferenceMap.SOFT); 038 039 /** 040 * returns a methods matching given criteria or null if method doesn't exist 041 * @param clazz clazz to get methods from 042 * @param methodName Name of the Method to get 043 * @param count wished count of arguments 044 * @return matching Methods as Array 045 */ 046 public Method[] getMethods(Class clazz,Collection.Key methodName, int count) { 047 Map<Key,Array> methodsMap = map.get(clazz); 048 if(methodsMap==null) 049 methodsMap=store(clazz); 050 051 Array methods = methodsMap.get(methodName); 052 if(methods==null) return null; 053 054 Object o = methods.get(count+1,null); 055 if(o==null) return null; 056 return (Method[]) o; 057 } 058 059 060 /** 061 * store a class with his methods 062 * @param clazz 063 * @return returns stored struct 064 */ 065 private Map<Key,Array> store(Class clazz) { 066 Method[] methods=clazz.getMethods(); 067 Map<Key,Array> methodsMap=new ConcurrentHashMap<Key, Array>(); 068 for(int i=0;i<methods.length;i++) { 069 storeMethod(methods[i],methodsMap); 070 071 } 072 map.put(clazz,methodsMap); 073 return methodsMap; 074 } 075 076 /** 077 * stores a single method 078 * @param method 079 * @param methodsMap 080 */ 081 private synchronized void storeMethod(Method method, Map<Key,Array> methodsMap) { 082 Key methodName = KeyImpl.init(method.getName()); 083 084 Array methodArgs=methodsMap.get(methodName); 085 if(methodArgs==null) { 086 methodArgs=new ArrayImpl(); 087 methodsMap.put(methodName,methodArgs); 088 } 089 090 storeArgs(method,methodArgs); 091 //Modifier.isStatic(method.getModifiers()); 092 } 093 094 /** 095 * stores arguments of a method 096 * @param method 097 * @param methodArgs 098 */ 099 private void storeArgs(Method method, Array methodArgs) { 100 101 Class[] pmt = method.getParameterTypes(); 102 Object o=methodArgs.get(pmt.length+1,null); 103 Method[] args; 104 if(o==null) { 105 args=new Method[1]; 106 methodArgs.setEL(pmt.length+1,args); 107 } 108 else { 109 Method[] ms = (Method[]) o; 110 args = new Method[ms.length+1]; 111 for(int i=0;i<ms.length;i++) { 112 args[i]=ms[i]; 113 } 114 methodArgs.setEL(pmt.length+1,args); 115 } 116 args[args.length-1]=method; 117 } 118}