1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.struts.taglib.html;
19
20 import org.apache.commons.beanutils.BeanUtils;
21 import org.apache.struts.taglib.TagUtils;
22 import org.apache.struts.util.MessageResources;
23
24 import javax.servlet.jsp.JspException;
25
26 import java.lang.reflect.InvocationTargetException;
27
28 /***
29 * Custom tag that represents an HTML select element, associated with a bean
30 * property specified by our attributes. This tag must be nested inside a
31 * form tag.
32 *
33 * @version $Rev: 376841 $ $Date: 2004-10-16 12:38:42 -0400 (Sat, 16 Oct 2004)
34 * $
35 */
36 public class SelectTag extends BaseHandlerTag {
37 /***
38 * The message resources for this package.
39 */
40 protected static MessageResources messages =
41 MessageResources.getMessageResources(Constants.Package
42 + ".LocalStrings");
43
44
45
46 /***
47 * The actual values we will match against, calculated in doStartTag().
48 */
49 protected String[] match = null;
50
51 /***
52 * Should multiple selections be allowed. Any non-null value will trigger
53 * rendering this.
54 */
55 protected String multiple = null;
56
57 /***
58 * The name of the bean containing our underlying property.
59 */
60 protected String name = Constants.BEAN_KEY;
61
62 /***
63 * The property name we are associated with.
64 */
65 protected String property = null;
66
67 /***
68 * The saved body content of this tag.
69 */
70 protected String saveBody = null;
71
72 /***
73 * How many available options should be displayed when this element is
74 * rendered?
75 */
76 protected String size = null;
77
78 /***
79 * The value to compare with for marking an option selected.
80 */
81 protected String value = null;
82
83 public String getMultiple() {
84 return (this.multiple);
85 }
86
87 public void setMultiple(String multiple) {
88 this.multiple = multiple;
89 }
90
91 public String getName() {
92 return (this.name);
93 }
94
95 public void setName(String name) {
96 this.name = name;
97 }
98
99 public String getSize() {
100 return (this.size);
101 }
102
103 public void setSize(String size) {
104 this.size = size;
105 }
106
107
108
109 /***
110 * Does the specified value match one of those we are looking for?
111 *
112 * @param value Value to be compared.
113 */
114 public boolean isMatched(String value) {
115 if ((this.match == null) || (value == null)) {
116 return false;
117 }
118
119 for (int i = 0; i < this.match.length; i++) {
120 if (value.equals(this.match[i])) {
121 return true;
122 }
123 }
124
125 return false;
126 }
127
128 /***
129 * Return the property name.
130 */
131 public String getProperty() {
132 return (this.property);
133 }
134
135 /***
136 * Set the property name.
137 *
138 * @param property The new property name
139 */
140 public void setProperty(String property) {
141 this.property = property;
142 }
143
144 /***
145 * Return the comparison value.
146 */
147 public String getValue() {
148 return (this.value);
149 }
150
151 /***
152 * Set the comparison value.
153 *
154 * @param value The new comparison value
155 */
156 public void setValue(String value) {
157 this.value = value;
158 }
159
160
161
162 /***
163 * Render the beginning of this select tag. <p> Support for indexed
164 * property since Struts 1.1
165 *
166 * @throws JspException if a JSP exception has occurred
167 */
168 public int doStartTag() throws JspException {
169 TagUtils.getInstance().write(pageContext, renderSelectStartElement());
170
171
172 pageContext.setAttribute(Constants.SELECT_KEY, this);
173
174 this.calculateMatchValues();
175
176 return (EVAL_BODY_TAG);
177 }
178
179 /***
180 * Create an appropriate select start element based on our parameters.
181 *
182 * @throws JspException
183 * @since Struts 1.1
184 */
185 protected String renderSelectStartElement()
186 throws JspException {
187 StringBuffer results = new StringBuffer("<select");
188
189 prepareAttribute(results, "name", prepareName());
190 prepareAttribute(results, "accesskey", getAccesskey());
191
192 if (multiple != null) {
193 results.append(" multiple=\"multiple\"");
194 }
195
196 prepareAttribute(results, "size", getSize());
197 prepareAttribute(results, "tabindex", getTabindex());
198 results.append(prepareEventHandlers());
199 results.append(prepareStyles());
200 prepareOtherAttributes(results);
201 results.append(">");
202
203 return results.toString();
204 }
205
206 /***
207 * Calculate the match values we will actually be using.
208 *
209 * @throws JspException
210 */
211 private void calculateMatchValues()
212 throws JspException {
213 if (this.value != null) {
214 this.match = new String[1];
215 this.match[0] = this.value;
216 } else {
217 Object bean =
218 TagUtils.getInstance().lookup(pageContext, name, null);
219
220 if (bean == null) {
221 JspException e =
222 new JspException(messages.getMessage("getter.bean", name));
223
224 TagUtils.getInstance().saveException(pageContext, e);
225 throw e;
226 }
227
228 try {
229 this.match = BeanUtils.getArrayProperty(bean, property);
230
231 if (this.match == null) {
232 this.match = new String[0];
233 }
234 } catch (IllegalAccessException e) {
235 TagUtils.getInstance().saveException(pageContext, e);
236 throw new JspException(messages.getMessage("getter.access",
237 property, name));
238 } catch (InvocationTargetException e) {
239 Throwable t = e.getTargetException();
240
241 TagUtils.getInstance().saveException(pageContext, t);
242 throw new JspException(messages.getMessage("getter.result",
243 property, t.toString()));
244 } catch (NoSuchMethodException e) {
245 TagUtils.getInstance().saveException(pageContext, e);
246 throw new JspException(messages.getMessage("getter.method",
247 property, name));
248 }
249 }
250 }
251
252 /***
253 * Save any body content of this tag, which will generally be the
254 * option(s) representing the values displayed to the user.
255 *
256 * @throws JspException if a JSP exception has occurred
257 */
258 public int doAfterBody() throws JspException {
259 if (bodyContent != null) {
260 String value = bodyContent.getString();
261
262 if (value == null) {
263 value = "";
264 }
265
266 this.saveBody = value.trim();
267 }
268
269 return (SKIP_BODY);
270 }
271
272 /***
273 * Render the end of this form.
274 *
275 * @throws JspException if a JSP exception has occurred
276 */
277 public int doEndTag() throws JspException {
278
279 pageContext.removeAttribute(Constants.SELECT_KEY);
280
281
282 StringBuffer results = new StringBuffer();
283
284 if (saveBody != null) {
285 results.append(saveBody);
286 saveBody = null;
287 }
288
289 results.append("</select>");
290
291 TagUtils.getInstance().write(pageContext, results.toString());
292
293 return (EVAL_PAGE);
294 }
295
296 /***
297 * Prepare the name element
298 *
299 * @return The element name.
300 */
301 protected String prepareName()
302 throws JspException {
303 if (property == null) {
304 return null;
305 }
306
307
308 if (indexed) {
309 StringBuffer results = new StringBuffer();
310
311 prepareIndex(results, name);
312 results.append(property);
313
314 return results.toString();
315 }
316
317 return property;
318 }
319
320 /***
321 * Release any acquired resources.
322 */
323 public void release() {
324 super.release();
325 match = null;
326 multiple = null;
327 name = Constants.BEAN_KEY;
328 property = null;
329 saveBody = null;
330 size = null;
331 value = null;
332 }
333 }