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
41
42
43
44
45
46 public final class MetaRulesetImpl extends MetaRuleset
47 {
48 private final static Metadata NONE = new NullMetadata();
49
50
51 private final static Logger log = Logger.getLogger(MetaRulesetImpl.class.getName());
52
53
54
55
56
57
58
59
60
61
62 private volatile static WeakHashMap<ClassLoader, Map<String, MetadataTarget>> metadata
63 = new WeakHashMap<ClassLoader, Map<String, MetadataTarget>>();
64
65
66
67
68 public static void clearMetadataTargetCache()
69 {
70 metadata.remove(ClassUtils.getContextClassLoader());
71 }
72
73 private static Map<String, MetadataTarget> getMetaData()
74 {
75 ClassLoader cl = ClassUtils.getContextClassLoader();
76
77 Map<String, MetadataTarget> metadata = (Map<String, MetadataTarget>)
78 MetaRulesetImpl.metadata.get(cl);
79
80 if (metadata == null)
81 {
82
83
84 synchronized (MetaRulesetImpl.metadata)
85 {
86 metadata = createMetaData(cl, metadata);
87 }
88 }
89
90 return metadata;
91 }
92
93 private static Map<String, MetadataTarget> createMetaData(ClassLoader cl, Map<String, MetadataTarget> metadata)
94 {
95 metadata = (Map<String, MetadataTarget>) MetaRulesetImpl.metadata.get(cl);
96 if (metadata == null)
97 {
98 metadata = new HashMap<String, MetadataTarget>();
99 MetaRulesetImpl.metadata.put(cl, metadata);
100 }
101 return metadata;
102 }
103
104 private final Map<String, TagAttribute> _attributes;
105
106 private final List<Metadata> _mappers;
107
108 private final List<MetaRule> _rules;
109
110 private final Tag _tag;
111
112 private final Class<?> _type;
113
114 public MetaRulesetImpl(Tag tag, Class<?> type)
115 {
116 _tag = tag;
117 _type = type;
118 TagAttribute[] allAttributes = _tag.getAttributes().getAll();
119
120
121
122 int initialSize = allAttributes.length > 0 ? (allAttributes.length * 4 + 3) / 3 : 4;
123 _attributes = new HashMap<String, TagAttribute>(initialSize);
124 _mappers = new ArrayList<Metadata>(initialSize);
125
126
127 _rules = new ArrayList<MetaRule>(8);
128
129
130 for (TagAttribute attribute : allAttributes)
131 {
132 _attributes.put(attribute.getLocalName(), attribute);
133 }
134
135
136 _rules.add(BeanPropertyTagRule.Instance);
137 }
138
139 public MetaRuleset add(Metadata mapper)
140 {
141 ParameterCheck.notNull("mapper", mapper);
142
143 if (!_mappers.contains(mapper))
144 {
145 _mappers.add(mapper);
146 }
147
148 return this;
149 }
150
151 public MetaRuleset addRule(MetaRule rule)
152 {
153 ParameterCheck.notNull("rule", rule);
154
155 _rules.add(rule);
156
157 return this;
158 }
159
160 public MetaRuleset alias(String attribute, String property)
161 {
162 ParameterCheck.notNull("attribute", attribute);
163 ParameterCheck.notNull("property", property);
164
165 TagAttribute attr = (TagAttribute) _attributes.remove(attribute);
166 if (attr != null)
167 {
168 _attributes.put(property, attr);
169 }
170
171 return this;
172 }
173
174 public Metadata finish()
175 {
176 assert !_rules.isEmpty();
177
178 if (!_attributes.isEmpty())
179 {
180 MetadataTarget target = this._getMetadataTarget();
181 int ruleEnd = _rules.size() - 1;
182
183
184 for (Map.Entry<String, TagAttribute> entry : _attributes.entrySet())
185 {
186 Metadata data = null;
187
188 int i = ruleEnd;
189
190
191 do
192 {
193 MetaRule rule = _rules.get(i);
194 data = rule.applyRule(entry.getKey(), entry.getValue(), target);
195 i--;
196 } while (data == null && i >= 0);
197
198 if (data == null)
199 {
200 if (log.isLoggable(Level.SEVERE))
201 {
202 log.severe(entry.getValue() + " Unhandled by MetaTagHandler for type " + _type.getName());
203 }
204 }
205 else
206 {
207 _mappers.add(data);
208 }
209 }
210 }
211
212 if (_mappers.isEmpty())
213 {
214 return NONE;
215 }
216 else
217 {
218 return new MetadataImpl(_mappers.toArray(new Metadata[_mappers.size()]));
219 }
220 }
221
222 public MetaRuleset ignore(String attribute)
223 {
224 ParameterCheck.notNull("attribute", attribute);
225
226 _attributes.remove(attribute);
227
228 return this;
229 }
230
231 public MetaRuleset ignoreAll()
232 {
233 _attributes.clear();
234
235 return this;
236 }
237
238 private final MetadataTarget _getMetadataTarget()
239 {
240 Map<String, MetadataTarget> metadata = getMetaData();
241 String metaKey = _type.getName();
242
243 MetadataTarget meta = metadata.get(metaKey);
244 if (meta == null)
245 {
246 try
247 {
248 meta = new MetadataTargetImpl(_type);
249 }
250 catch (IntrospectionException e)
251 {
252 throw new TagException(_tag, "Error Creating TargetMetadata", e);
253 }
254
255 synchronized(metadata)
256 {
257
258
259
260
261
262 metadata.put(metaKey, meta);
263 }
264 }
265
266 return meta;
267 }
268
269 private static class NullMetadata extends Metadata
270 {
271
272
273
274 @Override
275 public void applyMetadata(FaceletContext ctx, Object instance)
276 {
277
278 }
279 }
280 }