KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > sun > enterprise > tools > jsfext > el > VariableResolver


1 /*
2  * The contents of this file are subject to the terms
3  * of the Common Development and Distribution License
4  * (the License). You may not use this file except in
5  * compliance with the License.
6  *
7  * You can obtain a copy of the license at
8  * https://glassfish.dev.java.net/public/CDDLv1.0.html or
9  * glassfish/bootstrap/legal/CDDLv1.0.txt.
10  * See the License for the specific language governing
11  * permissions and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL
14  * Header Notice in each file and include the License file
15  * at glassfish/bootstrap/legal/CDDLv1.0.txt.
16  * If applicable, add the following below the CDDL Header,
17  * with the fields enclosed by brackets [] replaced by
18  * you own identifying information:
19  * "Portions Copyrighted [year] [name of copyright owner]"
20  *
21  * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
22  */

23 package com.sun.enterprise.tools.jsfext.el;
24
25 import com.sun.enterprise.tools.jsfext.layout.descriptor.LayoutElement;
26 import com.sun.enterprise.tools.jsfext.layout.descriptor.LayoutComponent;
27
28 import com.sun.web.ui.util.ClientSniffer;
29 import com.sun.web.ui.util.ThemeUtilities;
30
31 import java.lang.reflect.Field JavaDoc;
32 import java.lang.reflect.Modifier JavaDoc;
33 import java.util.ArrayList JavaDoc;
34 import java.util.Iterator JavaDoc;
35 import java.util.HashMap JavaDoc;
36 import java.util.List JavaDoc;
37 import java.util.Map JavaDoc;
38 import java.util.ResourceBundle JavaDoc;
39 import java.util.Stack JavaDoc;
40
41 import javax.faces.component.NamingContainer;
42 import javax.faces.component.UIComponent;
43 import javax.faces.component.UIViewRoot;
44 import javax.faces.context.FacesContext;
45 import javax.faces.event.ActionEvent;
46
47
48 /**
49  * <p> VariableResolver is used to parse expressions of the format.</p>
50  *
51  * <p> <dd>$&lt;type$gt;{&lt;key&gt;}</dd></p>
52  *
53  * <p> &lt;type&gt; refers to a registerd {@link VariableResolver.DataSource},
54  * custom {@link VariableResolver.DataSource}s can be registered via:
55  * {@link #setDataSource(String key,
56  * VariableResolver.DataSource dataSource)}.
57  * However, there are many built-in {@link VariableResolver.DataSource}
58  * types that are pre-registered.</p>
59  *
60  * <p> Below are the pre-registered types: </p>
61  *
62  * <ul><li>{@link #ATTRIBUTE} -- {@link AttributeDataSource}</li>
63  * <li>{@link #BOOLEAN} -- {@link BooleanDataSource}</li>
64  * <li>{@link #BROWSER} -- {@link BrowserDataSource}</li>
65  * <li>{@link #CONSTANT} -- {@link ConstantDataSource}</li>
66  * <li>{@link #ESCAPE} -- {@link EscapeDataSource}</li>
67  * <li>{@link #HAS_FACET} -- {@link HasFacetDataSource}</li>
68  * <li>{@link #HAS_PROPERTY} -- {@link HasPropertyDataSource}</li>
69  * <li>{@link #INT} -- {@link IntDataSource}</li>
70  * <li>{@link #METHOD_BINDING} -- {@link MethodBindingDataSource}</li>
71  * <li>{@link #PROPERTY} -- {@link PropertyDataSource}</li>
72  * <li>{@link #REQUEST_PARAMETER} --
73  * {@link RequestParameterDataSource}</li>
74  * <li>{@link #RESOURCE} -- {@link ResourceBundleDataSource}</li>
75  * <li>{@link #SESSION} -- {@link SessionDataSource}</li>
76  * <li>{@link #STACK_TRACE} -- {@link StackTraceDataSource}</li>
77  * <li>{@link #STYLE} -- {@link StyleDataSource}</li>
78  * <li>{@link #THEME_JS} -- {@link ThemeJavaScriptDataSource}</li>
79  * <li>{@link #THIS} -- {@link ThisDataSource}</li></ul>
80  *
81  * @author Ken Paulsen (ken.paulsen@sun.com)
82  */

83 public class VariableResolver {
84
85     /**
86      * <p> This method will substitute variables into the given String, or
87      * return the variable if the substitution is the whole String. This
88      * method looks for the LAST occurance of startToken in the given
89      * String. It then searches from that location (if found) to the
90      * first occurance of typeDelim. The value inbetween is used as the
91      * type of substitution to perform (i.e. request attribute, session,
92      * etc.). It next looks for the next occurance of endToken. The
93      * value inbetween is used as the key passed to the
94      * {@link VariableResolver.DataSource} specified by the type. The
95      * String value from the {@link VariableResolver.DataSource} replaces
96      * the portion of the String from the startToken to the endToken. If
97      * this is the entire String, the Object is returned instead of the
98      * String value. This process is repeated until no more
99      * substitutions are * needed.</p>
100      *
101      * <p> This algorithm will accomodate nested variables (e.g. "${A{$x}}").
102      * It also allows the replacement value itself to contain variables.
103      * Care should be taken to ensure that the replacement String included
104      * does not directly or indirectly refer to itself -- this will cause
105      * an infinite loop.</p>
106      *
107      * <p> There is one special case where the string to be evaluated begins
108      * with the startToken and ends with the endToken. In this case,
109      * string substitution is NOT performed. Instead the value of the
110      * request attribute is returned.</p>
111      *
112      * @param ctx The FacesContext
113      * @param desc The closest LayoutElement to this string
114      * @param component The assoicated UIComponent
115      * @param string The string to be evaluated.
116      * @param startToken Marks the beginning "$"
117      * @param typeDelim Marks separation of type/variable "{"
118      * @param endToken Marks the end of the variable "}"
119      *
120      * @return The new string with substitutions, or the specified request
121      * attribute value.
122      */

123     public static Object JavaDoc resolveVariables(FacesContext ctx,
124         LayoutElement desc, UIComponent component, String JavaDoc string,
125         String JavaDoc startToken, String JavaDoc typeDelim, String JavaDoc endToken) {
126
127     int stringLen = string.length();
128     int delimIndex;
129     int endIndex;
130     int parenSemi;
131     int startTokenLen = startToken.length();
132     int delimLen = typeDelim.length();
133     int endTokenLen = endToken.length();
134     boolean expressionIsWholeString = false;
135     char firstEndChar = SUB_END.charAt(0);
136     char firstDelimChar = SUB_TYPE_DELIM.charAt(0);
137     char currChar;
138     String JavaDoc type;
139     Object JavaDoc variable;
140
141     for (int startIndex = string.lastIndexOf(startToken); startIndex != -1;
142          startIndex = string.lastIndexOf(startToken, startIndex - 1)) {
143
144         // Find first typeDelim
145
delimIndex = string.indexOf(typeDelim, startIndex + startTokenLen);
146         if (delimIndex == -1) {
147         continue;
148         }
149
150         // Next find the end token
151
parenSemi = 0;
152         endIndex = -1;
153         // Iterate through the string looking for the matching end
154
for (int curr = delimIndex + delimLen; curr < stringLen; ) {
155         // Get the next char...
156
currChar = string.charAt(curr);
157         if ((currChar == firstDelimChar) && typeDelim.equals(
158                 string.substring(curr, curr + delimLen))) {
159             // Found the start of another... inc the semi
160
parenSemi++;
161             curr += delimLen;
162             continue;
163         }
164         if ((currChar == firstEndChar) && endToken.equals(
165                 string.substring(curr, curr + endTokenLen))) {
166             parenSemi--;
167             if (parenSemi < 0) {
168             // Found the right one!
169
endIndex = curr;
170             break;
171             }
172             // Found one, but this isn't the right one
173
curr += endTokenLen;
174             continue;
175         }
176         curr++;
177         }
178         if (endIndex == -1) {
179         // We didn't find a matching end...
180
continue;
181         }
182
183 /*
184         // Next find end token
185         endIndex = string.indexOf(endToken, delimIndex+delimLen);
186         matchingIndex = string.lastIndexOf(typeDelim, endIndex);
187         while ((endIndex != -1) && (matchingIndex != delimIndex)) {
188         // We found a endToken, but not the matching one...keep looking
189         endIndex = string.indexOf(endToken, endIndex+endTokenLen);
190         matchingIndex = string.lastIndexOf(typeDelim,
191             matchingIndex-delimLen);
192         }
193         if ((endIndex == -1) || (matchingIndex == -1)) {
194         continue;
195         }
196 */

197
198         // Handle special case where string starts with startToken and ends
199
// with endToken (and no replacements inbetween). This is special
200
// because we don't want to convert the attribute to a string, we
201
// want to return it (this allows Object types).
202
if ((startIndex == 0) && (endIndex == string.lastIndexOf(endToken))
203             && (string.endsWith(endToken))) {
204         // This is the special case...
205
expressionIsWholeString = true;
206         }
207
208         // Pull off the type...
209
type = string.substring(startIndex + startTokenLen, delimIndex);
210         DataSource ds = (DataSource) dataSourceMap.get(type);
211         if (ds == null) {
212         throw new IllegalArgumentException JavaDoc("Invalid type '" + type
213             + "' in attribute value: '" + string + "'.");
214         }
215
216         // Pull off the variable...
217
variable = string.substring(delimIndex + delimLen, endIndex);
218
219         // Get the value...
220
variable = ds.getValue(ctx, desc, component, (String JavaDoc) variable);
221         if (expressionIsWholeString) {
222         return variable;
223         }
224
225         // Make new string
226
string = string.substring(0, startIndex) + // Before replacement
227
((variable == null) ? "" : variable.toString())
228              + string.substring(endIndex + endTokenLen); // After
229
stringLen = string.length();
230     }
231
232     // Return the string
233
return string;
234     }
235
236     /**
237      * This method replaces the ${..} variables with their values. It will
238      * only do this for Strings and List's that contain Strings.
239      *
240      * @param desc The <code>LayoutElement</code> descriptor
241      * @param component The <code>UIComponent</code>
242      * @param value The value to resolve
243      *
244      * @return The result
245      */

246     public static Object JavaDoc resolveVariables(LayoutElement desc,
247         UIComponent component, Object JavaDoc value) {
248     if (value == null) {
249         return null;
250     }
251     return VariableResolver.resolveVariables(
252         FacesContext.getCurrentInstance(), desc, component, value);
253     }
254
255     /**
256      * This method replaces the ${..} variables with their attribute values.
257      * It will only do this for Strings and List's that contain Strings.
258      *
259      * @param ctx The <code>FacesContext</code>
260      * @param desc The <code>LayoutElement</code> descriptor
261      * @param component The <code>UIComponent</code>
262      * @param value The value to resolve
263      *
264      * @return The result
265      */

266     public static Object JavaDoc resolveVariables(FacesContext ctx, LayoutElement desc,
267         UIComponent component, Object JavaDoc value) {
268     if (value == null) {
269         return null;
270     }
271     if (value instanceof String JavaDoc) {
272         value = VariableResolver.resolveVariables(
273         ctx,
274         desc,
275         component,
276         (String JavaDoc) value,
277         VariableResolver.SUB_START,
278         VariableResolver.SUB_TYPE_DELIM,
279         VariableResolver.SUB_END);
280     } else if (value instanceof List JavaDoc) {
281         // Create a new List b/c invalid to change shared List
282
List JavaDoc list = ((List JavaDoc) value);
283         int size = list.size();
284         List JavaDoc newList = new ArrayList JavaDoc(size);
285         Iterator JavaDoc it = list.iterator();
286         while (it.hasNext()) {
287         newList.add(VariableResolver.resolveVariables(
288                 ctx, desc, component, it.next()));
289         }
290         return newList;
291     }
292     return value;
293     }
294
295     /**
296      * <p> This method looks up the requested
297      * {@link VariableResolver.DataSource} by the given key.
298      *
299      * @param key The key identifying the desired
300      * {@link VariableResolver.DataSource}
301      *
302      * @return The requested {@link VariableResolver.DataSource}
303      */

304     public static VariableResolver.DataSource getDataSource(String JavaDoc key) {
305     return (VariableResolver.DataSource) dataSourceMap.get(key);
306     }
307
308     /**
309      * <p> This method sets the given {@link VariableResolver.DataSource} to
310      * be used for $[type]{...} when key matches type.</p>
311      *
312      * @param key The key identifying the
313      * {@link VariableResolver.DataSource}
314      * @param dataSource The {@link VariableResolver.DataSource}
315      */

316     public static void setDataSource(String JavaDoc key,
317         VariableResolver.DataSource dataSource) {
318     dataSourceMap.put(key, dataSource);
319     }
320
321     /**
322      * <p> This interface defines a String substitution data source. This
323      * is used to retrieve values when a $&lt;type&gt;{&lt;data&gt;} is
324      * encountered within a parameter value.</p>
325      *
326      * <p> Implementations of this interface may register themselves
327      * statically to extend the capabilities of the ${} substitution
328      * mechanism.</p>
329      */

330     public interface DataSource {
331     /**
332      * <p> This method should return the resolved value based on the
333      * given key and contextual information.</p>
334      *
335      * @param ctx The <code>FacesContext</code>
336      * @param desc The <code>LayoutElement</code>
337      * @param component The <code>UIComponent</code>
338      * @param key The key used to obtain information from this
339      * <code>DataSource</code>.
340      *
341      * @return The value resolved from key.
342      */

343     Object JavaDoc getValue(FacesContext ctx, LayoutElement desc,
344         UIComponent component, String JavaDoc key);
345     }
346
347     /**
348      * <p> This {@link VariableResolver.DataSource} provides access to
349      * HttpRequest attributes. It uses the data portion of the
350      * substitution String as a key to the HttpRequest attribute Map.</p>
351      */

352     public static class AttributeDataSource implements DataSource {
353     /**
354      * <p> See class JavaDoc.</p>
355      *
356      * @param ctx The <code>FacesContext</code>
357      * @param desc The <code>LayoutElement</code>
358      * @param component The <code>UIComponent</code>
359      * @param key The key used to obtain information from this
360      * <code>DataSource</code>.
361      *
362      * @return The value resolved from key.
363      */

364     public Object JavaDoc getValue(FacesContext ctx, LayoutElement desc,
365         UIComponent component, String JavaDoc key) {
366         return ctx.getExternalContext().getRequestMap().get(key);
367     }
368     }
369
370     /**
371      * <p> This {@link VariableResolver.DataSource} provides access to
372      * PageSession attributes. It uses the data portion of the
373      * substitution String as a key to the PageSession attribute Map.</p>
374     public static class PageSessionDataSource implements DataSource {
375     /**
376      * <p> See class JavaDoc.</p>
377      *
378      * @param ctx The <code>FacesContext</code>
379      * @param desc The <code>LayoutElement</code>
380      * @param component The <code>UIComponent</code>
381      * @param key The key used to obtain information from this
382      * <code>DataSource</code>.
383      *
384      * @return The value resolved from key.
385     public Object getValue(FacesContext ctx, LayoutElement desc,
386         UIComponent component, String key) {
387         while (desc.getParent() != null) {
388         desc = desc.getParent();
389         }
390         return ((ViewBean)desc.getView(ctx)).getPageSessionAttribute(key);
391     }
392     }
393     */

394
395     /**
396      * <p> This {@link VariableResolver.DataSource} provides access to
397      * HttpRequest Parameters. It uses the data portion of the
398      * substitution String as a key to the HttpRequest Parameter Map.</p>
399      */

400     public static class RequestParameterDataSource implements DataSource {
401     /**
402      * <p> See class JavaDoc.</p>
403      *
404      * @param ctx The <code>FacesContext</code>
405      * @param desc The <code>LayoutElement</code>
406      * @param component The <code>UIComponent</code>
407      * @param key The key used to obtain information from this
408      * <code>DataSource</code>.
409      *
410      * @return The value resolved from key.
411      */

412     public Object JavaDoc getValue(FacesContext ctx, LayoutElement desc,
413         UIComponent component, String JavaDoc key) {
414         return ctx.getExternalContext().getRequestParameterMap().get(key);
415     }
416     }
417
418     /**
419      * <p> This {@link VariableResolver.DataSource} provides access to
420      * UIComponent Properties. It uses the data portion of the
421      * substitution String as a key to the UIComponent's properties via
422      * the attribute Map. If the property is null, it will attempt to
423      * look at the parent's properties.</p>
424      */

425     public static class PropertyDataSource implements DataSource {
426     /**
427      * <p> See class JavaDoc.</p>
428      *
429      * @param ctx The <code>FacesContext</code>
430      * @param desc The <code>LayoutElement</code>
431      * @param component The <code>UIComponent</code>
432      * @param key The key used to obtain information from this
433      * <code>DataSource</code>.
434      *
435      * @return The value resolved from key.
436      */

437     public Object JavaDoc getValue(FacesContext ctx, LayoutElement desc,
438         UIComponent component, String JavaDoc key) {
439
440         // Check to see if we should walk up the tree or not
441
int idx = key.indexOf(',');
442         boolean walk = false;
443         if (idx > 0) {
444         walk = Boolean.valueOf(key.substring(idx + 1)).booleanValue();
445         key = key.substring(0, idx);
446         }
447
448         Object JavaDoc value = component.getAttributes().get(key);
449         while (walk && (value == null) && (component.getParent() != null)) {
450         component = component.getParent();
451         value = component.getAttributes().get(key);
452         }
453 /*
454         if (LogUtil.finestEnabled()) {
455         // Trace information
456         LogUtil.finest(this, "RESOLVING ('" + key + "') for ('"
457             + component.getId() + "'): '" + value + "'");
458         }
459 */

460         return value;
461     }
462     }
463
464     /**
465      * <p> This {@link VariableResolver.DataSource} tests if the given
466      * property exists on the UIComponent. It uses the data portion of
467      * the substitution String as a key to the UIComponent's properties
468      * via the attribute Map.</p>
469      */

470     public static class HasPropertyDataSource implements DataSource {
471     /**
472      * <p> See class JavaDoc.</p>
473      *
474      * @param ctx The <code>FacesContext</code>
475      * @param desc The <code>LayoutElement</code>
476      * @param component The <code>UIComponent</code>
477      * @param key The key used to obtain information from this
478      * <code>DataSource</code>.
479      *
480      * @return The value resolved from key.
481      */

482     public Object JavaDoc getValue(FacesContext ctx, LayoutElement desc,
483         UIComponent component, String JavaDoc key) {
484         boolean hasKey = component.getAttributes().containsKey(key);
485         if (!hasKey) {
486         // Check the getter... JSF sucks when wrt attrs vs. props
487
if (component.getAttributes().get(key) != null) {
488             hasKey = true;
489         }
490         }
491         if (!hasKey && (desc instanceof LayoutComponent)) {
492         // In some cases, the component is a TemplateComponent child
493
return getValue(
494             ctx, desc.getParent(), component.getParent(), key);
495         }
496         return Boolean.valueOf(hasKey);
497     }
498     }
499
500     /**
501      * <p> This {@link VariableResolver.DataSource} tests if the given facet
502      * exists on the UIComponent. It uses the data portion of the
503      * substitution String as a key to the UIComponent's facets.</p>
504      */

505     public static class HasFacetDataSource implements DataSource {
506     /**
507      * <p> See class JavaDoc.</p>
508      *
509      * @param ctx The <code>FacesContext</code>
510      * @param desc The <code>LayoutElement</code>
511      * @param component The <code>UIComponent</code>
512      * @param key The key used to obtain information from this
513      * <code>DataSource</code>.
514      *
515      * @return The value resolved from key.
516      */

517     public Object JavaDoc getValue(FacesContext ctx, LayoutElement desc,
518         UIComponent component, String JavaDoc key) {
519         boolean hasFacet = component.getFacets().containsKey(key);
520         if (!hasFacet && (desc instanceof LayoutComponent)) {
521         // In some cases, the component is a TemplateComponent child
522
return getValue(
523             ctx, desc.getParent(), component.getParent(), key);
524         }
525         return Boolean.valueOf(hasFacet);
526     }
527     }
528
529     /**
530      * <p> This {@link VariableResolver.DataSource} simply returns the key
531      * that it is given. This is useful for supplying ${}'s around the
532      * string you wish to mark as a string. If not used, characters such
533      * as '=' will be interpretted as a separator causing your string to
534      * be split -- which can be very undesirable. Mostly useful in "if"
535      * statements.</p>
536      */

537     public static class EscapeDataSource implements DataSource {
538     /**
539      * <p> See class JavaDoc.</p>
540      *
541      * @param ctx The <code>FacesContext</code>
542      * @param desc The <code>LayoutElement</code>
543      * @param component The <code>UIComponent</code>
544      * @param key The key used to obtain information from this
545      * <code>DataSource</code>.
546      *
547      * @return The value resolved from key.
548      */

549     public Object JavaDoc getValue(FacesContext ctx, LayoutElement desc,
550         UIComponent component, String JavaDoc key) {
551         return key;
552     }
553     }
554
555     /**
556      * <p> This {@link VariableResolver.DataSource} converts the given
557      * <code>key</code> to a <code>Boolean</code>. This is needed because
558      * JSF does not do this for you. When you call
559      * <code>UIComponent.getAttributes().put(key, value)</code>,
560      * <code>value</code> is expected to be the correct type. Often
561      * <code>Boolean</code> types are needed. This
562      * {@link VariableResolver.DataSource} provides a means to supply a
563      * <code>Boolean</code> value.</p>
564      */

565     public static class BooleanDataSource implements DataSource {
566     /**
567      * <p> See class JavaDoc.</p>
568      *
569      * @param ctx The <code>FacesContext</code>
570      * @param desc The <code>LayoutElement</code>
571      * @param component The <code>UIComponent</code>
572      * @param key The key used to obtain information from this
573      * <code>DataSource</code>.
574      *
575      * @return The value resolved from key.
576      */

577     public Object JavaDoc getValue(FacesContext ctx, LayoutElement desc,
578         UIComponent component, String JavaDoc key) {
579         return Boolean.valueOf(key);
580     }
581     }
582
583     /**
584      * <p> This {@link VariableResolver.DataSource} uses the given
585      * <code>key</code> to check various properties of the browser that
586      * submitted the request. The valid keys are:</p>
587      *
588      * <ul><li>getUserAgent</li>
589      * <li>getUserAgentMajor</li>
590      * <li>isIe</li>
591      * <li>isNav</li>
592      * <li>isGecko</li>
593      * <li>isSun</li>
594      * <li>isWin</li>
595      * <li>isIe5up</li>
596      * <li>isIe6up</li>
597      * <li>isNav7up</li>
598      * <li>isIe6</li>
599      * <li>isIe5</li>
600      * <li>isIe4</li>
601      * <li>isIe3</li>
602      * <li>isNav70</li>
603      * <li>isNav7</li>
604      * <li>isNav6up</li>
605      * <li>isNav6</li>
606      * <li>isNav4up</li>
607      * <li>isNav4</li></ul>
608      *
609      * See Lockhart's <code>ClientSniffer</code>.
610      */

611     public static class BrowserDataSource implements DataSource {
612     /**
613      * <p> See class JavaDoc.</p>
614      *
615      * @param ctx The <code>FacesContext</code>
616      * @param desc The <code>LayoutElement</code>
617      * @param component The <code>UIComponent</code>
618      * @param key The key used to obtain information from this
619      * <code>DataSource</code>.
620      *
621      * @return The value resolved from key.
622      */

623     public Object JavaDoc getValue(FacesContext ctx, LayoutElement desc,
624         UIComponent component, String JavaDoc key) {
625         DataSource ds = (DataSource) innerDataSources.get(key);
626         if (ds == null) {
627         throw new IllegalArgumentException JavaDoc("'" + key
628             + "' is not a valid key for BrowserDataSource!");
629         }
630         return ds.getValue(ctx, desc, component, key);
631     }
632
633     /**
634      * <p> For efficiency, we will implement the branching as a Map of
635      * DataSources.</p>
636      */

637     private static Map JavaDoc innerDataSources = new HashMap JavaDoc();
638
639     static {
640         innerDataSources.put("getUserAgent", new DataSource() {
641             public Object JavaDoc getValue(FacesContext ctx, LayoutElement desc,
642                 UIComponent component, String JavaDoc key) {
643             return ClientSniffer.getInstance(ctx).getUserAgent();
644             }
645         });
646         innerDataSources.put("getUserAgentMajor", new DataSource() {
647             public Object JavaDoc getValue(FacesContext ctx, LayoutElement desc,
648                 UIComponent component, String JavaDoc key) {
649             return new Integer JavaDoc(
650                 ClientSniffer.getInstance(ctx).getUserAgentMajor());
651             }
652         });
653         innerDataSources.put("isIe", new DataSource() {
654             public Object JavaDoc getValue(FacesContext ctx, LayoutElement desc,
655                 UIComponent component, String JavaDoc key) {
656             return Boolean.valueOf(
657                 ClientSniffer.getInstance(ctx).isIe());
658             }
659         });
660         innerDataSources.put("isNav", new DataSource() {
661             public Object JavaDoc getValue(FacesContext ctx, LayoutElement desc,
662                 UIComponent component, String JavaDoc key) {
663             return Boolean.valueOf(
664                 ClientSniffer.getInstance(ctx).isNav());
665             }
666         });
667         innerDataSources.put("isGecko", new DataSource() {
668             public Object JavaDoc getValue(FacesContext ctx, LayoutElement desc,
669                 UIComponent component, String JavaDoc key) {
670             return Boolean.valueOf(
671                 ClientSniffer.getInstance(ctx).isGecko());
672             }
673         });
674         innerDataSources.put("isSun", new DataSource() {
675             public Object JavaDoc getValue(FacesContext ctx, LayoutElement desc,
676                 UIComponent component, String JavaDoc key) {
677             return Boolean.valueOf(
678                 ClientSniffer.getInstance(ctx).isSun());
679             }
680         });
681         innerDataSources.put("isWin", new DataSource() {
682             public Object JavaDoc getValue(FacesContext ctx, LayoutElement desc,
683                 UIComponent component, String JavaDoc key) {
684             return Boolean.valueOf(
685                 ClientSniffer.getInstance(ctx).isWin());
686             }
687         });
688         innerDataSources.put("isIe5up", new DataSource() {
689             public Object JavaDoc getValue(FacesContext ctx, LayoutElement desc,
690                 UIComponent component, String JavaDoc key) {
691             return Boolean.valueOf(
692                 ClientSniffer.getInstance(ctx).isIe5up());
693             }
694         });
695         innerDataSources.put("isIe6up", new DataSource() {
696             public Object JavaDoc getValue(FacesContext ctx, LayoutElement desc,
697                 UIComponent component, String JavaDoc key) {
698             return Boolean.valueOf(
699                 ClientSniffer.getInstance(ctx).isIe6up());
700             }
701         });
702         innerDataSources.put("isNav7up", new DataSource() {
703             public Object JavaDoc getValue(FacesContext ctx, LayoutElement desc,
704                 UIComponent component, String JavaDoc key) {
705             return Boolean.valueOf(
706                 ClientSniffer.getInstance(ctx).isNav7up());
707             }
708         });
709         innerDataSources.put("isIe6", new DataSource() {
710             public Object JavaDoc getValue(FacesContext ctx, LayoutElement desc,
711                 UIComponent component, String JavaDoc key) {
712             return Boolean.valueOf(
713                 ClientSniffer.getInstance(ctx).isIe6());
714             }
715         });
716         innerDataSources.put("isIe5", new DataSource() {
717             public Object JavaDoc getValue(FacesContext ctx, LayoutElement desc,
718                 UIComponent component, String JavaDoc key) {
719             return Boolean.valueOf(
720                 ClientSniffer.getInstance(ctx).isIe5());
721             }
722         });
723         innerDataSources.put("isIe4", new DataSource() {
724             public Object JavaDoc getValue(FacesContext ctx, LayoutElement desc,
725                 UIComponent component, String JavaDoc key) {
726             return Boolean.valueOf(
727                 ClientSniffer.getInstance(ctx).isIe4());
728             }
729         });
730         innerDataSources.put("isIe3", new DataSource() {
731             public Object JavaDoc getValue(FacesContext ctx, LayoutElement desc,
732                 UIComponent component, String JavaDoc key) {
733             return Boolean.valueOf(
734                 ClientSniffer.getInstance(ctx).isIe3());
735             }
736         });
737         innerDataSources.put("isNav70", new DataSource() {
738             public Object JavaDoc getValue(FacesContext ctx, LayoutElement desc,
739                 UIComponent component, String JavaDoc key) {
740             return Boolean.valueOf(
741                 ClientSniffer.getInstance(ctx).isNav70());
742             }
743         });
744         innerDataSources.put("isNav7", new DataSource() {
745             public Object JavaDoc getValue(FacesContext ctx, LayoutElement desc,
746                 UIComponent component, String JavaDoc key) {
747             return Boolean.valueOf(
748                 ClientSniffer.getInstance(ctx).isNav7());
749             }
750         });
751         innerDataSources.put("isNav6up", new DataSource() {
752             public Object JavaDoc getValue(FacesContext ctx, LayoutElement desc,
753                 UIComponent component, String JavaDoc key) {
754             return Boolean.valueOf(
755                 ClientSniffer.getInstance(ctx).isNav6up());
756             }
757         });
758         innerDataSources.put("isNav6", new DataSource() {
759             public Object JavaDoc getValue(FacesContext ctx, LayoutElement desc,
760                 UIComponent component, String JavaDoc key) {
761             return Boolean.valueOf(
762                 ClientSniffer.getInstance(ctx).isNav6());
763             }
764         });
765         innerDataSources.put("isNav4up", new DataSource() {
766             public Object JavaDoc getValue(FacesContext ctx, LayoutElement desc,
767                 UIComponent component, String JavaDoc key) {
768             return Boolean.valueOf(
769                 ClientSniffer.getInstance(ctx).isNav4up());
770             }
771         });
772         innerDataSources.put("isNav4", new DataSource() {
773             public Object JavaDoc getValue(FacesContext ctx, LayoutElement desc,
774                 UIComponent component, String JavaDoc key) {
775             return Boolean.valueOf(
776                 ClientSniffer.getInstance(ctx).isNav4());
777             }
778         });
779     }
780     }
781
782     /**
783      * <p> This {@link VariableResolver.DataSource} converts the given
784      * <code>key</code> to an <code>Integer</code>. This is needed
785      * because JSF does not do this for you. When you call
786      * <code>UIComponent.getAttributes().put(key, value)</code>,
787      * <code>value</code> is expected to be the correct type. Often
788      * <code>Integer</code> types are needed. This
789      * {@link VariableResolver.DataSource} provides a means to supply an
790      * <code>Integer</code> value.</p>
791      */

792     public static class IntDataSource implements DataSource {
793     /**
794      * <p> See class JavaDoc.</p>
795      *
796      * @param ctx The <code>FacesContext</code>
797      * @param desc The <code>LayoutElement</code>
798      * @param component The <code>UIComponent</code>
799      * @param key The key used to obtain information from this
800      * <code>DataSource</code>.
801      *
802      * @return The value resolved from key.
803      */

804     public Object JavaDoc getValue(FacesContext ctx, LayoutElement desc,
805         UIComponent component, String JavaDoc key) {
806         return Integer.valueOf(key);
807     }
808     }
809
810     /**
811      * <p> This {@link VariableResolver.DataSource} allows access to constants
812      * in java classes. It expects the key to be a fully qualified Java
813      * classname plus the variable name. Example:</p>
814      *
815      * <p> $constant{java.lang.Integer.MAX_VALUE} </p>
816      */

817     public static class ConstantDataSource implements DataSource {
818     /**
819      * <p> See class JavaDoc.</p>
820      *
821      * @param ctx The <code>FacesContext</code>
822      * @param desc The <code>LayoutElement</code>
823      * @param component The <code>UIComponent</code>
824      * @param key The key used to obtain information from this
825      * <code>DataSource</code>.
826      *
827      * @return The value resolved from key.
828      */

829     public Object JavaDoc getValue(FacesContext ctx, LayoutElement desc,
830         UIComponent component, String JavaDoc key) {
831         // First check to see if we've already found the value before.
832
Object JavaDoc value = constantMap.get(key);
833         if (value == null) {
834         // Not found, lets resolve it, duplicate the old Map to avoid
835
// sync problems
836
Map JavaDoc map = new HashMap JavaDoc(constantMap);
837         value = resolveValue(map, key);
838
839         // Replace the shared Map w/ this new one.
840
constantMap = map;
841         }
842         return value;
843     }
844
845     /**
846      * <p> This method resolves key. Key is expected to be in the
847      * format:</p>
848      *
849      * <p> some.package.Class.STATIC_VARIBLE</p>
850      *
851      * <p> This method will first resolve Class. It will then walk
852      * through all its variables adding each static final variable to
853      * the Map.</p>
854      *
855      * @param map The map to add variables to
856      * @param key The fully qualified CONSTANT name
857      *
858      * @return The value of the CONSTANT, or null if not found
859      */

860     private Object JavaDoc resolveValue(Map JavaDoc map, String JavaDoc key) {
861         int lastDot = key.lastIndexOf('.');
862         if (lastDot == -1) {
863         throw new IllegalArgumentException JavaDoc("Unable to resolve '" + key
864             + "' in $constant{" + key + "}. '" + key + "' must be a "
865             + "fully qualified classname plus the constant name.");
866         }
867
868         // Get the classname / constant name
869
String JavaDoc className = key.substring(0, lastDot);
870
871         // Add all constants to the Map
872
try {
873         addConstants(map, Class.forName(className));
874         } catch (ClassNotFoundException JavaDoc ex) {
875         RuntimeException JavaDoc iae = new IllegalArgumentException JavaDoc("'"
876             + className + "' was not found! This must be a valid "
877             + "classname. This was found in expression $constant{"
878             + key + "}.");
879         iae.initCause(ex);
880         throw iae;
881         }
882
883         // The constant hopefully is in the Map now, null if not
884
return map.get(key);
885     }
886
887     /**
888      * This method adds all constants in the given class to the Map. The
889      * Map key will be the fully qualified class name, plus a '.', plus
890      * the constant name.
891      *
892      * @param map <code>Map</code> to store <code>cls</code>
893      * @param cls The <code>Class</code> to store in <code>map</code>
894      */

895     private void addConstants(Map JavaDoc map, Class JavaDoc cls) {
896         // Get the class name
897
String JavaDoc className = cls.getName();
898
899         // Get the fields
900
Field JavaDoc[] fields = cls.getFields();
901
902         // Add the static final fields to the Map
903
Field JavaDoc field = null;
904         for (int count = 0; count < fields.length; count++) {
905         field = fields[count];
906         if (Modifier.isStatic(field.getModifiers())
907             && Modifier.isFinal(field.getModifiers())) {
908             try {
909             map.put(className + '.' + field.getName(),
910                 field.get(null));
911             } catch (IllegalAccessException JavaDoc ex) {
912             throw new RuntimeException JavaDoc(ex);
913             }
914         }
915         }
916     }
917
918     /**
919      * This embedded Map caches constant value lookups. It is static and
920      * is shared by all users.
921      */

922     private static Map JavaDoc constantMap = new HashMap JavaDoc();
923     }
924
925     /**
926      * <p> This {@link VariableResolver.DataSource} creates a MethodBinding
927      * from the supplied key. Example:</p>
928      *
929      * <p> $methodBinding{#{bean.bundleKey}}</p>
930      */

931     public static class MethodBindingDataSource implements DataSource {
932     /**
933      * <p> See class JavaDoc.</p>
934      *
935      * @param ctx The <code>FacesContext</code>
936      * @param desc The <code>LayoutElement</code>
937      * @param component The <code>UIComponent</code>
938      * @param key The key used to obtain information from this
939      * <code>DataSource</code>.
940      *
941      * @return The value resolved from key.
942      */

943     public Object JavaDoc getValue(FacesContext ctx, LayoutElement desc,
944         UIComponent component, String JavaDoc key) {
945         return ctx.getApplication().createMethodBinding(key, actionArgs);
946     }
947     }
948
949     /**
950      * <p> This {@link VariableResolver.DataSource} allows access to resource
951      * bundle keys. It expects the key to be a resource bundle key plus a
952      * '.' then the actual resouce bundle key Example:</p>
953      *
954      * <p> $resource{bundleID.bundleKey} </p>
955      *
956      * <p> The bundleID should not contain '.' characters. The bundleKey
957      * may.</p>
958      */

959     public static class ResourceBundleDataSource implements DataSource {
960     /**
961      * <p> See class JavaDoc.</p>
962      *
963      * @param ctx The <code>FacesContext</code>
964      * @param desc The <code>LayoutElement</code>
965      * @param component The <code>UIComponent</code>
966      * @param key The key used to obtain information from this
967      * <code>DataSource</code>.
968      *
969      * @return The value resolved from key.
970      */

971     public Object JavaDoc getValue(FacesContext ctx, LayoutElement desc,
972         UIComponent component, String JavaDoc key) {
973         // Get the Request attribute key
974
int separator = key.indexOf(".");
975         if (separator == -1) {
976         throw new IllegalArgumentException JavaDoc("'" + key
977             + "' is not in format: \"[bundleID].[bundleKey]\"!");
978         }
979         String JavaDoc value = key.substring(0, separator);
980
981         // Get the Resource Bundle
982
ResourceBundle JavaDoc bundle = (ResourceBundle JavaDoc) ctx.getExternalContext().
983             getRequestMap().get(value);
984
985         // Make sure we have the bundle
986
if (bundle == null) {
987         // Should we throw an exception? For now just return the key
988
return key;
989         }
990
991         // Return the result of the ResouceBundle lookup
992
value = bundle.getString(key.substring(separator + 1));
993         if (value == null) {
994         value = key;
995         }
996
997         return value;
998     }
999     }
1000
1001    /**
1002     * <p> This {@link VariableResolver.DataSource} provides access to
1003     * HttpSession attributes. It uses the data portion of the
1004     * substitution String as a key to the HttpSession Map.</p>
1005     */

1006    public static class SessionDataSource implements DataSource {
1007    /**
1008     * <p> See class JavaDoc.</p>
1009     *
1010     * @param ctx The <code>FacesContext</code>
1011     * @param desc The <code>LayoutElement</code>
1012     * @param component The <code>UIComponent</code>
1013     * @param key The key used to obtain information from this
1014     * <code>DataSource</code>.
1015     *
1016     * @return The value resolved from key.
1017     */

1018    public Object JavaDoc getValue(FacesContext ctx, LayoutElement desc,
1019        UIComponent component, String JavaDoc key) {
1020        return ctx.getExternalContext().getSessionMap().get(key);
1021    }
1022    }
1023
1024    /**
1025     * <p> This {@link VariableResolver.DataSource} returns a strack trace
1026     * from the current <code>com.sun.web.ui.theme.Theme</code>. The data
1027     * portion of the substitution String as an message.</p>
1028     */

1029    public static class StackTraceDataSource implements DataSource {
1030    /**
1031     * <p> See class JavaDoc.</p>
1032     *
1033     * @param ctx The <code>FacesContext</code>
1034     * @param desc The <code>LayoutElement</code>
1035     * @param component The <code>UIComponent</code>
1036     * @param key The key used to obtain information from this
1037     * <code>DataSource</code>.
1038     *
1039     * @return The value resolved from key.
1040     */

1041    public Object JavaDoc getValue(FacesContext ctx, LayoutElement desc,
1042        UIComponent component, String JavaDoc key) {
1043        // Get the trace information
1044
StackTraceElement JavaDoc[] trace = Thread.currentThread().getStackTrace();
1045        int len = trace.length;
1046
1047        // Create a String w/ this info...
1048
StringBuffer JavaDoc buf = new StringBuffer JavaDoc(key + "\n");
1049        for (int idx = 0; idx < len; idx++) {
1050        buf.append(trace[idx] + "\n");
1051        }
1052
1053        // Return it.
1054
return buf.toString();
1055    }
1056    }
1057
1058    /**
1059     * <p> This {@link VariableResolver.DataSource} retrieves style classes
1060     * from the current <code>com.sun.web.ui.theme.Theme</code>. The data
1061     * portion of the substitution String as the
1062     * <code>com.sun.web.ui.theme.Theme</code> key.</p>
1063     */

1064    public static class StyleDataSource implements DataSource {
1065    /**
1066     * <p> See class JavaDoc.</p>
1067     *
1068     * @param ctx The <code>FacesContext</code>
1069     * @param desc The <code>LayoutElement</code>
1070     * @param component The <code>UIComponent</code>
1071     * @param key The key used to obtain information from this
1072     * <code>DataSource</code>.
1073     *
1074     * @return The value resolved from key.
1075     */

1076    public Object JavaDoc getValue(FacesContext ctx, LayoutElement desc,
1077        UIComponent component, String JavaDoc key) {
1078        return ThemeUtilities.getTheme(ctx).getStyleClass(key);
1079    }
1080    }
1081
1082    /**
1083     * <p> This {@link VariableResolver.DataSource} retrieves Theme messages
1084     * from the <code>com.sun.web.ui.theme.Theme</code>. The data portion
1085     * of the substitution String is the
1086     * <code>com.sun.web.ui.theme.Theme</code> message key.</p>
1087     */

1088    public static class ThemeDataSource implements DataSource {
1089    /**
1090     * <p> See class JavaDoc.</p>
1091     *
1092     * @param ctx The <code>FacesContext</code>
1093     * @param desc The <code>LayoutElement</code>
1094     * @param component The <code>UIComponent</code>
1095     * @param key The key used to obtain information from this
1096     * <code>DataSource</code>.
1097     *
1098     * @return The value resolved from key.
1099     */

1100    public Object JavaDoc getValue(FacesContext ctx, LayoutElement desc,
1101        UIComponent component, String JavaDoc key) {
1102        return ThemeUtilities.getTheme(ctx).getMessage(key);
1103    }
1104    }
1105
1106    /**
1107     * <p> This {@link VariableResolver.DataSource} retrieves the path to a
1108     * JavaScript file from the <code>com.sun.web.ui.theme.Theme</code>.
1109     * The data portion of the substitution String is the
1110     * <code>com.sun.web.ui.theme.Theme</code> key for the JavaScript
1111     * file.</p>
1112     */

1113    public static class ThemeJavaScriptDataSource implements DataSource {
1114    /**
1115     * <p> See class JavaDoc.</p>
1116     *
1117     * @param ctx The <code>FacesContext</code>
1118     * @param desc The <code>LayoutElement</code>
1119     * @param component The <code>UIComponent</code>
1120     * @param key The key used to obtain information from this
1121     * <code>DataSource</code>.
1122     *
1123     * @return The value resolved from key.
1124     */

1125    public Object JavaDoc getValue(FacesContext ctx, LayoutElement desc,
1126        UIComponent component, String JavaDoc key) {
1127        return ThemeUtilities.getTheme(ctx).getPathToJSFile(key);
1128    }
1129    }
1130
1131    /**
1132     * <p> This {@link VariableResolver.DataSource} provides access to
1133     * DisplayField values. It uses the data portion of the substitution
1134     * String as the DisplayField name to find. This is a non-qualified
1135     * DisplayField name. It will walk up the View tree starting at the
1136     * View object cooresponding to the LayoutElement which contained this
1137     * expression. At each ContainerView, it will look for a child with
1138     * a matching name.</p>
1139    public static class DisplayFieldDataSource implements DataSource {
1140    public Object getValue(FacesContext ctx, LayoutElement desc,
1141        UIComponent component, String key) {
1142        while (desc != null) {
1143        View view = desc.getView(ctx);
1144        if (view instanceof ContainerView) {
1145            View child = null;
1146//FIXME: use a better way to find if 'key' is a child of 'view'
1147            try {
1148            child = (((ContainerView)(view)).getChild(key));
1149            } catch (Exception ex) {
1150            }
1151            if (child != null) {
1152            return ((ContainerView) view).getDisplayFieldValue(key);
1153            }
1154        }
1155        desc = desc.getParent();
1156        }
1157        return null;
1158    }
1159    }
1160    */

1161
1162    /**
1163     * <p> This class provides an implementation for the syntax $this{xyz}
1164     * where xyz can be any of the following.</p>
1165     *
1166     * <ul><li>component -- Current <code>UIComponent</code></li>
1167     * <li>clientId -- Current <code>UIComponent</code>'s client id</li>
1168     * <li>id -- Current <code>UIComponent</code>'s id</li>
1169     * <li>layoutElement -- Current {@link LayoutElement}</li>
1170     * <li>parent -- Parent <code>UIComponent</code></li>
1171     * <li>parentId -- Parent <code>UIComponent</code>'s client id</li>
1172     * <li>parentLayoutElement -- Parent {@link LayoutElement}</li>
1173     * <li>namingContainer -- Nearest <code>NamingContainer</code></li>
1174     * <li>valueBinding -- <code>ValueBinding</code> representing the
1175     * <code>UIComponent</code></li>
1176     * </ul>
1177     */

1178    public static class ThisDataSource implements DataSource {
1179    /**
1180     * <p> See class JavaDoc.</p>
1181     *
1182     * @param ctx The <code>FacesContext</code>
1183     * @param desc The <code>LayoutElement</code>
1184     * @param comp The <code>UIComponent</code>
1185     * @param key The key used to obtain information from this
1186     * <code>DataSource</code>.
1187     *
1188     * @return The value resolved from key.
1189     */

1190    public Object JavaDoc getValue(FacesContext ctx, LayoutElement desc,
1191        UIComponent comp, String JavaDoc key) {
1192        Object JavaDoc value = null;
1193
1194        if ((key.equalsIgnoreCase(CLIENT_ID)) || (key.length() == 0)) {
1195        value = comp.getClientId(ctx);
1196        } else if (key.equalsIgnoreCase(ID)) {
1197        value = comp.getId();
1198        } else if (key.equalsIgnoreCase(COMPONENT)) {
1199        value = comp;
1200        } else if (key.equalsIgnoreCase(LAYOUT_ELEMENT)) {
1201        value = desc;
1202        } else if (key.equalsIgnoreCase(PARENT_ID)) {
1203        value = comp.getParent().getId();
1204        } else if (key.equalsIgnoreCase(PARENT_CLIENT_ID)) {
1205        value = comp.getParent().getClientId(ctx);
1206        } else if (key.equalsIgnoreCase(PARENT)) {
1207        value = comp.getParent();
1208        } else if (key.equalsIgnoreCase(PARENT_LAYOUT_ELEMENT)) {
1209        value = desc.getParent();
1210        } else if (key.equalsIgnoreCase(NAMING_CONTAINER)) {
1211        for (value = comp.getParent(); value != null;
1212            value = ((UIComponent) value).getParent()) {
1213            if (value instanceof NamingContainer) {
1214            break;
1215            }
1216        }
1217        } else if (key.equalsIgnoreCase(VALUE_BINDING)) {
1218        // Walk backward up the tree generate the path
1219
Stack JavaDoc stack = new Stack JavaDoc();
1220        String JavaDoc id = null;
1221        // FIXME: b/c of a bug, the old behavior actually returned the
1222
// FIXME: parent component... the next line is here to persist
1223
// FIXME: this behavior b/c some code depends on this, fix this
1224
// FIXME: when you have a chance.
1225
comp = comp.getParent();
1226        while ((comp != null) && !(comp instanceof UIViewRoot)) {
1227            id = comp.getId();
1228            if (id == null) {
1229            // Generate an id based on the clientId
1230
id = comp.getClientId(ctx);
1231            id = id.substring(id.lastIndexOf(
1232                NamingContainer.SEPARATOR_CHAR) + 1);
1233            }
1234            stack.push(id);
1235            comp = comp.getParent();
1236        }
1237        StringBuffer JavaDoc buf = new StringBuffer JavaDoc();
1238        buf.append("view");
1239        while (!stack.empty()) {
1240            buf.append("." + stack.pop());
1241        }
1242        value = buf.toString();
1243        } else {
1244        throw new IllegalArgumentException JavaDoc("'" + key
1245            + "' is not valid in $this{" + key + "}.");
1246        }
1247
1248        return value;
1249    }
1250
1251    /**
1252     * <p> Defines "component" in $this{component}. Returns the
1253     * UIComponent object.</p>
1254     */

1255    public static final String JavaDoc COMPONENT = "component";
1256
1257    /**
1258     * <p> Defines "clientId" in $this{clientId}. Returns
1259     * the String representing the client id for the UIComponent.</p>
1260     */

1261    public static final String JavaDoc CLIENT_ID = "clientId";
1262
1263    /**
1264     * <p> Defines "id" in $this{id}. Returns the String representing
1265     * the id for the UIComponent.</p>
1266     */

1267    public static final String JavaDoc ID = "id";
1268
1269    /**
1270     * <p> Defines "layoutElement" in $this{layoutElement}. Returns
1271     * the LayoutElement.</p>
1272     */

1273    public static final String JavaDoc LAYOUT_ELEMENT = "layoutElement";
1274
1275    /**
1276     * <p> Defines "parent" in $this{parent}. Returns the
1277     * parent UIComponent object.</p>
1278     */

1279    public static final String JavaDoc PARENT = "parent";
1280
1281    /**
1282     * <p> Defines "parentId" in $this{parentId}. Returns the
1283     * parent UIComponent object's Id.</p>
1284     */

1285    public static final String JavaDoc PARENT_ID = "parentId";
1286
1287    /**
1288     * <p> Defines "parentClientId" in $this{parentClientId}. Returns the
1289     * parent UIComponent object's client Id.</p>
1290     */

1291    public static final String JavaDoc PARENT_CLIENT_ID = "parentClientId";
1292
1293    /**
1294     * <p> Defines "parentLayoutElement" in $this{parentLayoutElement}.
1295     * Returns the parent LayoutElement.</p>
1296     */

1297    public static final String JavaDoc PARENT_LAYOUT_ELEMENT =
1298        "parentLayoutElement";
1299
1300    /**
1301     * <p> Defines "namingContainer" in $this{namingContainer}. Returns
1302     * the nearest naming container object (i.e. the form).</p>
1303     */

1304    public static final String JavaDoc NAMING_CONTAINER = "namingContainer";
1305
1306    /**
1307     * <p> Defines "valueBinding" in $this{valueBinding}. Returns
1308     * a <code>ValueBinding</code> to this UIComponent.</p>
1309     */

1310    public static final String JavaDoc VALUE_BINDING = "valueBinding";
1311    }
1312
1313    /**
1314     * The main function for this class provides some simple test cases.
1315     *
1316     * @param args The commandline arguments.
1317     */

1318    public static void main(String JavaDoc[] args) {
1319    String JavaDoc test = null;
1320    String JavaDoc good = null;
1321
1322    test = "" + VariableResolver.resolveVariables(null, null, null,
1323        "$escape($escape(LayoutElement))", "$", "(", ")");
1324    good = "LayoutElement";
1325    System.out.println("Expected Result: '" + good + "'");
1326    System.out.println(" Result: '" + test + "'");
1327    if (!test.equals(good)) {
1328        System.out.println("FAILED!!!!");
1329    }
1330
1331    test = "" + VariableResolver.resolveVariables(null, null, null,
1332        "$escape($escape(EEPersistenceManager))", "$", "(", ")");
1333    good = "EEPersistenceManager";
1334    System.out.println("Expected Result: '" + good + "'");
1335    System.out.println(" Result: '" + test + "'");
1336    if (!test.equals(good)) {
1337        System.out.println("FAILED!!!!");
1338    }
1339
1340    test = "" + VariableResolver.resolveVariables(null, null, null,
1341        "$es$cape$escape(EEPersistenceManager))", "$", "(", ")");
1342    good = "$es$capeEEPersistenceManager)";
1343    System.out.println("Expected Result: '" + good + "'");
1344    System.out.println(" Result: '" + test + "'");
1345    if (!test.equals(good)) {
1346        System.out.println("FAILED!!!!");
1347    }
1348
1349    test = "" + VariableResolver.resolveVariables(null, null, null,
1350        "$escape($escapeEEP$ersistenceManager))", "$", "(", ")");
1351    good = "$escapeEEP$ersistenceManager)";
1352    System.out.println("Expected Result: '" + good + "'");
1353    System.out.println(" Result: '" + test + "'");
1354    if (!test.equals(good)) {
1355        System.out.println("FAILED!!!!");
1356    }
1357
1358    test = "" + VariableResolver.resolveVariables(null, null, null,
1359        "$escape($escape(EEPersistenceManager)))", "$", "(", ")");
1360    good = "EEPersistenceManager)";
1361    System.out.println("Expected Result: '" + good + "'");
1362    System.out.println(" Result: '" + test + "'");
1363    if (!test.equals(good)) {
1364        System.out.println("FAILED!!!!");
1365    }
1366
1367    test = "" + VariableResolver.resolveVariables(null, null, null,
1368        "$escape($escape(EEPersistenceManager())", "$", "(", ")");
1369    good = "$escape(EEPersistenceManager()";
1370    System.out.println("Expected Result: '" + good + "'");
1371    System.out.println(" Result: '" + test + "'");
1372    if (!test.equals(good)) {
1373        System.out.println("FAILED!!!!");
1374    }
1375
1376    test = "" + VariableResolver.resolveVariables(null, null, null,
1377        "$escape($escape($escape(EEPersistenceManager()))==$escape("
1378        + "EEPersistenceManager()))", "$", "(", ")");
1379    good = "EEPersistenceManager()==EEPersistenceManager()";
1380    System.out.println("Expected Result: '" + good + "'");
1381    System.out.println(" Result: '" + test + "'");
1382    if (!test.equals(good)) {
1383        System.out.println("FAILED!!!!");
1384    }
1385
1386    test = "" + VariableResolver.resolveVariables(null, null, null,
1387        "$escape($escape($escape(EEPersistenceManager()))==$escape("
1388        + "EEPersistenceManager()))", "$", "(", ")");
1389    good = "EEPersistenceManager()==EEPersistenceManager()";
1390    System.out.println("Expected Result: '" + good + "'");
1391    System.out.println(" Result: '" + test + "'");
1392    if (!test.equals(good)) {
1393        System.out.println("FAILED!!!!");
1394    }
1395
1396    /*
1397    for (int x = 0; x < 100000; x++) {
1398        System.out.println("" + VariableResolver.resolveVariables(
1399        null, null, null,
1400        "$escape($escape(EEPers" + x + "istenceManager()))==$escape("
1401        + "EEPersistenceManager())", "$", "(", ")"));
1402    }
1403    */

1404    }
1405
1406
1407    /**
1408     * <p> Contains the {@link VariableResolver.DataSource}'s for
1409     * $&lt;type&gt;{&lt;variable&gt;} syntax.</p>
1410     */

1411    private static Map JavaDoc dataSourceMap = new HashMap JavaDoc();
1412
1413    /**
1414     * <p> Defines "attribute" in $attribute{...}. This allows you to
1415     * retrieve an HttpRequest attribute.</p>
1416     */

1417    public static final String JavaDoc ATTRIBUTE = "attribute";
1418
1419    /**
1420     * <p> Defines "pageSession" in $pageSession{...}. This allows you to
1421     * retrieve a PageSession attribute.</p>
1422    public static final String PAGE_SESSION = "pageSession";
1423    */

1424
1425    /**
1426     * <p> Defines "property" in $property{...}. This allows you to
1427     * retrieve a property from the UIComponent.</p>
1428     */

1429    public static final String JavaDoc PROPERTY = "property";
1430
1431    /**
1432     * <p> Defines "hasProperty" in $hasProperty{...}. This allows you to
1433     * see if a property from the UIComponent exists.</p>
1434     */

1435    public static final String JavaDoc HAS_PROPERTY = "hasProperty";
1436
1437    /**
1438     * <p> Defines "hasFacet" in $hasFacet{...}. This allows you to
1439     * see if a facet from the UIComponent exists.</p>
1440     */

1441    public static final String JavaDoc HAS_FACET = "hasFacet";
1442
1443    /**
1444     * <p> Defines "session" in $session{...}. This allows you to retrieve
1445     * an HttpSession attribute.
1446     */

1447    public static final String JavaDoc SESSION = "session";
1448
1449    /**
1450     * <p> Defines "stackTrace" in $stackTrace{...}. This allows you to get
1451     * a stack trace from the current <code>Thread</code>.
1452     */

1453    public static final String JavaDoc STACK_TRACE = "stackTrace";
1454
1455    /**
1456     * <p> Defines "style" in $style{...}. This allows you to retrieve
1457     * a style classes from the current
1458     * <code>com.sun.web.ui.theme.Theme</code>.</p>
1459     */

1460    public static final String JavaDoc STYLE = "style";
1461
1462    /**
1463     * <p> Defines "theme" in $theme{...}. This allows you to
1464     * retrieve a Theme message from the current
1465     * <code>com.sun.web.ui.theme.Theme</code>.
1466     */

1467    public static final String JavaDoc THEME = "theme";
1468
1469    /**
1470     * <p> Defines "themeScript" in $themeScript{...}. This allows you to
1471     * retrieve a JavaScript classes from the current
1472     * <code>com.sun.web.ui.theme.Theme</code>.
1473     */

1474    public static final String JavaDoc THEME_JS = "themeScript";
1475
1476    /**
1477     * <p> Defines "requestParameter" in $requestParameter{...}. This allows
1478     * you to retrieve a HttpRequest parameter (QUERY_STRING
1479     * parameter).</p>
1480     */

1481    public static final String JavaDoc REQUEST_PARAMETER = "requestParameter";
1482
1483    /**
1484     * <p> Defines "display" in $display{...}. This allows you to retrive
1485     * a DisplayField value.</p>
1486    public static final String DISPLAY = "display";
1487     */

1488
1489    /**
1490     * <p> Defines "this" in $this{...}. This allows you to retrieve a
1491     * number of different objects related to the relative placement of
1492     * this expression.</p>
1493     *
1494     * @see ThisDataSource
1495     */

1496    public static final String JavaDoc THIS = "this";
1497
1498    /**
1499     * <p> Defines "escape" in $escape{...}. This allows some reserved
1500     * characters to be escaped in "if" attributes. Such as '=' or
1501     * '|'.</p>
1502     */

1503    public static final String JavaDoc ESCAPE = "escape";
1504
1505    /**
1506     * <p> Defines "boolean" in $boolean{...}. This converts the given
1507     * String to a Boolean.</p>
1508     */

1509    public static final String JavaDoc BOOLEAN = "boolean";
1510
1511    /**
1512     * <p> Defines "browser" in $browser{...}. This checks properties of the
1513     * browser that sent the request.</p>
1514     */

1515    public static final String JavaDoc BROWSER = "browser";
1516
1517    /**
1518     * <p> Defines "int" in $int{...}. This converts the given String to an
1519     * Integer.</p>
1520     */

1521    public static final String JavaDoc INT = "int";
1522
1523    /**
1524     * <p> Defines "methodBinding" in $methodBinding{...}. This allows
1525     * MethodBindings in to be created.</p>
1526     */

1527    public static final String JavaDoc METHOD_BINDING = "methodBinding";
1528
1529    /**
1530     * <p> Defines "constant" in $constant{...}. This allows constants
1531     * in java classes to be accessed.</p>
1532     */

1533    public static final String JavaDoc CONSTANT = "constant";
1534
1535    /**
1536     * <p> Defines "resource" in $resource{...}. This allows resource
1537     * to be accessed.</p>
1538     */

1539    public static final String JavaDoc RESOURCE = "resource";
1540
1541
1542    // Static initializer to setup DataSources
1543
static {
1544    AttributeDataSource attrDS = new AttributeDataSource();
1545    dataSourceMap.put(ATTRIBUTE, attrDS);
1546    dataSourceMap.put("", attrDS);
1547// dataSourceMap.put(PAGE_SESSION, new PageSessionDataSource());
1548
dataSourceMap.put(PROPERTY, new PropertyDataSource());
1549    dataSourceMap.put(HAS_PROPERTY, new HasPropertyDataSource());
1550    dataSourceMap.put(HAS_FACET, new HasFacetDataSource());
1551    dataSourceMap.put(SESSION, new SessionDataSource());
1552    dataSourceMap.put(STACK_TRACE, new StackTraceDataSource());
1553    dataSourceMap.put(STYLE, new StyleDataSource());
1554    dataSourceMap.put(THEME, new ThemeDataSource());
1555    dataSourceMap.put(THEME_JS, new ThemeJavaScriptDataSource());
1556    dataSourceMap.put(REQUEST_PARAMETER, new RequestParameterDataSource());
1557// dataSourceMap.put(DISPLAY, new DisplayFieldDataSource());
1558
dataSourceMap.put(THIS, new ThisDataSource());
1559    dataSourceMap.put(ESCAPE, new EscapeDataSource());
1560    dataSourceMap.put(INT, new IntDataSource());
1561    dataSourceMap.put(BOOLEAN, new BooleanDataSource());
1562    dataSourceMap.put(BROWSER, new BrowserDataSource());
1563    dataSourceMap.put(CONSTANT, new ConstantDataSource());
1564    dataSourceMap.put(RESOURCE, new ResourceBundleDataSource());
1565    dataSourceMap.put(METHOD_BINDING, new MethodBindingDataSource());
1566    }
1567
1568    /**
1569     * Constant defining the arguments required for a Action MethodBinding.
1570     */

1571    private static Class JavaDoc[] actionArgs = {ActionEvent.class};
1572
1573    /**
1574     * The '$' character marks the beginning of a substituion in a String.
1575     */

1576    public static final String JavaDoc SUB_START = "$";
1577
1578
1579    /**
1580     * The '(' character marks the beginning of the data content of a String
1581     * substitution.
1582     */

1583    public static final String JavaDoc SUB_TYPE_DELIM = "{";
1584
1585
1586    /**
1587     * The ')' character marks the end of the data content for a String
1588     * substitution.
1589     */

1590    public static final String JavaDoc SUB_END = "}";
1591}
1592
Popular Tags