1 | |
|
2 | |
|
3 | |
|
4 | |
|
5 | |
|
6 | |
|
7 | |
|
8 | |
|
9 | |
|
10 | |
|
11 | |
|
12 | |
|
13 | |
|
14 | |
|
15 | |
|
16 | |
|
17 | |
|
18 | |
|
19 | |
package org.apache.myfaces.view.facelets.tag; |
20 | |
|
21 | |
import org.apache.myfaces.shared.util.ClassUtils; |
22 | |
import org.apache.myfaces.view.facelets.util.ParameterCheck; |
23 | |
|
24 | |
import javax.faces.view.facelets.FaceletContext; |
25 | |
import javax.faces.view.facelets.MetaRule; |
26 | |
import javax.faces.view.facelets.MetaRuleset; |
27 | |
import javax.faces.view.facelets.Metadata; |
28 | |
import javax.faces.view.facelets.MetadataTarget; |
29 | |
import javax.faces.view.facelets.Tag; |
30 | |
import javax.faces.view.facelets.TagAttribute; |
31 | |
import javax.faces.view.facelets.TagException; |
32 | |
import java.beans.IntrospectionException; |
33 | |
import java.util.ArrayList; |
34 | |
import java.util.HashMap; |
35 | |
import java.util.List; |
36 | |
import java.util.Map; |
37 | |
import java.util.WeakHashMap; |
38 | |
import java.util.logging.Level; |
39 | |
import java.util.logging.Logger; |
40 | |
import org.apache.myfaces.view.facelets.PassthroughRule; |
41 | |
import org.apache.myfaces.view.facelets.tag.jsf.PassThroughLibrary; |
42 | |
|
43 | |
|
44 | |
|
45 | |
|
46 | |
|
47 | |
|
48 | 0 | public final class MetaRulesetImpl extends MetaRuleset |
49 | |
{ |
50 | 0 | private final static Metadata NONE = new NullMetadata(); |
51 | |
|
52 | |
|
53 | 0 | private final static Logger log = Logger.getLogger(MetaRulesetImpl.class.getName()); |
54 | |
|
55 | |
|
56 | |
|
57 | |
|
58 | |
|
59 | |
|
60 | |
|
61 | |
|
62 | |
|
63 | |
|
64 | 0 | private volatile static WeakHashMap<ClassLoader, Map<String, MetadataTarget>> metadata |
65 | |
= new WeakHashMap<ClassLoader, Map<String, MetadataTarget>>(); |
66 | |
|
67 | |
|
68 | |
|
69 | |
|
70 | |
public static void clearMetadataTargetCache() |
71 | |
{ |
72 | 0 | metadata.remove(ClassUtils.getContextClassLoader()); |
73 | 0 | } |
74 | |
|
75 | |
private static Map<String, MetadataTarget> getMetaData() |
76 | |
{ |
77 | 0 | ClassLoader cl = ClassUtils.getContextClassLoader(); |
78 | |
|
79 | 0 | Map<String, MetadataTarget> metadata = (Map<String, MetadataTarget>) |
80 | |
MetaRulesetImpl.metadata.get(cl); |
81 | |
|
82 | 0 | if (metadata == null) |
83 | |
{ |
84 | |
|
85 | |
|
86 | 0 | synchronized (MetaRulesetImpl.metadata) |
87 | |
{ |
88 | 0 | metadata = createMetaData(cl, metadata); |
89 | 0 | } |
90 | |
} |
91 | |
|
92 | 0 | return metadata; |
93 | |
} |
94 | |
|
95 | |
private static Map<String, MetadataTarget> createMetaData(ClassLoader cl, Map<String, MetadataTarget> metadata) |
96 | |
{ |
97 | 0 | metadata = (Map<String, MetadataTarget>) MetaRulesetImpl.metadata.get(cl); |
98 | 0 | if (metadata == null) |
99 | |
{ |
100 | 0 | metadata = new HashMap<String, MetadataTarget>(); |
101 | 0 | MetaRulesetImpl.metadata.put(cl, metadata); |
102 | |
} |
103 | 0 | return metadata; |
104 | |
} |
105 | |
|
106 | 0 | private final static TagAttribute[] EMPTY = new TagAttribute[0]; |
107 | |
|
108 | |
private final Map<String, TagAttribute> _attributes; |
109 | |
|
110 | |
private final TagAttribute[] _passthroughAttributes; |
111 | |
|
112 | |
private final List<Metadata> _mappers; |
113 | |
|
114 | |
private final List<MetaRule> _rules; |
115 | |
|
116 | |
private final Tag _tag; |
117 | |
|
118 | |
private final Class<?> _type; |
119 | |
|
120 | |
private final List<MetaRule> _passthroughRules; |
121 | |
|
122 | |
public MetaRulesetImpl(Tag tag, Class<?> type) |
123 | 0 | { |
124 | 0 | _tag = tag; |
125 | 0 | _type = type; |
126 | 0 | TagAttribute[] allAttributes = _tag.getAttributes().getAll(); |
127 | |
|
128 | |
|
129 | |
|
130 | 0 | int initialSize = allAttributes.length > 0 ? (allAttributes.length * 4 + 3) / 3 : 4; |
131 | 0 | _attributes = new HashMap<String, TagAttribute>(initialSize); |
132 | 0 | _mappers = new ArrayList<Metadata>(initialSize); |
133 | |
|
134 | |
|
135 | 0 | _rules = new ArrayList<MetaRule>(8); |
136 | 0 | _passthroughRules = new ArrayList<MetaRule>(2); |
137 | |
|
138 | |
|
139 | |
|
140 | |
|
141 | |
|
142 | 0 | TagAttribute[] passthroughAttribute = _tag.getAttributes().getAll( |
143 | |
PassThroughLibrary.NAMESPACE); |
144 | 0 | TagAttribute[] passthroughAttributeAlias = _tag.getAttributes().getAll( |
145 | |
PassThroughLibrary.ALIAS_NAMESPACE); |
146 | |
|
147 | 0 | if (passthroughAttribute.length > 0 || |
148 | |
passthroughAttributeAlias.length > 0) |
149 | |
{ |
150 | 0 | _passthroughAttributes = new TagAttribute[passthroughAttribute.length+ |
151 | |
passthroughAttributeAlias.length]; |
152 | 0 | int i = 0; |
153 | 0 | for (TagAttribute attribute : allAttributes) |
154 | |
{ |
155 | |
|
156 | |
|
157 | 0 | if (attribute.getNamespace().length() > 0 && |
158 | |
(PassThroughLibrary.NAMESPACE.equals(attribute.getNamespace()) || |
159 | |
PassThroughLibrary.ALIAS_NAMESPACE.equals(attribute.getNamespace()))) |
160 | |
{ |
161 | 0 | _passthroughAttributes[i] = attribute; |
162 | 0 | i++; |
163 | |
} |
164 | |
else |
165 | |
{ |
166 | 0 | _attributes.put(attribute.getLocalName(), attribute); |
167 | |
} |
168 | |
} |
169 | 0 | } |
170 | |
else |
171 | |
{ |
172 | 0 | _passthroughAttributes = EMPTY; |
173 | |
|
174 | 0 | for (TagAttribute attribute : allAttributes) |
175 | |
{ |
176 | 0 | _attributes.put(attribute.getLocalName(), attribute); |
177 | |
} |
178 | |
} |
179 | |
|
180 | |
|
181 | 0 | _rules.add(BeanPropertyTagRule.INSTANCE); |
182 | 0 | } |
183 | |
|
184 | |
public MetaRuleset add(Metadata mapper) |
185 | |
{ |
186 | 0 | ParameterCheck.notNull("mapper", mapper); |
187 | |
|
188 | 0 | if (!_mappers.contains(mapper)) |
189 | |
{ |
190 | 0 | _mappers.add(mapper); |
191 | |
} |
192 | |
|
193 | 0 | return this; |
194 | |
} |
195 | |
|
196 | |
public MetaRuleset addRule(MetaRule rule) |
197 | |
{ |
198 | 0 | ParameterCheck.notNull("rule", rule); |
199 | |
|
200 | 0 | if (rule instanceof PassthroughRule) |
201 | |
{ |
202 | 0 | _passthroughRules.add(rule); |
203 | |
} |
204 | |
else |
205 | |
{ |
206 | 0 | _rules.add(rule); |
207 | |
} |
208 | |
|
209 | 0 | return this; |
210 | |
} |
211 | |
|
212 | |
public MetaRuleset alias(String attribute, String property) |
213 | |
{ |
214 | 0 | ParameterCheck.notNull("attribute", attribute); |
215 | 0 | ParameterCheck.notNull("property", property); |
216 | |
|
217 | 0 | TagAttribute attr = (TagAttribute) _attributes.remove(attribute); |
218 | 0 | if (attr != null) |
219 | |
{ |
220 | 0 | _attributes.put(property, attr); |
221 | |
} |
222 | |
|
223 | 0 | return this; |
224 | |
} |
225 | |
|
226 | |
public Metadata finish() |
227 | |
{ |
228 | 0 | MetadataTarget target = null; |
229 | |
|
230 | 0 | assert !_rules.isEmpty(); |
231 | |
|
232 | 0 | if (!_attributes.isEmpty()) |
233 | |
{ |
234 | 0 | target = this._getMetadataTarget(); |
235 | 0 | int ruleEnd = _rules.size() - 1; |
236 | |
|
237 | |
|
238 | 0 | for (Map.Entry<String, TagAttribute> entry : _attributes.entrySet()) |
239 | |
{ |
240 | 0 | Metadata data = null; |
241 | |
|
242 | 0 | int i = ruleEnd; |
243 | |
|
244 | |
|
245 | |
do |
246 | |
{ |
247 | 0 | MetaRule rule = _rules.get(i); |
248 | 0 | data = rule.applyRule(entry.getKey(), entry.getValue(), target); |
249 | 0 | i--; |
250 | 0 | } while (data == null && i >= 0); |
251 | |
|
252 | 0 | if (data == null) |
253 | |
{ |
254 | 0 | if (log.isLoggable(Level.SEVERE)) |
255 | |
{ |
256 | 0 | log.severe(entry.getValue() + " Unhandled by MetaTagHandler for type " + _type.getName()); |
257 | |
} |
258 | |
} |
259 | |
else |
260 | |
{ |
261 | 0 | _mappers.add(data); |
262 | |
} |
263 | 0 | } |
264 | |
} |
265 | |
|
266 | 0 | if (_passthroughAttributes.length > 0 && |
267 | |
_passthroughRules.size() > 0) |
268 | |
{ |
269 | 0 | if (target == null) |
270 | |
{ |
271 | 0 | target = this._getMetadataTarget(); |
272 | |
} |
273 | 0 | int ruleEnd = _passthroughRules.size() - 1; |
274 | |
|
275 | |
|
276 | 0 | for (TagAttribute passthroughAttribute : _passthroughAttributes) |
277 | |
{ |
278 | 0 | Metadata data = null; |
279 | |
|
280 | 0 | int i = ruleEnd; |
281 | |
|
282 | |
|
283 | |
do |
284 | |
{ |
285 | 0 | MetaRule rule = _passthroughRules.get(i); |
286 | 0 | data = rule.applyRule(passthroughAttribute.getLocalName(), |
287 | |
passthroughAttribute, target); |
288 | 0 | i--; |
289 | 0 | } while (data == null && i >= 0); |
290 | |
|
291 | 0 | if (data == null) |
292 | |
{ |
293 | 0 | if (log.isLoggable(Level.SEVERE)) |
294 | |
{ |
295 | 0 | log.severe(passthroughAttribute.getLocalName() + |
296 | |
" Unhandled by MetaTagHandler for type " + _type.getName()); |
297 | |
} |
298 | |
} |
299 | |
else |
300 | |
{ |
301 | 0 | _mappers.add(data); |
302 | |
} |
303 | |
} |
304 | |
} |
305 | |
|
306 | 0 | if (_mappers.isEmpty()) |
307 | |
{ |
308 | 0 | return NONE; |
309 | |
} |
310 | |
else |
311 | |
{ |
312 | 0 | return new MetadataImpl(_mappers.toArray(new Metadata[_mappers.size()])); |
313 | |
} |
314 | |
} |
315 | |
|
316 | |
public MetaRuleset ignore(String attribute) |
317 | |
{ |
318 | 0 | ParameterCheck.notNull("attribute", attribute); |
319 | |
|
320 | 0 | _attributes.remove(attribute); |
321 | |
|
322 | 0 | return this; |
323 | |
} |
324 | |
|
325 | |
public MetaRuleset ignoreAll() |
326 | |
{ |
327 | 0 | _attributes.clear(); |
328 | |
|
329 | 0 | return this; |
330 | |
} |
331 | |
|
332 | |
private MetadataTarget _getMetadataTarget() |
333 | |
{ |
334 | 0 | Map<String, MetadataTarget> metadata = getMetaData(); |
335 | 0 | String metaKey = _type.getName(); |
336 | |
|
337 | 0 | MetadataTarget meta = metadata.get(metaKey); |
338 | 0 | if (meta == null) |
339 | |
{ |
340 | |
try |
341 | |
{ |
342 | 0 | meta = new MetadataTargetImpl(_type); |
343 | |
} |
344 | 0 | catch (IntrospectionException e) |
345 | |
{ |
346 | 0 | throw new TagException(_tag, "Error Creating TargetMetadata", e); |
347 | 0 | } |
348 | |
|
349 | 0 | synchronized(metadata) |
350 | |
{ |
351 | |
|
352 | |
|
353 | |
|
354 | |
|
355 | |
|
356 | 0 | metadata.put(metaKey, meta); |
357 | 0 | } |
358 | |
} |
359 | |
|
360 | 0 | return meta; |
361 | |
} |
362 | |
|
363 | 0 | private static class NullMetadata extends Metadata |
364 | |
{ |
365 | |
|
366 | |
|
367 | |
|
368 | |
@Override |
369 | |
public void applyMetadata(FaceletContext ctx, Object instance) |
370 | |
{ |
371 | |
|
372 | 0 | } |
373 | |
} |
374 | |
} |