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.jstl.core;
20
21 import java.io.IOException;
22 import java.lang.reflect.Array;
23 import java.util.Collection;
24 import java.util.Iterator;
25 import java.util.List;
26 import java.util.Map;
27
28 import javax.el.ELException;
29 import javax.el.ValueExpression;
30 import javax.faces.FacesException;
31 import javax.faces.component.UIComponent;
32 import javax.faces.view.facelets.FaceletContext;
33 import javax.faces.view.facelets.FaceletException;
34 import javax.faces.view.facelets.TagAttribute;
35 import javax.faces.view.facelets.TagAttributeException;
36 import javax.faces.view.facelets.TagConfig;
37 import javax.faces.view.facelets.TagHandler;
38
39 import org.apache.myfaces.view.facelets.AbstractFaceletContext;
40 import org.apache.myfaces.view.facelets.FaceletCompositionContext;
41 import org.apache.myfaces.view.facelets.PageContext;
42 import org.apache.myfaces.view.facelets.tag.ComponentContainerHandler;
43 import org.apache.myfaces.view.facelets.tag.jsf.ComponentSupport;
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60 public final class LegacyForEachHandler extends TagHandler implements ComponentContainerHandler
61 {
62
63 private static class ArrayIterator implements Iterator<Object>
64 {
65
66 protected final Object array;
67
68 protected int i;
69
70 protected final int len;
71
72 public ArrayIterator(Object src)
73 {
74 this.i = 0;
75 this.array = src;
76 this.len = Array.getLength(src);
77 }
78
79 public boolean hasNext()
80 {
81 return this.i < this.len;
82 }
83
84 public Object next()
85 {
86 return Array.get(this.array, this.i++);
87 }
88
89 public void remove()
90 {
91 throw new UnsupportedOperationException();
92 }
93 }
94
95
96
97
98
99
100
101
102
103
104
105 private final TagAttribute begin;
106
107
108
109
110
111
112
113
114
115
116 private final TagAttribute end;
117
118
119
120
121
122 private final TagAttribute items;
123
124
125
126
127
128
129 private final TagAttribute step;
130
131 private final TagAttribute tranzient;
132
133
134
135
136
137
138
139
140 private final TagAttribute var;
141
142
143
144
145
146
147 private final TagAttribute varStatus;
148
149
150
151
152 public LegacyForEachHandler(TagConfig config)
153 {
154 super(config);
155 this.items = this.getAttribute("items");
156 this.var = this.getAttribute("var");
157 this.begin = this.getAttribute("begin");
158 this.end = this.getAttribute("end");
159 this.step = this.getAttribute("step");
160 this.varStatus = this.getAttribute("varStatus");
161 this.tranzient = this.getAttribute("transient");
162
163 if (this.items == null && this.begin != null && this.end == null)
164 {
165 throw new TagAttributeException(this.tag, this.begin,
166 "If the 'items' attribute is not specified, but the 'begin' attribute is, "
167 + "then the 'end' attribute is required");
168 }
169 }
170
171 public void apply(FaceletContext ctx, UIComponent parent) throws IOException, FacesException, FaceletException,
172 ELException
173 {
174
175 int s = this.getBegin(ctx);
176 int e = this.getEnd(ctx);
177 int m = this.getStep(ctx);
178 Integer sO = this.begin != null ? Integer.valueOf(s) : null;
179 Integer eO = this.end != null ? Integer.valueOf(e) : null;
180 Integer mO = this.step != null ? Integer.valueOf(m) : null;
181
182 boolean t = this.getTransient(ctx);
183 Object src = null;
184 ValueExpression srcVE = null;
185 if (this.items != null)
186 {
187 srcVE = this.items.getValueExpression(ctx, Object.class);
188 src = srcVE.getValue(ctx);
189 }
190 else
191 {
192 byte[] b = new byte[e + 1];
193 for (int i = 0; i < b.length; i++)
194 {
195 b[i] = (byte) i;
196 }
197 src = b;
198 }
199 FaceletCompositionContext fcc = FaceletCompositionContext.getCurrentInstance(ctx);
200 if (src != null)
201 {
202 try
203 {
204 fcc.startComponentUniqueIdSection();
205 AbstractFaceletContext actx = (AbstractFaceletContext) ctx;
206 PageContext pctx = actx.getPageContext();
207 Iterator<?> itr = this.toIterator(src);
208 if (itr != null)
209 {
210 int i = 0;
211
212
213 while (i < s && itr.hasNext())
214 {
215 itr.next();
216 i++;
217 }
218
219 String v = this.getVarName(ctx);
220 String vs = this.getVarStatusName(ctx);
221 ValueExpression ve = null;
222 ValueExpression vO = this.capture(v, pctx);
223 ValueExpression vsO = this.capture(vs, pctx);
224 int mi = 0;
225 Object value = null;
226 try
227 {
228 boolean first = true;
229 while (i <= e && itr.hasNext())
230 {
231 value = itr.next();
232
233
234 if (v != null)
235 {
236 if (t || srcVE == null)
237 {
238 if (value == null)
239 {
240 pctx.getAttributes().put(v, null);
241 }
242 else
243 {
244 pctx.getAttributes().put(v,
245 ctx.getExpressionFactory().createValueExpression(
246 value, Object.class));
247 }
248 }
249 else
250 {
251 ve = this.getVarExpr(srcVE, src, value, i);
252 pctx.getAttributes().put(v, ve);
253 }
254 }
255
256
257 if (vs != null)
258 {
259 IterationStatus itrS = new IterationStatus(first, !itr.hasNext(), i, sO, eO, mO, value);
260 if (t || srcVE == null)
261 {
262 if (srcVE == null)
263 {
264 pctx.getAttributes().put(vs, null);
265 }
266 else
267 {
268 pctx.getAttributes().put(vs,
269 ctx.getExpressionFactory().createValueExpression(
270 itrS, Object.class));
271 }
272 }
273 else
274 {
275 ve = new IterationStatusExpression(itrS);
276 pctx.getAttributes().put(vs, ve);
277 }
278 }
279
280
281 this.nextHandler.apply(ctx, parent);
282
283
284 mi = 1;
285 while (mi < m && itr.hasNext())
286 {
287 itr.next();
288 mi++;
289 i++;
290 }
291 i++;
292
293 first = false;
294 }
295 }
296 finally
297 {
298
299 if (v != null)
300 {
301 pctx.getAttributes().put(v, vO);
302 }
303 else
304 {
305 pctx.getAttributes().remove(v);
306 }
307 if (vs != null)
308 {
309 pctx.getAttributes().put(vs, vsO);
310 }
311 else
312 {
313 pctx.getAttributes().remove(vs);
314 }
315 }
316 }
317 }
318 finally
319 {
320 fcc.endComponentUniqueIdSection();
321 }
322 }
323
324 if (fcc.isUsingPSSOnThisView() && fcc.isRefreshTransientBuildOnPSS() && !fcc.isRefreshingTransientBuild())
325 {
326
327 ComponentSupport.markComponentToRestoreFully(ctx.getFacesContext(), parent);
328 }
329 if (fcc.isDynamicComponentSection())
330 {
331 ComponentSupport.markComponentToRefreshDynamically(ctx.getFacesContext(), parent);
332 }
333 }
334
335 private final ValueExpression capture(String name, PageContext pctx)
336 {
337 if (name != null)
338 {
339 return pctx.getAttributes().put(name, null);
340 }
341 return null;
342 }
343
344 private final int getBegin(FaceletContext ctx)
345 {
346 if (this.begin != null)
347 {
348 return this.begin.getInt(ctx);
349 }
350 return 0;
351 }
352
353 private final int getEnd(FaceletContext ctx)
354 {
355 if (this.end != null)
356 {
357 return this.end.getInt(ctx);
358 }
359 return Integer.MAX_VALUE - 1;
360 }
361
362 private final int getStep(FaceletContext ctx)
363 {
364 if (this.step != null)
365 {
366 return this.step.getInt(ctx);
367 }
368 return 1;
369 }
370
371 private final boolean getTransient(FaceletContext ctx)
372 {
373 if (this.tranzient != null)
374 {
375 return this.tranzient.getBoolean(ctx);
376 }
377 return false;
378 }
379
380 private final ValueExpression getVarExpr(ValueExpression ve, Object src, Object value, int i)
381 {
382 if (src instanceof List || src.getClass().isArray())
383 {
384 return new IndexedValueExpression(ve, i);
385 }
386 else if (src instanceof Map && value instanceof Map.Entry)
387 {
388 return new MappedValueExpression(ve, (Map.Entry) value);
389 }
390 else if (src instanceof Collection)
391 {
392 return new IteratedValueExpression(ve, value);
393 }
394 throw new IllegalStateException("Cannot create VE for: " + src);
395 }
396
397 private final String getVarName(FaceletContext ctx)
398 {
399 if (this.var != null)
400 {
401 return this.var.getValue(ctx);
402 }
403 return null;
404 }
405
406 private final String getVarStatusName(FaceletContext ctx)
407 {
408 if (this.varStatus != null)
409 {
410 return this.varStatus.getValue(ctx);
411 }
412 return null;
413 }
414
415 private final Iterator<?> toIterator(Object src)
416 {
417 if (src == null)
418 {
419 return null;
420 }
421 else if (src instanceof Collection)
422 {
423 return ((Collection<?>) src).iterator();
424 }
425 else if (src instanceof Map)
426 {
427 return ((Map<?, ?>) src).entrySet().iterator();
428 }
429 else if (src.getClass().isArray())
430 {
431 return new ArrayIterator(src);
432 }
433 else
434 {
435 throw new TagAttributeException(this.tag, this.items,
436 "Must evaluate to a Collection, Map, Array, or null.");
437 }
438 }
439
440 }