KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > javax > el > BeanELResolver


1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one or more
3  * contributor license agreements. See the NOTICE file distributed with
4  * this work for additional information regarding copyright ownership.
5  * The ASF licenses this file to You under the Apache License, Version 2.0
6  * (the "License"); you may not use this file except in compliance with
7  * the License. You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */

17
18 package javax.el;
19
20 import java.beans.BeanInfo JavaDoc;
21 import java.beans.FeatureDescriptor JavaDoc;
22 import java.beans.IntrospectionException JavaDoc;
23 import java.beans.Introspector JavaDoc;
24 import java.beans.PropertyDescriptor JavaDoc;
25 import java.lang.reflect.InvocationTargetException JavaDoc;
26 import java.lang.reflect.Method JavaDoc;
27 import java.lang.reflect.Modifier JavaDoc;
28 import java.util.Arrays JavaDoc;
29 import java.util.HashMap JavaDoc;
30 import java.util.Iterator JavaDoc;
31 import java.util.Map JavaDoc;
32 import java.util.WeakHashMap JavaDoc;
33 import java.util.concurrent.ConcurrentHashMap JavaDoc;
34
35 public class BeanELResolver extends ELResolver {
36
37     private final boolean readOnly;
38
39     private final ConcurrentCache<String JavaDoc, BeanProperties> cache = new ConcurrentCache<String JavaDoc, BeanProperties>(
40             1000);
41
42     public BeanELResolver() {
43         this.readOnly = false;
44     }
45
46     public BeanELResolver(boolean readOnly) {
47         this.readOnly = readOnly;
48     }
49
50     public Object JavaDoc getValue(ELContext context, Object JavaDoc base, Object JavaDoc property)
51             throws NullPointerException JavaDoc, PropertyNotFoundException, ELException {
52         if (context == null) {
53             throw new NullPointerException JavaDoc();
54         }
55         if (base == null || property == null) {
56             return null;
57         }
58
59         context.setPropertyResolved(true);
60         Method JavaDoc m = this.property(context, base, property).read(context);
61         try {
62             return m.invoke(base, (Object JavaDoc[]) null);
63         } catch (IllegalAccessException JavaDoc e) {
64             throw new ELException(e);
65         } catch (InvocationTargetException JavaDoc e) {
66             throw new ELException(message(context, "propertyReadError",
67                     new Object JavaDoc[] { base.getClass().getName(),
68                             property.toString() }), e.getCause());
69         } catch (Exception JavaDoc e) {
70             throw new ELException(e);
71         }
72     }
73
74     public Class JavaDoc<?> getType(ELContext context, Object JavaDoc base, Object JavaDoc property)
75             throws NullPointerException JavaDoc, PropertyNotFoundException, ELException {
76         if (context == null) {
77             throw new NullPointerException JavaDoc();
78         }
79         if (base == null || property == null) {
80             return null;
81         }
82
83         context.setPropertyResolved(true);
84         return this.property(context, base, property).getType();
85     }
86
87     public void setValue(ELContext context, Object JavaDoc base, Object JavaDoc property,
88             Object JavaDoc value) throws NullPointerException JavaDoc,
89             PropertyNotFoundException, PropertyNotWritableException,
90             ELException {
91         if (context == null) {
92             throw new NullPointerException JavaDoc();
93         }
94         if (base == null || property == null) {
95             return;
96         }
97
98         context.setPropertyResolved(true);
99
100         if (this.readOnly) {
101             throw new PropertyNotWritableException(message(context,
102                     "resolverNotWriteable", new Object JavaDoc[] { base.getClass()
103                             .getName() }));
104         }
105
106         Method JavaDoc m = this.property(context, base, property).write(context);
107         try {
108             m.invoke(base, new Object JavaDoc[] { value });
109         } catch (IllegalAccessException JavaDoc e) {
110             throw new ELException(e);
111         } catch (InvocationTargetException JavaDoc e) {
112             throw new ELException(message(context, "propertyWriteError",
113                     new Object JavaDoc[] { base.getClass().getName(),
114                             property.toString() }), e.getCause());
115         } catch (Exception JavaDoc e) {
116             throw new ELException(e);
117         }
118     }
119
120     public boolean isReadOnly(ELContext context, Object JavaDoc base, Object JavaDoc property)
121             throws NullPointerException JavaDoc, PropertyNotFoundException, ELException {
122         if (context == null) {
123             throw new NullPointerException JavaDoc();
124         }
125         if (base == null || property == null) {
126             return false;
127         }
128
129         context.setPropertyResolved(true);
130         return this.readOnly
131                 || this.property(context, base, property).isReadOnly();
132     }
133
134     public Iterator JavaDoc<FeatureDescriptor JavaDoc> getFeatureDescriptors(ELContext context, Object JavaDoc base) {
135         if (context == null) {
136             throw new NullPointerException JavaDoc();
137         }
138
139         if (base == null) {
140             return null;
141         }
142
143         try {
144             BeanInfo JavaDoc info = Introspector.getBeanInfo(base.getClass());
145             PropertyDescriptor JavaDoc[] pds = info.getPropertyDescriptors();
146             for (int i = 0; i < pds.length; i++) {
147                 pds[i].setValue(RESOLVABLE_AT_DESIGN_TIME, Boolean.TRUE);
148                 pds[i].setValue(TYPE, pds[i].getPropertyType());
149             }
150             return Arrays.asList((FeatureDescriptor JavaDoc[]) pds).iterator();
151         } catch (IntrospectionException JavaDoc e) {
152             //
153
}
154
155         return null;
156     }
157
158     public Class JavaDoc<?> getCommonPropertyType(ELContext context, Object JavaDoc base) {
159         if (context == null) {
160             throw new NullPointerException JavaDoc();
161         }
162
163         if (base != null) {
164             return Object JavaDoc.class;
165         }
166
167         return null;
168     }
169
170     protected final static class BeanProperties {
171         private final Map JavaDoc<String JavaDoc, BeanProperty> properties;
172
173         private final Class JavaDoc<?> type;
174
175         public BeanProperties(Class JavaDoc<?> type) throws ELException {
176             this.type = type;
177             this.properties = new HashMap JavaDoc<String JavaDoc, BeanProperty>();
178             try {
179                 BeanInfo JavaDoc info = Introspector.getBeanInfo(this.type);
180                 PropertyDescriptor JavaDoc[] pds = info.getPropertyDescriptors();
181                 for (int i = 0; i < pds.length; i++) {
182                     this.properties.put(pds[i].getName(), new BeanProperty(
183                             type, pds[i]));
184                 }
185             } catch (IntrospectionException JavaDoc ie) {
186                 throw new ELException(ie);
187             }
188         }
189
190         public BeanProperty get(ELContext ctx, String JavaDoc name) {
191             BeanProperty property = this.properties.get(name);
192             if (property == null) {
193                 throw new PropertyNotFoundException(message(ctx,
194                         "propertyNotFound",
195                         new Object JavaDoc[] { type.getName(), name }));
196             }
197             return property;
198         }
199         
200         public Class JavaDoc<?> getType() {
201             return type;
202         }
203     }
204
205     protected final static class BeanProperty {
206         private final Class JavaDoc type;
207
208         private final Class JavaDoc owner;
209
210         private final PropertyDescriptor JavaDoc descriptor;
211
212         private Method JavaDoc read;
213
214         private Method JavaDoc write;
215
216         public BeanProperty(Class JavaDoc owner, PropertyDescriptor JavaDoc descriptor) {
217             this.owner = owner;
218             this.descriptor = descriptor;
219             this.type = descriptor.getPropertyType();
220         }
221
222         public Class JavaDoc<?> getType() {
223             return this.type;
224         }
225
226         public boolean isReadOnly() {
227             return this.write == null
228                 && (null == (this.write = getMethod(this.owner, descriptor.getWriteMethod())));
229         }
230
231         public Method JavaDoc write(ELContext ctx) {
232             if (this.write == null) {
233                 this.write = getMethod(this.owner, descriptor.getWriteMethod());
234                 if (this.write == null) {
235                     throw new PropertyNotFoundException(message(ctx,
236                             "propertyNotWritable", new Object JavaDoc[] {
237                                     type.getName(), descriptor.getName() }));
238                 }
239             }
240             return this.write;
241         }
242
243         public Method JavaDoc read(ELContext ctx) {
244             if (this.read == null) {
245                 this.read = getMethod(this.owner, descriptor.getReadMethod());
246                 if (this.read == null) {
247                     throw new PropertyNotFoundException(message(ctx,
248                             "propertyNotReadable", new Object JavaDoc[] {
249                                     type.getName(), descriptor.getName() }));
250                 }
251             }
252             return this.read;
253         }
254     }
255
256     private final BeanProperty property(ELContext ctx, Object JavaDoc base,
257             Object JavaDoc property) {
258         Class JavaDoc<?> type = base.getClass();
259         String JavaDoc prop = property.toString();
260
261         BeanProperties props = this.cache.get(type.getName());
262         if (props == null || type != props.getType()) {
263             props = new BeanProperties(type);
264             this.cache.put(type.getName(), props);
265         }
266
267         return props.get(ctx, prop);
268     }
269
270     private final static Method JavaDoc getMethod(Class JavaDoc type, Method JavaDoc m) {
271         if (m == null || Modifier.isPublic(type.getModifiers())) {
272             return m;
273         }
274         Class JavaDoc[] inf = type.getInterfaces();
275         Method JavaDoc mp = null;
276         for (int i = 0; i < inf.length; i++) {
277             try {
278                 mp = inf[i].getMethod(m.getName(), (Class JavaDoc[]) m.getParameterTypes());
279                 mp = getMethod(mp.getDeclaringClass(), mp);
280                 if (mp != null) {
281                     return mp;
282                 }
283             } catch (NoSuchMethodException JavaDoc e) {
284             }
285         }
286         Class JavaDoc sup = type.getSuperclass();
287         if (sup != null) {
288             try {
289                 mp = sup.getMethod(m.getName(), (Class JavaDoc[]) m.getParameterTypes());
290                 mp = getMethod(mp.getDeclaringClass(), mp);
291                 if (mp != null) {
292                     return mp;
293                 }
294             } catch (NoSuchMethodException JavaDoc e) {
295             }
296         }
297         return null;
298     }
299     
300     private final static class ConcurrentCache<K,V> {
301
302         private final int size;
303         private final Map JavaDoc<K,V> eden;
304         private final Map JavaDoc<K,V> longterm;
305         
306         public ConcurrentCache(int size) {
307             this.size = size;
308             this.eden = new ConcurrentHashMap JavaDoc<K,V>(size);
309             this.longterm = new WeakHashMap JavaDoc<K,V>(size);
310         }
311         
312         public V get(K key) {
313             V value = this.eden.get(key);
314             if (value == null) {
315                 value = this.longterm.get(key);
316                 if (value != null) {
317                     this.eden.put(key, value);
318                 }
319             }
320             return value;
321         }
322         
323         public void put(K key, V value) {
324             if (this.eden.size() >= this.size) {
325                 this.longterm.putAll(this.eden);
326                 this.eden.clear();
327             }
328             this.eden.put(key, value);
329         }
330
331     }
332 }
333
Popular Tags