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