|
58 | 58 |
|
59 | 59 | package javax.el; |
60 | 60 |
|
| 61 | + |
| 62 | +import org.jboss.el.cache.BeanPropertiesCache; |
| 63 | + |
61 | 64 | import java.lang.reflect.InvocationTargetException; |
62 | 65 | import java.lang.reflect.Method; |
63 | | -import java.lang.reflect.Modifier; |
64 | | -import java.lang.ref.SoftReference; |
65 | | -import java.lang.ref.ReferenceQueue; |
66 | 66 | import java.beans.FeatureDescriptor; |
67 | 67 | import java.beans.BeanInfo; |
68 | 68 | import java.beans.Introspector; |
69 | 69 | import java.beans.PropertyDescriptor; |
70 | | -import java.beans.IntrospectionException; |
71 | 70 | import java.util.Iterator; |
72 | 71 | import java.util.ArrayList; |
73 | | -import java.util.Map; |
74 | | -import java.util.HashMap; |
75 | | -import java.util.concurrent.ConcurrentHashMap; |
| 72 | + |
| 73 | +import static org.jboss.el.cache.BeanPropertiesCache.BeanProperties; |
| 74 | +import static org.jboss.el.cache.BeanPropertiesCache.BeanProperty; |
76 | 75 |
|
77 | 76 | /** |
78 | 77 | * Defines property resolution behavior on objects using the JavaBeans |
|
113 | 112 | */ |
114 | 113 | public class BeanELResolver extends ELResolver { |
115 | 114 |
|
116 | | - static private class BPSoftReference extends SoftReference<BeanProperties> { |
117 | | - final Class<?> key; |
118 | | - BPSoftReference(Class<?> key, BeanProperties beanProperties, |
119 | | - ReferenceQueue<BeanProperties> refQ) { |
120 | | - super(beanProperties, refQ); |
121 | | - this.key = key; |
122 | | - } |
123 | | - } |
124 | | - |
125 | | - static private class SoftConcurrentHashMap extends |
126 | | - ConcurrentHashMap<Class<?>, BeanProperties> { |
127 | | - |
128 | | - private static final int CACHE_INIT_SIZE = 1024; |
129 | | - private ConcurrentHashMap<Class<?>, BPSoftReference> map = |
130 | | - new ConcurrentHashMap<Class<?>, BPSoftReference>(CACHE_INIT_SIZE); |
131 | | - private ReferenceQueue<BeanProperties> refQ = |
132 | | - new ReferenceQueue<BeanProperties>(); |
133 | | - |
134 | | - // Remove map entries that have been placed on the queue by GC. |
135 | | - private void cleanup() { |
136 | | - BPSoftReference BPRef = null; |
137 | | - while ((BPRef = (BPSoftReference)refQ.poll()) != null) { |
138 | | - map.remove(BPRef.key); |
139 | | - } |
140 | | - } |
141 | | - |
142 | | - @Override |
143 | | - public BeanProperties put(Class<?> key, BeanProperties value) { |
144 | | - cleanup(); |
145 | | - BPSoftReference prev = |
146 | | - map.put(key, new BPSoftReference(key, value, refQ)); |
147 | | - return prev == null? null: prev.get(); |
148 | | - } |
149 | | - |
150 | | - @Override |
151 | | - public BeanProperties putIfAbsent(Class<?> key, BeanProperties value) { |
152 | | - cleanup(); |
153 | | - BPSoftReference prev = |
154 | | - map.putIfAbsent(key, new BPSoftReference(key, value, refQ)); |
155 | | - return prev == null? null: prev.get(); |
156 | | - } |
157 | | - |
158 | | - @Override |
159 | | - public BeanProperties get(Object key) { |
160 | | - cleanup(); |
161 | | - BPSoftReference BPRef = map.get(key); |
162 | | - if (BPRef == null) { |
163 | | - return null; |
164 | | - } |
165 | | - if (BPRef.get() == null) { |
166 | | - // value has been garbage collected, remove entry in map |
167 | | - map.remove(key); |
168 | | - return null; |
169 | | - } |
170 | | - return BPRef.get(); |
171 | | - } |
172 | | - } |
173 | | - |
174 | 115 | private boolean isReadOnly; |
175 | 116 |
|
176 | | - private static final SoftConcurrentHashMap properties = |
177 | | - new SoftConcurrentHashMap(); |
178 | | - |
179 | | - /* |
180 | | - * Defines a property for a bean. |
181 | | - */ |
182 | | - final static class BeanProperty { |
183 | | - |
184 | | - private Method readMethod; |
185 | | - private Method writeMethod; |
186 | | - private PropertyDescriptor descriptor; |
187 | | - |
188 | | - public BeanProperty(Class<?> baseClass, |
189 | | - PropertyDescriptor descriptor) { |
190 | | - this.descriptor = descriptor; |
191 | | - readMethod = getMethod(baseClass, descriptor.getReadMethod()); |
192 | | - writeMethod = getMethod(baseClass, descriptor.getWriteMethod()); |
193 | | - } |
194 | | - |
195 | | - public Class getPropertyType() { |
196 | | - return descriptor.getPropertyType(); |
197 | | - } |
198 | | - |
199 | | - public boolean isReadOnly() { |
200 | | - return getWriteMethod() == null; |
201 | | - } |
202 | | - |
203 | | - public Method getReadMethod() { |
204 | | - return readMethod; |
205 | | - } |
206 | | - |
207 | | - public Method getWriteMethod() { |
208 | | - return writeMethod; |
209 | | - } |
210 | | - } |
211 | | - |
212 | | - /* |
213 | | - * Defines the properties for a bean. |
214 | | - */ |
215 | | - final static class BeanProperties { |
216 | | - |
217 | | - private final Map<String, BeanProperty> propertyMap = |
218 | | - new HashMap<String, BeanProperty>(); |
219 | | - |
220 | | - public BeanProperties(Class<?> baseClass) { |
221 | | - PropertyDescriptor[] descriptors; |
222 | | - try { |
223 | | - BeanInfo info = Introspector.getBeanInfo(baseClass); |
224 | | - descriptors = info.getPropertyDescriptors(); |
225 | | - } catch (IntrospectionException ie) { |
226 | | - throw new ELException(ie); |
227 | | - } |
228 | | - for (PropertyDescriptor pd: descriptors) { |
229 | | - propertyMap.put(pd.getName(), |
230 | | - new BeanProperty(baseClass, pd)); |
231 | | - } |
232 | | - } |
233 | | - |
234 | | - public BeanProperty getBeanProperty(String property) { |
235 | | - return propertyMap.get(property); |
236 | | - } |
237 | | - } |
238 | | - |
239 | 117 | /** |
240 | 118 | * Creates a new read/write <code>BeanELResolver</code>. |
241 | 119 | */ |
@@ -526,7 +404,7 @@ public Object invoke(ELContext context, |
526 | 404 | } |
527 | 405 | Method m = ELUtil.findMethod(base.getClass(), method.toString(), |
528 | 406 | paramTypes,params, false); |
529 | | - m = getMethod(base.getClass(), m); |
| 407 | + m = BeanPropertiesCache.getMethod(base.getClass(), m); |
530 | 408 | for (Object p: params) { |
531 | 409 | // If the parameters is a LambdaExpression, set the ELContext |
532 | 410 | // for its evaluation |
@@ -672,59 +550,17 @@ public Class<?> getCommonPropertyType(ELContext context, |
672 | 550 | return Object.class; |
673 | 551 | } |
674 | 552 |
|
675 | | - /* |
676 | | - * Get a public method form a public class or interface of a given method. |
677 | | - * Note that if a PropertyDescriptor is obtained for a non-public class that |
678 | | - * implements a public interface, the read/write methods will be for the |
679 | | - * class, and therefore inaccessible. To correct this, a version of the |
680 | | - * same method must be found in a superclass or interface. |
681 | | - **/ |
682 | | - |
683 | | - static private Method getMethod(Class<?> cl, Method method) { |
684 | | - |
685 | | - if (method == null) { |
686 | | - return null; |
687 | | - } |
688 | | - |
689 | | - if (Modifier.isPublic (cl.getModifiers ())) { |
690 | | - return method; |
691 | | - } |
692 | | - Class<?> [] interfaces = cl.getInterfaces (); |
693 | | - for (int i = 0; i < interfaces.length; i++) { |
694 | | - Class<?> c = interfaces[i]; |
695 | | - Method m = null; |
696 | | - try { |
697 | | - m = c.getMethod(method.getName(), method.getParameterTypes()); |
698 | | - c = m.getDeclaringClass(); |
699 | | - if ((m = getMethod(c, m)) != null) |
700 | | - return m; |
701 | | - } catch (NoSuchMethodException ex) { |
702 | | - } |
703 | | - } |
704 | | - Class<?> c = cl.getSuperclass(); |
705 | | - if (c != null) { |
706 | | - Method m = null; |
707 | | - try { |
708 | | - m = c.getMethod(method.getName(), method.getParameterTypes()); |
709 | | - c = m.getDeclaringClass(); |
710 | | - if ((m = getMethod(c, m)) != null) |
711 | | - return m; |
712 | | - } catch (NoSuchMethodException ex) { |
713 | | - } |
714 | | - } |
715 | | - return null; |
716 | | - } |
717 | 553 |
|
718 | 554 | private BeanProperty getBeanProperty(ELContext context, |
719 | 555 | Object base, |
720 | 556 | Object prop) { |
721 | 557 |
|
722 | 558 | String property = prop.toString(); |
723 | 559 | Class baseClass = base.getClass(); |
724 | | - BeanProperties bps = properties.get(baseClass); |
| 560 | + BeanProperties bps = BeanPropertiesCache.getProperties().get(baseClass); |
725 | 561 | if (bps == null) { |
726 | 562 | bps = new BeanProperties(baseClass); |
727 | | - properties.put(baseClass, bps); |
| 563 | + BeanPropertiesCache.getProperties().put(baseClass, bps); |
728 | 564 | } |
729 | 565 | BeanProperty bp = bps.getBeanProperty(property); |
730 | 566 | if (bp == null) { |
|
0 commit comments