|
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